Mercurial > 510Connectbot
changeset 438:d29cce60f393
migrate from Eclipse to Android Studio
line wrap: on
line diff
--- a/.classpath Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry kind="src" path="src"/> - <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> - <classpathentry kind="src" path="gen"/> - <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> - <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> - <classpathentry kind="output" path="bin/classes"/> -</classpath>
--- a/.hgignore Fri Jun 19 13:41:57 2015 -0700 +++ b/.hgignore Thu Dec 03 11:23:55 2015 -0800 @@ -1,8 +1,11 @@ syntax: glob .git -bin -gen +.gradle +.idea +html +app/build +app/src/main/assets/help launchpad-*.tar.gz local.properties *~
--- a/.project Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>510Connectbot</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>com.android.ide.eclipse.adt.ApkBuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>com.android.ide.eclipse.adt.AndroidNature</nature> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription>
--- a/.settings/org.eclipse.jdt.core.prefs Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,284 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.source=1.5 -org.eclipse.jdt.core.formatter.align_type_members_on_columns=false -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_assignment=0 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 -org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 -org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -org.eclipse.jdt.core.formatter.blank_lines_before_field=0 -org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 -org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -org.eclipse.jdt.core.formatter.comment.format_header=false -org.eclipse.jdt.core.formatter.comment.format_html=true -org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=true -org.eclipse.jdt.core.formatter.comment.format_source_code=true -org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true -org.eclipse.jdt.core.formatter.comment.indent_root_tags=true -org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert -org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert -org.eclipse.jdt.core.formatter.comment.line_length=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true -org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_empty_lines=false -org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true -org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert -org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert -org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false -org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false -org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false -org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false -org.eclipse.jdt.core.formatter.lineSplit=100 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 -org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=tab -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
--- a/.settings/org.eclipse.jdt.ui.prefs Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -cleanup.add_default_serial_version_id=true -cleanup.add_generated_serial_version_id=false -cleanup.add_missing_annotations=true -cleanup.add_missing_deprecated_annotations=true -cleanup.add_missing_methods=false -cleanup.add_missing_nls_tags=false -cleanup.add_missing_override_annotations=true -cleanup.add_serial_version_id=false -cleanup.always_use_blocks=false -cleanup.always_use_parentheses_in_expressions=false -cleanup.always_use_this_for_non_static_field_access=false -cleanup.always_use_this_for_non_static_method_access=false -cleanup.convert_to_enhanced_for_loop=false -cleanup.correct_indentation=true -cleanup.format_source_code=true -cleanup.format_source_code_changes_only=false -cleanup.make_local_variable_final=true -cleanup.make_parameters_final=false -cleanup.make_private_fields_final=true -cleanup.make_type_abstract_if_missing_method=false -cleanup.make_variable_declarations_final=false -cleanup.never_use_blocks=false -cleanup.never_use_parentheses_in_expressions=true -cleanup.organize_imports=true -cleanup.qualify_static_field_accesses_with_declaring_class=false -cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -cleanup.qualify_static_member_accesses_with_declaring_class=true -cleanup.qualify_static_method_accesses_with_declaring_class=false -cleanup.remove_private_constructors=true -cleanup.remove_trailing_whitespaces=true -cleanup.remove_trailing_whitespaces_all=true -cleanup.remove_trailing_whitespaces_ignore_empty=false -cleanup.remove_unnecessary_casts=true -cleanup.remove_unnecessary_nls_tags=true -cleanup.remove_unused_imports=true -cleanup.remove_unused_local_variables=false -cleanup.remove_unused_private_fields=true -cleanup.remove_unused_private_members=false -cleanup.remove_unused_private_methods=true -cleanup.remove_unused_private_types=true -cleanup.sort_members=true -cleanup.sort_members_all=true -cleanup.use_blocks=true -cleanup.use_blocks_only_for_return_and_throw=true -cleanup.use_parentheses_in_expressions=false -cleanup.use_this_for_non_static_field_access=true -cleanup.use_this_for_non_static_field_access_only_if_necessary=true -cleanup.use_this_for_non_static_method_access=true -cleanup.use_this_for_non_static_method_access_only_if_necessary=true -cleanup_profile=_ConnectBot Light Cleanup -cleanup_settings_version=2 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -formatter_profile=_ConnectBot -formatter_settings_version=12 -org.eclipse.jdt.ui.ignorelowercasenames=true -org.eclipse.jdt.ui.importorder=java;javax;org;com; -org.eclipse.jdt.ui.javadoc=true -org.eclipse.jdt.ui.ondemandthreshold=99 -org.eclipse.jdt.ui.staticondemandthreshold=99 -org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * @author ${user}\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created JavaScript files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * @author ${user}\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for vars" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Jsdoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created function stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated function stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates> -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=false -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=false -sp_cleanup.correct_indentation=false -sp_cleanup.format_source_code=false -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=false -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=true -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=false -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=true -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=false -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=false -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
--- a/AndroidManifest.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ConnectBot: simple, powerful, open-source SSH client for Android - Copyright 2007 Kenny Root, Jeffrey Sharkey - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.five_ten_sg.connectbot" - android:versionName="1.9.2-0" - android:versionCode="1920" - android:installLocation="auto"> - - <uses-sdk android:targetSdkVersion="15" android:minSdkVersion="8" /> - - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.VIBRATE" /> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.WAKE_LOCK" /> - - <permission - android:name="org.openintents.ssh.permission.ACCESS_SSH_AGENT" - android:protectionLevel="dangerous" - android:permissionGroup="android.permission-group.PERSONAL_INFO" - android:label="@string/ssh_agent_permission_label" - android:description="@string/ssh_agent_permission_desc" - android:icon="@drawable/pubkey"> - </permission> - - <uses-feature android:name="android.hardware.touchscreen" android:required="false"/> - - <supports-screens /> - - <application - android:debuggable="true" - android:icon="@drawable/icon" - android:label="@string/app_name" - android:description="@string/app_desc" - android:allowBackup="false" - android:backupAgent=".service.BackupAgent" - android:killAfterRestore="true"> - - <activity android:name=".HostListActivity" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.CREATE_SHORTCUT" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.PICK" /> - <category android:name="android.intent.category.DEFAULT" /> - <data android:scheme="tn5250" /> - <data android:scheme="ssh" /> - <data android:scheme="telnet" /> - <data android:scheme="local" /> - </intent-filter> - </activity> - - <activity android:name=".PubkeyListActivity" android:configChanges="keyboardHidden|orientation" > - <intent-filter> - <action android:name="org.openintents.ssh.agent.IDENTITY_ADMIN" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity> - <activity android:name=".GeneratePubkeyActivity" android:configChanges="keyboardHidden|orientation" /> - <activity android:name=".HostEditorActivity" android:configChanges="keyboardHidden|orientation" /> - <activity android:name=".PortForwardListActivity" android:configChanges="keyboardHidden|orientation" /> - <activity android:name=".SettingsActivity" android:configChanges="keyboardHidden|orientation" /> - <activity android:name=".WizardActivity" android:configChanges="keyboardHidden|orientation" /> - <activity android:name=".HelpActivity" android:configChanges="keyboardHidden|orientation" /> - <activity android:name=".HelpTopicActivity" android:configChanges="keyboardHidden|orientation" /> - <activity android:name=".ColorsActivity" android:configChanges="keyboardHidden|orientation" /> - <activity android:name="com.lamerman.FileDialog" android:configChanges="keyboardHidden|orientation" /> - - <service android:name="com.five_ten_sg.connectbot.service.TerminalManager" - android:configChanges="keyboardHidden|orientation" - android:description="@string/service_desc" /> - - <service android:name="com.five_ten_sg.connectbot.service.AuthAgentService" - android:description="@string/auth_agent_service_desc" - android:permission="org.openintents.ssh.permission.ACCESS_SSH_AGENT"> - <intent-filter> - <action android:name="org.openintents.ssh.BIND_SSH_AGENT_SERVICE" /> - </intent-filter> - </service> - - <activity android:name=".ConsoleActivity" android:configChanges="keyboardHidden|orientation" - android:theme="@style/NoTitle" android:windowSoftInputMode="stateAlwaysVisible|adjustResize" - android:launchMode="singleTop" android:hardwareAccelerated="false"> - <intent-filter> - <action android:name="android.intent.action.VIEW" /> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - <data android:scheme="tn5250" /> - <data android:scheme="ssh" /> - <data android:scheme="telnet" /> - <data android:scheme="local" /> - <!-- format: ssh://user@host:port/#nickname --> - <!-- format: telnet://host:port/#nickname --> - <!-- format: local:// --> - </intent-filter> - </activity> - - <meta-data android:name="com.google.android.backup.api_key" - android:value="AEdPqrEAAAAIDlFz9nSUr2g0gSytW0t2cNnYAGHDkptlVohsBA" /> - - </application> -</manifest>
--- a/Makefile Fri Jun 19 13:41:57 2015 -0700 +++ b/Makefile Thu Dec 03 11:23:55 2015 -0800 @@ -1,13 +1,22 @@ #mc40 is "On Device Storage" #tc55 is "Internal Storage" -style=release -dest=/run/user/1000/gvfs/mtp*/*torage/Download -apk='bin/510Connectbot-$(style).apk' +style:=release +dest:=/run/user/1000/gvfs/mtp*/*torage/Download +apk:='app/build/outputs/apk/510Connectbot-$(style).apk' +ver:=$(shell grep versionName app/src/main/AndroidManifest.xml | cut -d'"' -f2) +id:=$(shell hg id --id) +da:=$(shell date +%Y-%m-%d) +version:=\ +<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ +<resources>\n\ + <string name=\"msg_version\" translatable=\"false\">510Connectbot $(ver) ($(id) $(da))</string>\n\ +</resources>\n + ifeq ($(style),release) - debuggable=false + task=assembleRelease else - debuggable=true + task=assembleDebug endif @@ -16,11 +25,12 @@ make builder builder: prep - sed -i -e 's/android:debuggable=".*"/android:debuggable="$(debuggable)"/g' AndroidManifest.xml - rm -rf gen bin - ndk-build clean; V=1 ndk-build - android update project -p . -t android-16 - ant $(style) + rm -rf app/build/* + echo -e "$(version)" >app/src/main/res/values/version.xml + cat app/src/main/res/values/version.xml + ./gradlew $(task) + mv app/build/outputs/apk/app-arm-$(style).apk $(apk) + ls -al app/build/outputs/apk prep: (cd help; make) @@ -38,19 +48,19 @@ buildicon: convert base.510.icon.png -background white -resize 500x500 -extent 1024x500 google.play.store/feature.510.icon.png - cp -a base.510.icon.png res/drawable-xxxhdpi/icon.png - convert base.510.icon.png -resize 144x144 res/drawable-xxhdpi/icon.png - convert base.510.icon.png -resize 96x96 res/drawable-xhdpi/icon.png - convert base.510.icon.png -resize 72x72 res/drawable-hdpi/icon.png - convert base.510.icon.png -resize 48x48 res/drawable-mdpi/icon.png - convert base.510.icon.png -resize 36x36 res/drawable-ldpi/icon.png + cp -a base.510.icon.png app/src/main/res/drawable-xxxhdpi/icon.png + convert base.510.icon.png -resize 144x144 app/src/main/res/drawable-xxhdpi/icon.png + convert base.510.icon.png -resize 96x96 app/src/main/res/drawable-xhdpi/icon.png + convert base.510.icon.png -resize 72x72 app/src/main/res/drawable-hdpi/icon.png + convert base.510.icon.png -resize 48x48 app/src/main/res/drawable-mdpi/icon.png + convert base.510.icon.png -resize 36x36 app/src/main/res/drawable-ldpi/icon.png - convert res/drawable-xxxhdpi/icon.png -resize 50% -colorspace Gray res/drawable-xxxhdpi/notification_icon.png - convert res/drawable-xxhdpi/icon.png -resize 50% -colorspace Gray res/drawable-xxhdpi/notification_icon.png - convert res/drawable-xhdpi/icon.png -resize 50% -colorspace Gray res/drawable-xhdpi/notification_icon.png - convert res/drawable-hdpi/icon.png -resize 50% -colorspace Gray res/drawable-hdpi/notification_icon.png - convert res/drawable-mdpi/icon.png -resize 50% -colorspace Gray res/drawable-mdpi/notification_icon.png - convert res/drawable-ldpi/icon.png -resize 50% -colorspace Gray res/drawable-ldpi/notification_icon.png + convert app/src/main/res/drawable-xxxhdpi/icon.png -resize 50% -colorspace Gray app/src/main/res/drawable-xxxhdpi/notification_icon.png + convert app/src/main/res/drawable-xxhdpi/icon.png -resize 50% -colorspace Gray app/src/main/res/drawable-xxhdpi/notification_icon.png + convert app/src/main/res/drawable-xhdpi/icon.png -resize 50% -colorspace Gray app/src/main/res/drawable-xhdpi/notification_icon.png + convert app/src/main/res/drawable-hdpi/icon.png -resize 50% -colorspace Gray app/src/main/res/drawable-hdpi/notification_icon.png + convert app/src/main/res/drawable-mdpi/icon.png -resize 50% -colorspace Gray app/src/main/res/drawable-mdpi/notification_icon.png + convert app/src/main/res/drawable-ldpi/icon.png -resize 50% -colorspace Gray app/src/main/res/drawable-ldpi/notification_icon.png indentc: indent --line-length100 \
--- a/ant.properties Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -# This file is used to override default values used by the Ant build system. -# -# This file must be checked in Version Control Systems, as it is -# integral to the build system of your project. - -# This file is only used by the Ant script. - -# You can use this to override default values such as -# 'source.dir' for the location of your java source folder and -# 'out.dir' for the location of your output folder. - -# You can also use it define how the release builds are signed by declaring -# the following properties: -# 'key.store' for the location of your keystore and -# 'key.alias' for the name of the key to use. -# The password will be asked during the build when you use the 'release' target. - -source.dir=src -out.dir=bin -key.store=510Connectbot.keystore -key.alias=510Connectbot
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/build.gradle Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,75 @@ +tasks.whenTaskAdded { task -> + if (task.name.contains("lint")) { + task.enabled = false + } +} + +apply plugin: 'com.android.model.application' + +model { + def signConf + + android { + compileSdkVersion = 16 + buildToolsVersion = "23.0.2" + + defaultConfig.with { + applicationId = "com.five_ten_sg.connectbot" + minSdkVersion.apiLevel = 8 + targetSdkVersion.apiLevel = 15 + } + } + + compileOptions.with { + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + } + + android.ndk { + moduleName = "com_google_ase_Exec" + cppFlags.add("-Werror") + ldLibs.add("log") + } + + android.sources { + main { + jni { + source { + srcDir "Exec" + } + } + } + } + + android.signingConfigs { + create("signed") { + storeFile = file("../510Connectbot.keystore") + storePassword = new String(System.console().readPassword("\n\$ Enter keystore password: ")) + storeType = "jks" + keyAlias = "510Connectbot" + keyPassword = new String(System.console().readPassword("\n\$ Enter key password: ")) + signConf = it + } + } + + android.buildTypes { + release { + minifyEnabled = false + signingConfig = signConf + //proguardFiles.add(file('proguard-rules.txt')) + } + debug { + debuggable = true + } + } + + android.productFlavors { + create("arm") { + ndk.abiFilters.add("armeabi") + } + create("x86") { + ndk.abiFilters.add("x86") + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/lint.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<lint> + <issue id="MissingTranslation" severity="warning" /> + <issue id="NewApi" severity="warning" /> +</lint> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/AndroidManifest.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ConnectBot: simple, powerful, open-source SSH client for Android + Copyright 2007 Kenny Root, Jeffrey Sharkey + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.five_ten_sg.connectbot" + android:versionName="1.9.2-0" + android:versionCode="1920" + android:installLocation="auto"> + + <uses-sdk android:targetSdkVersion="15" android:minSdkVersion="8" /> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.VIBRATE" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + + <permission + android:name="org.openintents.ssh.permission.ACCESS_SSH_AGENT" + android:protectionLevel="dangerous" + android:permissionGroup="android.permission-group.PERSONAL_INFO" + android:label="@string/ssh_agent_permission_label" + android:description="@string/ssh_agent_permission_desc" + android:icon="@drawable/pubkey"> + </permission> + + <uses-feature android:name="android.hardware.touchscreen" android:required="false"/> + + <supports-screens /> + + <application + android:debuggable="true" + android:icon="@drawable/icon" + android:label="@string/app_name" + android:description="@string/app_desc" + android:allowBackup="false" + android:backupAgent=".service.BackupAgent" + android:killAfterRestore="true"> + + <activity android:name=".HostListActivity" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.CREATE_SHORTCUT" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.PICK" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:scheme="tn5250" /> + <data android:scheme="ssh" /> + <data android:scheme="telnet" /> + <data android:scheme="local" /> + </intent-filter> + </activity> + + <activity android:name=".PubkeyListActivity" android:configChanges="keyboardHidden|orientation" > + <intent-filter> + <action android:name="org.openintents.ssh.agent.IDENTITY_ADMIN" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity> + <activity android:name=".GeneratePubkeyActivity" android:configChanges="keyboardHidden|orientation" /> + <activity android:name=".HostEditorActivity" android:configChanges="keyboardHidden|orientation" /> + <activity android:name=".PortForwardListActivity" android:configChanges="keyboardHidden|orientation" /> + <activity android:name=".SettingsActivity" android:configChanges="keyboardHidden|orientation" /> + <activity android:name=".WizardActivity" android:configChanges="keyboardHidden|orientation" /> + <activity android:name=".HelpActivity" android:configChanges="keyboardHidden|orientation" /> + <activity android:name=".HelpTopicActivity" android:configChanges="keyboardHidden|orientation" /> + <activity android:name=".ColorsActivity" android:configChanges="keyboardHidden|orientation" /> + <activity android:name="com.lamerman.FileDialog" android:configChanges="keyboardHidden|orientation" /> + + <service android:name="com.five_ten_sg.connectbot.service.TerminalManager" + android:configChanges="keyboardHidden|orientation" + android:description="@string/service_desc" /> + + <service android:name="com.five_ten_sg.connectbot.service.AuthAgentService" + android:description="@string/auth_agent_service_desc" + android:permission="org.openintents.ssh.permission.ACCESS_SSH_AGENT"> + <intent-filter> + <action android:name="org.openintents.ssh.BIND_SSH_AGENT_SERVICE" /> + </intent-filter> + </service> + + <activity android:name=".ConsoleActivity" android:configChanges="keyboardHidden|orientation" + android:theme="@style/NoTitle" android:windowSoftInputMode="stateAlwaysVisible|adjustResize" + android:launchMode="singleTop" android:hardwareAccelerated="false"> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + <data android:scheme="tn5250" /> + <data android:scheme="ssh" /> + <data android:scheme="telnet" /> + <data android:scheme="local" /> + <!-- format: ssh://user@host:port/#nickname --> + <!-- format: telnet://host:port/#nickname --> + <!-- format: local:// --> + </intent-filter> + </activity> + + <meta-data android:name="com.google.android.backup.api_key" + android:value="AEdPqrEAAAAIDlFz9nSUr2g0gSytW0t2cNnYAGHDkptlVohsBA" /> + + </application> +</manifest>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/AbstractSFTPClient.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,690 @@ +package ch.ethz.ssh2; + +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.SocketException; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.util.HashMap; +import java.util.Map; + +import ch.ethz.ssh2.channel.Channel; +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.packets.TypesWriter; +import ch.ethz.ssh2.sftp.AttribFlags; +import ch.ethz.ssh2.sftp.ErrorCodes; +import ch.ethz.ssh2.sftp.Packet; +import ch.ethz.ssh2.util.StringEncoder; + +/** + * @version $Id: AbstractSFTPClient.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public abstract class AbstractSFTPClient implements SFTPClient { + + private static final Logger log = Logger.getLogger(SFTPv3Client.class); + + private Session sess; + + private InputStream is; + private OutputStream os; + + private int next_request_id = 1000; + + private String charset; + + /** + * Parallel read requests maximum size. + */ + private static final int DEFAULT_MAX_PARALLELISM = 64; + + /** + * Parallel read requests. + */ + private int parallelism = DEFAULT_MAX_PARALLELISM; + + public void setRequestParallelism(int parallelism) { + this.parallelism = Math.min(parallelism, DEFAULT_MAX_PARALLELISM); + } + + /** + * Mapping request ID to request. + */ + private Map<Integer, OutstandingReadRequest> pendingReadQueue + = new HashMap<Integer, OutstandingReadRequest>(); + + /** + * Mapping request ID to request. + */ + private Map<Integer, OutstandingStatusRequest> pendingStatusQueue + = new HashMap<Integer, OutstandingStatusRequest>(); + + private PacketListener listener; + + protected AbstractSFTPClient(final Connection conn, final int version, final PacketListener listener) throws IOException { + this.listener = listener; + log.debug("Opening session and starting SFTP subsystem."); + sess = conn.openSession(); + sess.startSubSystem("sftp"); + is = sess.getStdout(); + os = new BufferedOutputStream(sess.getStdin(), 2048); + init(version); + } + + private void init(final int client_version) throws IOException { + // Send SSH_FXP_INIT with client version + TypesWriter tw = new TypesWriter(); + tw.writeUINT32(client_version); + sendMessage(Packet.SSH_FXP_INIT, 0, tw.getBytes()); + /* Receive SSH_FXP_VERSION */ + log.debug("Waiting for SSH_FXP_VERSION..."); + TypesReader tr = new TypesReader(receiveMessage(34000)); /* Should be enough for any reasonable server */ + int t = tr.readByte(); + listener.read(Packet.forName(t)); + + if (t != Packet.SSH_FXP_VERSION) { + log.warning(String.format("The server did not send a SSH_FXP_VERSION but %d", t)); + throw new PacketTypeException(t); + } + + final int protocol_version = tr.readUINT32(); + log.debug("SSH_FXP_VERSION: protocol_version = " + protocol_version); + + if (protocol_version != client_version) { + throw new IOException(String.format("Server protocol version %d does not match %d", + protocol_version, client_version)); + } + + // Both parties should from then on adhere to particular version of the protocol + + // Read and save extensions (if any) for later use + while (tr.remain() != 0) { + String name = tr.readString(); + listener.read(name); + byte[] value = tr.readByteString(); + log.debug(String.format("SSH_FXP_VERSION: extension: %s = '%s'", name, StringEncoder.GetString(value))); + } + } + + /** + * Queries the channel state + * + * @return True if the underlying session is in open state + */ + public boolean isConnected() { + return sess.getState() == Channel.STATE_OPEN; + } + + /** + * Close this SFTP session. NEVER forget to call this method to free up + * resources - even if you got an exception from one of the other methods. + * Sometimes these other methods may throw an exception, saying that the + * underlying channel is closed (this can happen, e.g., if the other server + * sent a close message.) However, as long as you have not called the + * <code>close()</code> method, you are likely wasting resources. + */ + public void close() { + sess.close(); + } + + /** + * Set the charset used to convert between Java Unicode Strings and byte encodings + * used by the server for paths and file names. + * + * @param charset the name of the charset to be used or <code>null</code> to use UTF-8. + * @throws java.io.IOException + * @see #getCharset() + */ + public void setCharset(String charset) throws IOException { + if (charset == null) { + this.charset = null; + return; + } + + try { + Charset.forName(charset); + } + catch (UnsupportedCharsetException e) { + throw new IOException("This charset is not supported", e); + } + + this.charset = charset; + } + + /** + * The currently used charset for filename encoding/decoding. + * + * @return The name of the charset (<code>null</code> if UTF-8 is used). + * @see #setCharset(String) + */ + public String getCharset() { + return charset; + } + + public abstract SFTPFileHandle openFile(String fileName, int flags, SFTPFileAttributes attr) throws IOException; + + public void mkdir(String dirName, int posixPermissions) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(dirName, this.getCharset()); + tw.writeUINT32(AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS); + tw.writeUINT32(posixPermissions); + sendMessage(Packet.SSH_FXP_MKDIR, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + public void rm(String fileName) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(fileName, this.getCharset()); + sendMessage(Packet.SSH_FXP_REMOVE, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + public void rmdir(String dirName) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(dirName, this.getCharset()); + sendMessage(Packet.SSH_FXP_RMDIR, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + public void mv(String oldPath, String newPath) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(oldPath, this.getCharset()); + tw.writeString(newPath, this.getCharset()); + sendMessage(Packet.SSH_FXP_RENAME, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + public String readLink(String path) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(path, charset); + sendMessage(Packet.SSH_FXP_READLINK, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_NAME) { + int count = tr.readUINT32(); + + if (count != 1) { + throw new PacketTypeException(t); + } + + return tr.readString(charset); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + public void setstat(String path, SFTPFileAttributes attr) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(path, charset); + tw.writeBytes(attr.toBytes()); + sendMessage(Packet.SSH_FXP_SETSTAT, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + public void fsetstat(SFTPFileHandle handle, SFTPFileAttributes attr) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(handle.getHandle(), 0, handle.getHandle().length); + tw.writeBytes(attr.toBytes()); + sendMessage(Packet.SSH_FXP_FSETSTAT, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + public void createSymlink(String src, String target) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(src, charset); + tw.writeString(target, charset); + sendMessage(Packet.SSH_FXP_SYMLINK, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + public void createHardlink(String src, String target) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString("hardlink@openssh.com", charset); + tw.writeString(target, charset); + tw.writeString(src, charset); + sendMessage(Packet.SSH_FXP_EXTENDED, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + public String canonicalPath(String path) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(path, charset); + sendMessage(Packet.SSH_FXP_REALPATH, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_NAME) { + int count = tr.readUINT32(); + + if (count != 1) { + throw new PacketFormatException("The server sent an invalid SSH_FXP_NAME packet."); + } + + final String name = tr.readString(charset); + listener.read(name); + return name; + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + private void sendMessage(int type, int requestId, byte[] msg, int off, int len) throws IOException { + if (log.isDebugEnabled()) { + log.debug(String.format("Send message of type %d with request id %d", type, requestId)); + } + + listener.write(Packet.forName(type)); + int msglen = len + 1; + + if (type != Packet.SSH_FXP_INIT) { + msglen += 4; + } + + os.write(msglen >> 24); + os.write(msglen >> 16); + os.write(msglen >> 8); + os.write(msglen); + os.write(type); + + if (type != Packet.SSH_FXP_INIT) { + os.write(requestId >> 24); + os.write(requestId >> 16); + os.write(requestId >> 8); + os.write(requestId); + } + + os.write(msg, off, len); + os.flush(); + } + + protected void sendMessage(int type, int requestId, byte[] msg) throws IOException { + sendMessage(type, requestId, msg, 0, msg.length); + } + + private void readBytes(byte[] buff, int pos, int len) throws IOException { + while (len > 0) { + int count = is.read(buff, pos, len); + + if (count < 0) { + throw new SocketException("Unexpected end of stream."); + } + + len -= count; + pos += count; + } + } + + /** + * Read a message and guarantee that the <b>contents</b> is not larger than + * <code>maxlen</code> bytes. + * <p/> + * Note: receiveMessage(34000) actually means that the message may be up to 34004 + * bytes (the length attribute preceding the contents is 4 bytes). + * + * @param maxlen + * @return the message contents + * @throws IOException + */ + protected byte[] receiveMessage(int maxlen) throws IOException { + byte[] msglen = new byte[4]; + readBytes(msglen, 0, 4); + int len = (((msglen[0] & 0xff) << 24) | ((msglen[1] & 0xff) << 16) | ((msglen[2] & 0xff) << 8) | (msglen[3] & 0xff)); + + if ((len > maxlen) || (len <= 0)) { + throw new PacketFormatException(String.format("Illegal SFTP packet length %d", len)); + } + + byte[] msg = new byte[len]; + readBytes(msg, 0, len); + return msg; + } + + protected int generateNextRequestID() { + synchronized (this) { + return next_request_id++; + } + } + + protected void closeHandle(byte[] handle) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(handle, 0, handle.length); + sendMessage(Packet.SSH_FXP_CLOSE, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + private void readStatus() throws IOException { + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + // Search the pending queue + OutstandingStatusRequest status = pendingStatusQueue.remove(tr.readUINT32()); + + if (null == status) { + throw new RequestMismatchException(); + } + + // Evaluate the answer + if (t == Packet.SSH_FXP_STATUS) { + // In any case, stop sending more packets + int code = tr.readUINT32(); + + if (log.isDebugEnabled()) { + String[] desc = ErrorCodes.getDescription(code); + log.debug("Got SSH_FXP_STATUS (" + status.req_id + ") (" + ((desc != null) ? desc[0] : "UNKNOWN") + ")"); + } + + if (code == ErrorCodes.SSH_FX_OK) { + return; + } + + String msg = tr.readString(); + listener.read(msg); + throw new SFTPException(msg, code); + } + + throw new PacketTypeException(t); + } + + private void readPendingReadStatus() throws IOException { + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + // Search the pending queue + OutstandingReadRequest status = pendingReadQueue.remove(tr.readUINT32()); + + if (null == status) { + throw new RequestMismatchException(); + } + + // Evaluate the answer + if (t == Packet.SSH_FXP_STATUS) { + // In any case, stop sending more packets + int code = tr.readUINT32(); + + if (log.isDebugEnabled()) { + String[] desc = ErrorCodes.getDescription(code); + log.debug("Got SSH_FXP_STATUS (" + status.req_id + ") (" + ((desc != null) ? desc[0] : "UNKNOWN") + ")"); + } + + if (code == ErrorCodes.SSH_FX_OK) { + return; + } + + if (code == ErrorCodes.SSH_FX_EOF) { + return; + } + + String msg = tr.readString(); + listener.read(msg); + throw new SFTPException(msg, code); + } + + throw new PacketTypeException(t); + } + + protected void expectStatusOKMessage(int id) throws IOException { + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != id) { + throw new RequestMismatchException(); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + + if (errorCode == ErrorCodes.SSH_FX_OK) { + return; + } + + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + public void closeFile(SFTPFileHandle handle) throws IOException { + while (!pendingReadQueue.isEmpty()) { + this.readPendingReadStatus(); + } + + while (!pendingStatusQueue.isEmpty()) { + this.readStatus(); + } + + closeHandle(handle.getHandle()); + } + + public int read(SFTPFileHandle handle, long fileOffset, byte[] dst, int dstoff, int len) throws IOException { + boolean errorOccured = false; + int remaining = len * parallelism; + //int clientOffset = dstoff; + long serverOffset = fileOffset; + + for (OutstandingReadRequest r : pendingReadQueue.values()) { + // Server offset should take pending requests into account. + serverOffset += r.len; + } + + while (true) { + // Stop if there was an error and no outstanding request + if ((pendingReadQueue.size() == 0) && errorOccured) { + break; + } + + // Send as many requests as we are allowed to + while (pendingReadQueue.size() < parallelism) { + if (errorOccured) { + break; + } + + // Send the next read request + OutstandingReadRequest req = new OutstandingReadRequest(); + req.req_id = generateNextRequestID(); + req.serverOffset = serverOffset; + req.len = (remaining > len) ? len : remaining; + req.buffer = dst; + req.dstOffset = dstoff; + serverOffset += req.len; + //clientOffset += req.len; + remaining -= req.len; + sendReadRequest(req.req_id, handle, req.serverOffset, req.len); + pendingReadQueue.put(req.req_id, req); + } + + if (pendingReadQueue.size() == 0) { + break; + } + + // Receive a single answer + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + // Search the pending queue + OutstandingReadRequest req = pendingReadQueue.remove(tr.readUINT32()); + + if (null == req) { + throw new RequestMismatchException(); + } + + // Evaluate the answer + if (t == Packet.SSH_FXP_STATUS) { + /* In any case, stop sending more packets */ + int code = tr.readUINT32(); + String msg = tr.readString(); + listener.read(msg); + + if (log.isDebugEnabled()) { + String[] desc = ErrorCodes.getDescription(code); + log.debug("Got SSH_FXP_STATUS (" + req.req_id + ") (" + ((desc != null) ? desc[0] : "UNKNOWN") + ")"); + } + + // Flag to read all pending requests but don't send any more. + errorOccured = true; + + if (pendingReadQueue.isEmpty()) { + if (ErrorCodes.SSH_FX_EOF == code) { + return -1; + } + + throw new SFTPException(msg, code); + } + } + else if (t == Packet.SSH_FXP_DATA) { + // OK, collect data + int readLen = tr.readUINT32(); + + if ((readLen < 0) || (readLen > req.len)) { + throw new PacketFormatException("The server sent an invalid length field in a SSH_FXP_DATA packet."); + } + + if (log.isDebugEnabled()) { + log.debug("Got SSH_FXP_DATA (" + req.req_id + ") " + req.serverOffset + "/" + readLen + + " (requested: " + req.len + ")"); + } + + // Read bytes into buffer + tr.readBytes(req.buffer, req.dstOffset, readLen); + + if (readLen < req.len) { + /* Send this request packet again to request the remaing data in this slot. */ + req.req_id = generateNextRequestID(); + req.serverOffset += readLen; + req.len -= readLen; + log.debug("Requesting again: " + req.serverOffset + "/" + req.len); + sendReadRequest(req.req_id, handle, req.serverOffset, req.len); + pendingReadQueue.put(req.req_id, req); + } + + return readLen; + } + else { + throw new PacketTypeException(t); + } + } + + // Should never reach here. + throw new SFTPException("No EOF reached", -1); + } + + private void sendReadRequest(int id, SFTPFileHandle handle, long offset, int len) throws IOException { + TypesWriter tw = new TypesWriter(); + tw.writeString(handle.getHandle(), 0, handle.getHandle().length); + tw.writeUINT64(offset); + tw.writeUINT32(len); + sendMessage(Packet.SSH_FXP_READ, id, tw.getBytes()); + } + + public void write(SFTPFileHandle handle, long fileOffset, byte[] src, int srcoff, int len) throws IOException { + while (len > 0) { + int writeRequestLen = len; + + if (writeRequestLen > 32768) { + writeRequestLen = 32768; + } + + // Send the next write request + OutstandingStatusRequest req = new OutstandingStatusRequest(); + req.req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(handle.getHandle(), 0, handle.getHandle().length); + tw.writeUINT64(fileOffset); + tw.writeString(src, srcoff, writeRequestLen); + sendMessage(Packet.SSH_FXP_WRITE, req.req_id, tw.getBytes()); + pendingStatusQueue.put(req.req_id, req); + + // Only read next status if parallelism reached + while (pendingStatusQueue.size() >= parallelism) { + this.readStatus(); + } + + fileOffset += writeRequestLen; + srcoff += writeRequestLen; + len -= writeRequestLen; + } + } + + + /** + * A read is divided into multiple requests sent sequentially before + * reading any status from the server + */ + private static class OutstandingReadRequest { + int req_id; + /** + * Read offset to request on server starting at the file offset for the first request. + */ + long serverOffset; + /** + * Length of requested data + */ + int len; + /** + * Offset in destination buffer + */ + int dstOffset; + /** + * Temporary buffer + */ + byte[] buffer; + } + + /** + * A read is divided into multiple requests sent sequentially before + * reading any status from the server + */ + private static final class OutstandingStatusRequest { + int req_id; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/AuthAgentCallback.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,64 @@ +package ch.ethz.ssh2; + +import java.security.KeyPair; +import java.util.Map; + +/** + * AuthAgentCallback. + * + * @author Kenny Root + * @version $Id$ + */ +public interface AuthAgentCallback { + + /** + * @return array of blobs containing the OpenSSH-format encoded public keys + */ + Map<String, byte[]> retrieveIdentities(); + + /** + * @param pair A <code>RSAPrivateKey</code> or <code>DSAPrivateKey</code> or <code>ECPrivateKey</code> + * containing a DSA or RSA or EC private key of + * the user in standard java key format. + * @param comment comment associated with this key + * @param confirmUse whether to prompt before using this key + * @param lifetime lifetime in seconds for key to be remembered + * @return success or failure + */ + boolean addIdentity(KeyPair pair, String comment, boolean confirmUse, int lifetime); + + /** + * @param publicKey byte blob containing the OpenSSH-format encoded public key + * @return success or failure + */ + boolean removeIdentity(byte[] publicKey); + + /** + * @return success or failure + */ + boolean removeAllIdentities(); + + /** + * @param publicKey byte blob containing the OpenSSH-format encoded public key + * @return A <code>RSAPrivateKey</code> or <code>DSAPrivateKey</code> + * containing a DSA or RSA or EC private key of + * the user in standard java key format. + */ + KeyPair getKeyPair(byte[] publicKey); + + /** + * @return + */ + boolean isAgentLocked(); + + /** + * @param lockPassphrase + */ + boolean setAgentLock(String lockPassphrase); + + /** + * @param unlockPassphrase + * @return + */ + boolean requestAgentUnlock(String unlockPassphrase); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/AuthenticationResult.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,21 @@ + +package ch.ethz.ssh2; + +public enum AuthenticationResult { + + /** + * + */ + SUCCESS, + /** + * The authentication request to which this is a response was successful, however, more + * authentication requests are needed (multi-method authentication sequence). + * + * @see ServerAuthenticationCallback#getRemainingAuthMethods(ServerConnection) + */ + PARTIAL_SUCCESS, + /** + * The server rejected the authentication request. + */ + FAILURE +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ChannelCondition.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * Contains constants that can be used to specify what conditions to wait for on + * a SSH-2 channel (e.g., represented by a {@link Session}). + * + * @see Session#waitForCondition(int, long) + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public abstract interface ChannelCondition { + /** + * A timeout has occurred, none of your requested conditions is fulfilled. + * However, other conditions may be true - therefore, NEVER use the "==" + * operator to test for this (or any other) condition. Always use + * something like <code>((cond & ChannelCondition.CLOSED) != 0)</code>. + */ + public static final int TIMEOUT = 1; + + /** + * The underlying SSH-2 channel, however not necessarily the whole connection, + * has been closed. This implies <code>EOF</code>. Note that there may still + * be unread stdout or stderr data in the local window, i.e, <code>STDOUT_DATA</code> + * or/and <code>STDERR_DATA</code> may be set at the same time. + */ + public static final int CLOSED = 2; + + /** + * There is stdout data available that is ready to be consumed. + */ + public static final int STDOUT_DATA = 4; + + /** + * There is stderr data available that is ready to be consumed. + */ + public static final int STDERR_DATA = 8; + + /** + * EOF on has been reached, no more _new_ stdout or stderr data will arrive + * from the remote server. However, there may be unread stdout or stderr + * data, i.e, <code>STDOUT_DATA</code> or/and <code>STDERR_DATA</code> + * may be set at the same time. + */ + public static final int EOF = 16; + + /** + * The exit status of the remote process is available. + * Some servers never send the exist status, or occasionally "forget" to do so. + */ + public static final int EXIT_STATUS = 32; + + /** + * The exit signal of the remote process is available. + */ + public static final int EXIT_SIGNAL = 64; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/Connection.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1452 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2; + +import java.io.CharArrayWriter; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import ch.ethz.ssh2.auth.AgentProxy; +import ch.ethz.ssh2.auth.AuthenticationManager; +import ch.ethz.ssh2.channel.ChannelManager; +import ch.ethz.ssh2.compression.CompressionFactory; +import ch.ethz.ssh2.crypto.CryptoWishList; +import ch.ethz.ssh2.crypto.SecureRandomFix; +import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; +import ch.ethz.ssh2.crypto.digest.MAC; +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.PacketIgnore; +import ch.ethz.ssh2.transport.ClientTransportManager; +import ch.ethz.ssh2.transport.HTTPProxyClientTransportManager; +import ch.ethz.ssh2.transport.KexManager; +import ch.ethz.ssh2.util.TimeoutService.TimeoutToken; +import ch.ethz.ssh2.util.TimeoutService; + +/** + * A <code>Connection</code> is used to establish an encrypted TCP/IP + * connection to a SSH-2 server. + * <p/> + * Typically, one + * <ol> + * <li>creates a {@link #Connection(String) Connection} object.</li> + * <li>calls the {@link #connect() connect()} method.</li> + * <li>calls some of the authentication methods (e.g., {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}).</li> + * <li>calls one or several times the {@link #openSession() openSession()} method.</li> + * <li>finally, one must close the connection and release resources with the {@link #close() close()} method.</li> + * </ol> + * + * @author Christian Plattner + * @version $Id: Connection.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ + +public class Connection { + protected static final Logger log = Logger.getLogger(Connection.class); + + /** + * The identifier presented to the SSH-2 server. This is the same + * as the "softwareversion" defined in RFC 4253. + * <p/> + * <b>NOTE: As per the RFC, the "softwareversion" string MUST consist of printable + * US-ASCII characters, with the exception of whitespace characters and the minus sign (-).</b> + */ + private String softwareversion + = String.format("Ganymed_%s", Version.getSpecification()); + + /* Will be used to generate all random data needed for the current connection. + * Note: SecureRandom.nextBytes() is thread safe. + */ + + private SecureRandomFix generator; + + /** + * Unless you know what you are doing, you will never need this. + * + * @return The list of supported cipher algorithms by this implementation. + */ + + public static synchronized String[] getAvailableCiphers() { + return BlockCipherFactory.getDefaultCipherList(); + } + + /** + * Unless you know what you are doing, you will never need this. + * + * @return The list of supported MAC algorthims by this implementation. + */ + + public static synchronized String[] getAvailableMACs() { + return MAC.getMacList(); + } + + /** + * Unless you know what you are doing, you will never need this. + * + * @return The list of supported server host key algorthims by this implementation. + */ + + public static synchronized String[] getAvailableServerHostKeyAlgorithms() { + return KexManager.getDefaultServerHostkeyAlgorithmList(); + } + + private AuthenticationManager am; + + private boolean authenticated; + private ChannelManager cm; + + private CryptoWishList cryptoWishList + = new CryptoWishList(); + + private DHGexParameters dhgexpara + = new DHGexParameters(); + + private final String hostname; + + private final int port; + + private ClientTransportManager tm; + + private boolean tcpNoDelay = false; + + private HTTPProxyData proxy; + + private List<ConnectionMonitor> connectionMonitors + = new ArrayList<ConnectionMonitor>(); + + /** + * Prepares a fresh <code>Connection</code> object which can then be used + * to establish a connection to the specified SSH-2 server. + * <p/> + * Same as {@link #Connection(String, int) Connection(hostname, 22)}. + * + * @param hostname the hostname of the SSH-2 server. + */ + public Connection(String hostname) { + this(hostname, 22); + } + + /** + * Prepares a fresh <code>Connection</code> object which can then be used + * to establish a connection to the specified SSH-2 server. + * + * @param hostname the host where we later want to connect to. + * @param port port on the server, normally 22. + */ + public Connection(String hostname, int port) { + this.hostname = hostname; + this.port = port; + } + + /** + * Prepares a fresh <code>Connection</code> object which can then be used + * to establish a connection to the specified SSH-2 server. + * + * @param hostname the host where we later want to connect to. + * @param port port on the server, normally 22. + * @param softwareversion Allows you to set a custom "softwareversion" string as defined in RFC 4253. + * <b>NOTE: As per the RFC, the "softwareversion" string MUST consist of printable + * US-ASCII characters, with the exception of whitespace characters and the minus sign (-).</b> + */ + public Connection(String hostname, int port, String softwareversion) { + this.hostname = hostname; + this.port = port; + this.softwareversion = softwareversion; + } + + public Connection(String hostname, int port, final HTTPProxyData proxy) { + this.hostname = hostname; + this.port = port; + this.proxy = proxy; + } + + public Connection(String hostname, int port, String softwareversion, final HTTPProxyData proxy) { + this.hostname = hostname; + this.port = port; + this.softwareversion = softwareversion; + this.proxy = proxy; + } + + /** + * After a successful connect, one has to authenticate oneself. This method + * is based on DSA (it uses DSA to sign a challenge sent by the server). + * <p/> + * If the authentication phase is complete, <code>true</code> will be + * returned. If the server does not accept the request (or if further + * authentication steps are needed), <code>false</code> is returned and + * one can retry either by using this or any other authentication method + * (use the <code>getRemainingAuthMethods</code> method to get a list of + * the remaining possible methods). + * + * @param user A <code>String</code> holding the username. + * @param pem A <code>String</code> containing the DSA private key of the + * user in OpenSSH key format (PEM, you can't miss the + * "-----BEGIN DSA PRIVATE KEY-----" tag). The string may contain + * linefeeds. + * @param password If the PEM string is 3DES encrypted ("DES-EDE3-CBC"), then you + * must specify the password. Otherwise, this argument will be + * ignored and can be set to <code>null</code>. + * @return whether the connection is now authenticated. + * @throws IOException + * @deprecated You should use one of the {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()} + * methods, this method is just a wrapper for it and will + * disappear in future builds. + */ + @Deprecated + + public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException { + if (tm == null) { + throw new IllegalStateException("Connection is not established!"); + } + + if (authenticated) { + throw new IllegalStateException("Connection is already authenticated!"); + } + + if (am == null) { + am = new AuthenticationManager(tm); + } + + if (cm == null) { + cm = new ChannelManager(tm); + } + + if (user == null) { + throw new IllegalArgumentException("user argument is null"); + } + + if (pem == null) { + throw new IllegalArgumentException("pem argument is null"); + } + + authenticated = am.authenticatePublicKey(user, pem.toCharArray(), password, getOrCreateSecureRND()); + return authenticated; + } + + /** + * A wrapper that calls {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback) + * authenticateWithKeyboardInteractivewith} a <code>null</code> submethod list. + * + * @param user A <code>String</code> holding the username. + * @param cb An <code>InteractiveCallback</code> which will be used to + * determine the responses to the questions asked by the server. + * @return whether the connection is now authenticated. + * @throws IOException + */ + + public synchronized boolean authenticateWithKeyboardInteractive(String user, InteractiveCallback cb) + throws IOException { + return authenticateWithKeyboardInteractive(user, null, cb); + } + + /** + * After a successful connect, one has to authenticate oneself. This method + * is based on "keyboard-interactive", specified in + * draft-ietf-secsh-auth-kbdinteract-XX. Basically, you have to define a + * callback object which will be feeded with challenges generated by the + * server. Answers are then sent back to the server. It is possible that the + * callback will be called several times during the invocation of this + * method (e.g., if the server replies to the callback's answer(s) with + * another challenge...) + * <p/> + * If the authentication phase is complete, <code>true</code> will be + * returned. If the server does not accept the request (or if further + * authentication steps are needed), <code>false</code> is returned and + * one can retry either by using this or any other authentication method + * (use the <code>getRemainingAuthMethods</code> method to get a list of + * the remaining possible methods). + * <p/> + * Note: some SSH servers advertise "keyboard-interactive", however, any + * interactive request will be denied (without having sent any challenge to + * the client). + * + * @param user A <code>String</code> holding the username. + * @param submethods An array of submethod names, see + * draft-ietf-secsh-auth-kbdinteract-XX. May be <code>null</code> + * to indicate an empty list. + * @param cb An <code>InteractiveCallback</code> which will be used to + * determine the responses to the questions asked by the server. + * @return whether the connection is now authenticated. + * @throws IOException + */ + + public synchronized boolean authenticateWithKeyboardInteractive(String user, String[] submethods, + InteractiveCallback cb) throws IOException { + if (cb == null) { + throw new IllegalArgumentException("Callback may not ne NULL!"); + } + + if (tm == null) { + throw new IllegalStateException("Connection is not established!"); + } + + if (authenticated) { + throw new IllegalStateException("Connection is already authenticated!"); + } + + if (am == null) { + am = new AuthenticationManager(tm); + } + + if (cm == null) { + cm = new ChannelManager(tm); + } + + if (user == null) { + throw new IllegalArgumentException("user argument is null"); + } + + authenticated = am.authenticateInteractive(user, submethods, cb); + return authenticated; + } + + public synchronized boolean authenticateWithAgent(String user, AgentProxy proxy) throws IOException { + if (tm == null) { + throw new IllegalStateException("Connection is not established!"); + } + + if (authenticated) { + throw new IllegalStateException("Connection is already authenticated!"); + } + + if (am == null) { + am = new AuthenticationManager(tm); + } + + if (cm == null) { + cm = new ChannelManager(tm); + } + + if (user == null) { + throw new IllegalArgumentException("user argument is null"); + } + + authenticated = am.authenticatePublicKey(user, proxy); + return authenticated; + } + + /** + * After a successful connect, one has to authenticate oneself. This method + * sends username and password to the server. + * <p/> + * If the authentication phase is complete, <code>true</code> will be + * returned. If the server does not accept the request (or if further + * authentication steps are needed), <code>false</code> is returned and + * one can retry either by using this or any other authentication method + * (use the <code>getRemainingAuthMethods</code> method to get a list of + * the remaining possible methods). + * <p/> + * Note: if this method fails, then please double-check that it is actually + * offered by the server (use {@link #getRemainingAuthMethods(String) getRemainingAuthMethods()}. + * <p/> + * Often, password authentication is disabled, but users are not aware of it. + * Many servers only offer "publickey" and "keyboard-interactive". However, + * even though "keyboard-interactive" *feels* like password authentication + * (e.g., when using the putty or openssh clients) it is *not* the same mechanism. + * + * @param user + * @param password + * @return if the connection is now authenticated. + * @throws IOException + */ + + public synchronized boolean authenticateWithPassword(String user, String password) throws IOException { + if (tm == null) { + throw new IllegalStateException("Connection is not established!"); + } + + if (authenticated) { + throw new IllegalStateException("Connection is already authenticated!"); + } + + if (am == null) { + am = new AuthenticationManager(tm); + } + + if (cm == null) { + cm = new ChannelManager(tm); + } + + if (user == null) { + throw new IllegalArgumentException("user argument is null"); + } + + if (password == null) { + throw new IllegalArgumentException("password argument is null"); + } + + authenticated = am.authenticatePassword(user, password); + return authenticated; + } + + /** + * After a successful connect, one has to authenticate oneself. + * This method can be used to explicitly use the special "none" + * authentication method (where only a username has to be specified). + * <p/> + * Note 1: The "none" method may always be tried by clients, however as by + * the specs, the server will not explicitly announce it. In other words, + * the "none" token will never show up in the list returned by + * {@link #getRemainingAuthMethods(String)}. + * <p/> + * Note 2: no matter which one of the authenticateWithXXX() methods + * you call, the library will always issue exactly one initial "none" + * authentication request to retrieve the initially allowed list of + * authentication methods by the server. Please read RFC 4252 for the + * details. + * <p/> + * If the authentication phase is complete, <code>true</code> will be + * returned. If further authentication steps are needed, <code>false</code> + * is returned and one can retry by any other authentication method + * (use the <code>getRemainingAuthMethods</code> method to get a list of + * the remaining possible methods). + * + * @param user + * @return if the connection is now authenticated. + * @throws IOException + */ + + public synchronized boolean authenticateWithNone(String user) throws IOException { + if (tm == null) { + throw new IllegalStateException("Connection is not established!"); + } + + if (authenticated) { + throw new IllegalStateException("Connection is already authenticated!"); + } + + if (am == null) { + am = new AuthenticationManager(tm); + } + + if (cm == null) { + cm = new ChannelManager(tm); + } + + if (user == null) { + throw new IllegalArgumentException("user argument is null"); + } + + /* Trigger the sending of the PacketUserauthRequestNone packet */ + /* (if not already done) */ + authenticated = am.authenticateNone(user); + return authenticated; + } + + /** + * After a successful connect, one has to authenticate oneself. + * The authentication method "publickey" works by signing a challenge + * sent by the server. The signature is either DSA or RSA based - it + * just depends on the type of private key you specify, either a DSA + * or RSA private key in PEM format. And yes, this is may seem to be a + * little confusing, the method is called "publickey" in the SSH-2 protocol + * specification, however since we need to generate a signature, you + * actually have to supply a private key =). + * <p/> + * The private key contained in the PEM file may also be encrypted ("Proc-Type: 4,ENCRYPTED"). + * The library supports DES-CBC and DES-EDE3-CBC encryption, as well + * as the more exotic PEM encrpytions AES-128-CBC, AES-192-CBC and AES-256-CBC. + * <p/> + * If the authentication phase is complete, <code>true</code> will be + * returned. If the server does not accept the request (or if further + * authentication steps are needed), <code>false</code> is returned and + * one can retry either by using this or any other authentication method + * (use the <code>getRemainingAuthMethods</code> method to get a list of + * the remaining possible methods). + * <p/> + * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..." + * it is not in the expected format. You have to convert it to the OpenSSH + * key format by using the "puttygen" tool (can be downloaded from the Putty + * website). Simply load your key and then use the "Conversions/Export OpenSSH key" + * functionality to get a proper PEM file. + * + * @param user A <code>String</code> holding the username. + * @param pemPrivateKey A <code>char[]</code> containing a DSA or RSA private key of the + * user in OpenSSH key format (PEM, you can't miss the + * "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----" + * tag). The char array may contain linebreaks/linefeeds. + * @param password If the PEM structure is encrypted ("Proc-Type: 4,ENCRYPTED") then + * you must specify a password. Otherwise, this argument will be ignored + * and can be set to <code>null</code>. + * @return whether the connection is now authenticated. + * @throws IOException + */ + + public synchronized boolean authenticateWithPublicKey(String user, char[] pemPrivateKey, String password) + throws IOException { + if (tm == null) { + throw new IllegalStateException("Connection is not established!"); + } + + if (authenticated) { + throw new IllegalStateException("Connection is already authenticated!"); + } + + if (am == null) { + am = new AuthenticationManager(tm); + } + + if (cm == null) { + cm = new ChannelManager(tm); + } + + if (user == null) { + throw new IllegalArgumentException("user argument is null"); + } + + if (pemPrivateKey == null) { + throw new IllegalArgumentException("pemPrivateKey argument is null"); + } + + authenticated = am.authenticatePublicKey(user, pemPrivateKey, password, getOrCreateSecureRND()); + return authenticated; + } + + /** + * After a successful connect, one has to authenticate oneself. The + * authentication method "publickey" works by signing a challenge sent by + * the server. The signature is either DSA or RSA based - it just depends on + * the type of private key you specify, either a DSA or RSA private key in + * PEM format. And yes, this is may seem to be a little confusing, the + * method is called "publickey" in the SSH-2 protocol specification, however + * since we need to generate a signature, you actually have to supply a + * private key =). + * <p> + * If the authentication phase is complete, <code>true</code> will be + * returned. If the server does not accept the request (or if further + * authentication steps are needed), <code>false</code> is returned and + * one can retry either by using this or any other authentication method + * (use the <code>getRemainingAuthMethods</code> method to get a list of + * the remaining possible methods). + * + * @param user + * A <code>String</code> holding the username. + * @param pair + * A <code>RSAPrivateKey</code> or <code>DSAPrivateKey</code> + * containing a DSA or RSA private key of + * the user in Trilead object format. + * + * @return whether the connection is now authenticated. + * @throws IOException + */ + + public synchronized boolean authenticateWithPublicKey(String user, KeyPair pair) + throws IOException { + if (tm == null) + throw new IllegalStateException("Connection is not established!"); + + if (authenticated) + throw new IllegalStateException("Connection is already authenticated!"); + + if (am == null) + am = new AuthenticationManager(tm); + + if (cm == null) + cm = new ChannelManager(tm); + + if (user == null) + throw new IllegalArgumentException("user argument is null"); + + if (pair == null) + throw new IllegalArgumentException("Key pair argument is null"); + + authenticated = am.authenticatePublicKey(user, pair, getOrCreateSecureRND()); + return authenticated; + } + + /** + * A convenience wrapper function which reads in a private key (PEM format, either DSA or RSA) + * and then calls <code>authenticateWithPublicKey(String, char[], String)</code>. + * <p/> + * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..." + * it is not in the expected format. You have to convert it to the OpenSSH + * key format by using the "puttygen" tool (can be downloaded from the Putty + * website). Simply load your key and then use the "Conversions/Export OpenSSH key" + * functionality to get a proper PEM file. + * + * @param user A <code>String</code> holding the username. + * @param pemFile A <code>File</code> object pointing to a file containing a DSA or RSA + * private key of the user in OpenSSH key format (PEM, you can't miss the + * "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----" + * tag). + * @param password If the PEM file is encrypted then you must specify the password. + * Otherwise, this argument will be ignored and can be set to <code>null</code>. + * @return whether the connection is now authenticated. + * @throws IOException + */ + + public synchronized boolean authenticateWithPublicKey(String user, File pemFile, String password) + throws IOException { + if (pemFile == null) { + throw new IllegalArgumentException("pemFile argument is null"); + } + + char[] buff = new char[256]; + CharArrayWriter cw = new CharArrayWriter(); + FileReader fr = new FileReader(pemFile); + + while (true) { + int len = fr.read(buff); + + if (len < 0) { + break; + } + + cw.write(buff, 0, len); + } + + fr.close(); + return authenticateWithPublicKey(user, cw.toCharArray(), password); + } + + /** + * Add a {@link ConnectionMonitor} to this connection. Can be invoked at any time, + * but it is best to add connection monitors before invoking + * <code>connect()</code> to avoid glitches (e.g., you add a connection monitor after + * a successful connect(), but the connection has died in the mean time. Then, + * your connection monitor won't be notified.) + * <p/> + * You can add as many monitors as you like. If a monitor has already been added, then + * this method does nothing. + * + * @param cmon An object implementing the {@link ConnectionMonitor} interface. + * @see ConnectionMonitor + */ + + public synchronized void addConnectionMonitor(ConnectionMonitor cmon) { + if (!connectionMonitors.contains(cmon)) { + connectionMonitors.add(cmon); + + if (tm != null) { + tm.setConnectionMonitors(connectionMonitors); + } + } + } + + /** + * Remove a {@link ConnectionMonitor} from this connection. + * + * @param cmon + * @return whether the monitor could be removed + */ + + public synchronized boolean removeConnectionMonitor(ConnectionMonitor cmon) { + boolean existed = connectionMonitors.remove(cmon); + + if (tm != null) { + tm.setConnectionMonitors(connectionMonitors); + } + + return existed; + } + + /** + * Controls whether compression is used on the link or not. + * <p> + * Note: This can only be called before connect() + * @param enabled whether to enable compression + * @throws IOException + */ + + public synchronized void setCompression(boolean enabled) throws IOException { + if (tm != null) + throw new IOException("Connection to " + hostname + " is already in connected state!"); + + if (enabled) enableCompression(); + else disableCompression(); + } + + /** + * Close the connection to the SSH-2 server. All assigned sessions will be + * closed, too. Can be called at any time. Don't forget to call this once + * you don't need a connection anymore - otherwise the receiver thread may + * run forever. + */ + + // cannot be synchronized, since Connection.connect() is synchronized, and + // if the key exchange fails, another thread will try to close(). + + public void close() { + log.debug("Connection.close()"); + Throwable t = new Throwable("Closed due to user request."); + close(t, false); + } + + public void close(Throwable t, boolean hard) { + log.debug(String.format("Connection.close(%s hard=%b)", t.getMessage(), hard)); + if (cm != null) { + cm.closeAllChannels(); + } + + if (tm != null) { + tm.close(t, hard == false); + tm = null; + } + + am = null; + cm = null; + authenticated = false; + } + + /** + * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(null, 0, 0)}. + * + * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. + * @throws IOException + */ + + public synchronized ConnectionInfo connect() throws IOException { + return connect(null, 0, 0); + } + + /** + * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(verifier, 0, 0)}. + * + * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. + * @throws IOException + */ + + public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier) throws IOException { + return connect(verifier, 0, 0); + } + + /** + * Connect to the SSH-2 server and, as soon as the server has presented its + * host key, use the {@link ServerHostKeyVerifier#verifyServerHostKey(String, + * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} + * method of the <code>verifier</code> to ask for permission to proceed. + * If <code>verifier</code> is <code>null</code>, then any host key will be + * accepted - this is NOT recommended, since it makes man-in-the-middle attackes + * VERY easy (somebody could put a proxy SSH server between you and the real server). + * <p/> + * Note: The verifier will be called before doing any crypto calculations + * (i.e., diffie-hellman). Therefore, if you don't like the presented host key then + * no CPU cycles are wasted (and the evil server has less information about us). + * <p/> + * However, it is still possible that the server presented a fake host key: the server + * cheated (typically a sign for a man-in-the-middle attack) and is not able to generate + * a signature that matches its host key. Don't worry, the library will detect such + * a scenario later when checking the signature (the signature cannot be checked before + * having completed the diffie-hellman exchange). + * <p/> + * Note 2: The {@link ServerHostKeyVerifier#verifyServerHostKey(String, + * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} method + * will *NOT* be called from the current thread, the call is being made from a + * background thread (there is a background dispatcher thread for every + * established connection). + * <p/> + * Note 3: This method will block as long as the key exchange of the underlying connection + * has not been completed (and you have not specified any timeouts). + * <p/> + * Note 4: If you want to re-use a connection object that was successfully connected, + * then you must call the {@link #close()} method before invoking <code>connect()</code> again. + * + * @param verifier An object that implements the + * {@link ServerHostKeyVerifier} interface. Pass <code>null</code> + * to accept any server host key - NOT recommended. + * @param connectTimeout Connect the underlying TCP socket to the server with the given timeout + * value (non-negative, in milliseconds). Zero means no timeout. + * @param kexTimeout Timeout for complete connection establishment (non-negative, + * in milliseconds). Zero means no timeout. The timeout counts from the + * moment you invoke the connect() method and is cancelled as soon as the + * first key-exchange round has finished. It is possible that + * the timeout event will be fired during the invocation of the + * <code>verifier</code> callback, but it will only have an effect after + * the <code>verifier</code> returns. + * @return A {@link ConnectionInfo} object containing the details of + * the established connection. + * @throws IOException If any problem occurs, e.g., the server's host key is not + * accepted by the <code>verifier</code> or there is problem during + * the initial crypto setup (e.g., the signature sent by the server is wrong). + * <p/> + * In case of a timeout (either connectTimeout or kexTimeout) + * a SocketTimeoutException is thrown. + * <p/> + * An exception may also be thrown if the connection was already successfully + * connected (no matter if the connection broke in the mean time) and you invoke + * <code>connect()</code> again without having called {@link #close()} first. + * <p/> + * If a HTTP proxy is being used and the proxy refuses the connection, + * then a {@link HTTPProxyException} may be thrown, which + * contains the details returned by the proxy. If the proxy is buggy and does + * not return a proper HTTP response, then a normal IOException is thrown instead. + */ + + public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout) + throws IOException { + final class TimeoutState { + boolean isCancelled = false; + boolean timeoutSocketClosed = false; + } + + if (tm != null) { + throw new IllegalStateException(String.format("Connection to %s is already in connected state", hostname)); + } + + if (connectTimeout < 0) { + throw new IllegalArgumentException("connectTimeout must be non-negative!"); + } + + if (kexTimeout < 0) { + throw new IllegalArgumentException("kexTimeout must be non-negative!"); + } + + final TimeoutState state = new TimeoutState(); + + if (null == proxy) { + tm = new ClientTransportManager(new Socket()); + } + else { + tm = new HTTPProxyClientTransportManager(new Socket(), proxy); + } + + tm.setSoTimeout(connectTimeout); + tm.setTcpNoDelay(tcpNoDelay); + tm.setConnectionMonitors(connectionMonitors); + + try { + TimeoutToken token = null; + + if (kexTimeout > 0) { + final Runnable timeoutHandler = new Runnable() { + public void run() { + synchronized (state) { + if (state.isCancelled) { + return; + } + + state.timeoutSocketClosed = true; + tm.close(new SocketTimeoutException("The connect timeout expired"), false); + } + } + }; + long timeoutHorizont = System.currentTimeMillis() + kexTimeout; + token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler); + } + + tm.connect(hostname, port, softwareversion, cryptoWishList, verifier, dhgexpara, connectTimeout, + getOrCreateSecureRND()); + /* Wait until first KEX has finished */ + ConnectionInfo ci = tm.getConnectionInfo(1); + + /* Now try to cancel the timeout, if needed */ + + if (token != null) { + TimeoutService.cancelTimeoutHandler(token); + + /* Were we too late? */ + + synchronized (state) { + if (state.timeoutSocketClosed) { + throw new IOException("This exception will be replaced by the one below =)"); + } + + /* Just in case the "cancelTimeoutHandler" invocation came just a little bit + * too late but the handler did not enter the semaphore yet - we can + * still stop it. + */ + state.isCancelled = true; + } + } + + return ci; + } + catch (SocketTimeoutException e) { + throw e; + } + catch (HTTPProxyException e) { + throw e; + } + catch (IOException e) { + // This will also invoke any registered connection monitors + close(e, false); + + synchronized (state) { + /* Show a clean exception, not something like "the socket is closed!?!" */ + if (state.timeoutSocketClosed) { + throw new SocketTimeoutException(String.format("The kexTimeout (%d ms) expired.", kexTimeout)); + } + } + + throw e; + } + } + + /** + * Creates a new {@link LocalPortForwarder}. + * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local + * port via the secure tunnel to another host (which may or may not be + * identical to the remote SSH-2 server). + * <p/> + * This method must only be called after one has passed successfully the authentication step. + * There is no limit on the number of concurrent forwardings. + * + * @param local_port the local port the LocalPortForwarder shall bind to. + * @param host_to_connect target address (IP or hostname) + * @param port_to_connect target port + * @return A {@link LocalPortForwarder} object. + * @throws IOException + */ + + public synchronized LocalPortForwarder createLocalPortForwarder(int local_port, String host_to_connect, + int port_to_connect) throws IOException { + this.checkConnection(); + return new LocalPortForwarder(cm, local_port, host_to_connect, port_to_connect); + } + + /** + * Creates a new {@link LocalPortForwarder}. + * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local + * port via the secure tunnel to another host (which may or may not be + * identical to the remote SSH-2 server). + * <p/> + * This method must only be called after one has passed successfully the authentication step. + * There is no limit on the number of concurrent forwardings. + * + * @param addr specifies the InetSocketAddress where the local socket shall be bound to. + * @param host_to_connect target address (IP or hostname) + * @param port_to_connect target port + * @return A {@link LocalPortForwarder} object. + * @throws IOException + */ + + public synchronized LocalPortForwarder createLocalPortForwarder(InetSocketAddress addr, String host_to_connect, + int port_to_connect) throws IOException { + this.checkConnection(); + return new LocalPortForwarder(cm, addr, host_to_connect, port_to_connect); + } + + /** + * Creates a new {@link LocalStreamForwarder}. + * A <code>LocalStreamForwarder</code> manages an Input/Outputstream pair + * that is being forwarded via the secure tunnel into a TCP/IP connection to another host + * (which may or may not be identical to the remote SSH-2 server). + * + * @param host_to_connect + * @param port_to_connect + * @return A {@link LocalStreamForwarder} object. + * @throws IOException + */ + + public synchronized LocalStreamForwarder createLocalStreamForwarder(String host_to_connect, int port_to_connect) + throws IOException { + this.checkConnection(); + return new LocalStreamForwarder(cm, host_to_connect, port_to_connect); + } + + /** + * Creates a new {@link DynamicPortForwarder}. A + * <code>DynamicPortForwarder</code> forwards TCP/IP connections that arrive + * at a local port via the secure tunnel to another host that is chosen via + * the SOCKS protocol. + * <p> + * This method must only be called after one has passed successfully the + * authentication step. There is no limit on the number of concurrent + * forwardings. + * + * @param local_port + * @return A {@link DynamicPortForwarder} object. + * @throws IOException + */ + + public synchronized DynamicPortForwarder createDynamicPortForwarder(int local_port) throws IOException { + if (tm == null) + throw new IllegalStateException("Cannot forward ports, you need to establish a connection first."); + + if (!authenticated) + throw new IllegalStateException("Cannot forward ports, connection is not authenticated."); + + return new DynamicPortForwarder(cm, local_port); + } + + /** + * Creates a new {@link DynamicPortForwarder}. A + * <code>DynamicPortForwarder</code> forwards TCP/IP connections that arrive + * at a local port via the secure tunnel to another host that is chosen via + * the SOCKS protocol. + * <p> + * This method must only be called after one has passed successfully the + * authentication step. There is no limit on the number of concurrent + * forwardings. + * + * @param addr + * specifies the InetSocketAddress where the local socket shall + * be bound to. + * @return A {@link DynamicPortForwarder} object. + * @throws IOException + */ + + public synchronized DynamicPortForwarder createDynamicPortForwarder(InetSocketAddress addr) throws IOException { + if (tm == null) + throw new IllegalStateException("Cannot forward ports, you need to establish a connection first."); + + if (!authenticated) + throw new IllegalStateException("Cannot forward ports, connection is not authenticated."); + + return new DynamicPortForwarder(cm, addr); + } + + /** + * Create a very basic {@link SCPClient} that can be used to copy + * files from/to the SSH-2 server. + * <p/> + * Works only after one has passed successfully the authentication step. + * There is no limit on the number of concurrent SCP clients. + * <p/> + * Note: This factory method will probably disappear in the future. + * + * @return A {@link SCPClient} object. + * @throws IOException + */ + + public synchronized SCPClient createSCPClient() throws IOException { + this.checkConnection(); + return new SCPClient(this); + } + + /** + * Force an asynchronous key re-exchange (the call does not block). The + * latest values set for MAC, Cipher and DH group exchange parameters will + * be used. If a key exchange is currently in progress, then this method has + * the only effect that the so far specified parameters will be used for the + * next (server driven) key exchange. + * <p/> + * Note: This implementation will never start a key exchange (other than the initial one) + * unless you or the SSH-2 server ask for it. + * + * @throws IOException In case of any failure behind the scenes. + */ + + public synchronized void forceKeyExchange() throws IOException { + this.checkConnection(); + tm.forceKeyExchange(cryptoWishList, dhgexpara, null, null, null); + } + + /** + * Returns the hostname that was passed to the constructor. + * + * @return the hostname + */ + + public synchronized String getHostname() { + return hostname; + } + + /** + * Returns the port that was passed to the constructor. + * + * @return the TCP port + */ + + public synchronized int getPort() { + return port; + } + + /** + * Returns a {@link ConnectionInfo} object containing the details of + * the connection. Can be called as soon as the connection has been + * established (successfully connected). + * + * @return A {@link ConnectionInfo} object. + * @throws IOException In case of any failure behind the scenes. + */ + + public synchronized ConnectionInfo getConnectionInfo() throws IOException { + this.checkConnection(); + return tm.getConnectionInfo(1); + } + + /** + * After a successful connect, one has to authenticate oneself. This method + * can be used to tell which authentication methods are supported by the + * server at a certain stage of the authentication process (for the given + * username). + * <p/> + * Note 1: the username will only be used if no authentication step was done + * so far (it will be used to ask the server for a list of possible + * authentication methods by sending the initial "none" request). Otherwise, + * this method ignores the user name and returns a cached method list + * (which is based on the information contained in the last negative server response). + * <p/> + * Note 2: the server may return method names that are not supported by this + * implementation. + * <p/> + * After a successful authentication, this method must not be called + * anymore. + * + * @param user A <code>String</code> holding the username. + * @return a (possibly emtpy) array holding authentication method names. + * @throws IOException + */ + + public synchronized String[] getRemainingAuthMethods(String user) throws IOException { + if (user == null) { + throw new IllegalArgumentException("user argument may not be NULL!"); + } + + if (tm == null) { + throw new IllegalStateException("Connection is not established!"); + } + + if (authenticated) { + throw new IllegalStateException("Connection is already authenticated!"); + } + + if (am == null) { + am = new AuthenticationManager(tm); + } + + if (cm == null) { + cm = new ChannelManager(tm); + } + + final Set<String> remainingMethods = am.getRemainingMethods(user); + return remainingMethods.toArray(new String[remainingMethods.size()]); + } + + /** + * Determines if the authentication phase is complete. Can be called at any + * time. + * + * @return <code>true</code> if no further authentication steps are + * needed. + */ + + public synchronized boolean isAuthenticationComplete() { + return authenticated; + } + + /** + * Returns true if there was at least one failed authentication request and + * the last failed authentication request was marked with "partial success" + * by the server. This is only needed in the rare case of SSH-2 server setups + * that cannot be satisfied with a single successful authentication request + * (i.e., multiple authentication steps are needed.) + * <p/> + * If you are interested in the details, then have a look at RFC4252. + * + * @return if the there was a failed authentication step and the last one + * was marked as a "partial success". + */ + + public synchronized boolean isAuthenticationPartialSuccess() { + if (am == null) { + return false; + } + + return am.getPartialSuccess(); + } + + /** + * Checks if a specified authentication method is available. This method is + * actually just a wrapper for {@link #getRemainingAuthMethods(String) + * getRemainingAuthMethods()}. + * + * @param user A <code>String</code> holding the username. + * @param method An authentication method name (e.g., "publickey", "password", + * "keyboard-interactive") as specified by the SSH-2 standard. + * @return if the specified authentication method is currently available. + * @throws IOException + */ + + public synchronized boolean isAuthMethodAvailable(String user, String method) throws IOException { + String methods[] = getRemainingAuthMethods(user); + + for (final String m : methods) { + if (m.compareTo(method) == 0) { + return true; + } + } + + return false; + } + + private SecureRandomFix getOrCreateSecureRND() { + if (generator == null) { + generator = new SecureRandomFix(); + } + + return generator; + } + + /** + * Open a new {@link Session} on this connection. Works only after one has passed + * successfully the authentication step. There is no limit on the number of + * concurrent sessions. + * + * @return A {@link Session} object. + * @throws IOException + */ + + public synchronized Session openSession() throws IOException { + this.checkConnection(); + return new Session(cm, getOrCreateSecureRND()); + } + + /** + * Send an SSH_MSG_IGNORE packet. This method will generate a random data attribute + * (length between 0 (invlusive) and 16 (exclusive) bytes, contents are random bytes). + * <p/> + * This method must only be called once the connection is established. + * + * @throws IOException + */ + + public synchronized void sendIgnorePacket() throws IOException { + SecureRandomFix rnd = getOrCreateSecureRND(); + byte[] data = new byte[rnd.nextInt(16)]; + rnd.nextBytes(data); + sendIgnorePacket(data); + } + + /** + * Send an SSH_MSG_IGNORE packet with the given data attribute. + * <p/> + * This method must only be called once the connection is established. + * + * @throws IOException + */ + + public synchronized void sendIgnorePacket(byte[] data) throws IOException { + this.checkConnection(); + PacketIgnore pi = new PacketIgnore(data); + tm.sendMessage(pi.getPayload()); + } + + /** + * Controls whether compression is used on the link or not. + */ + + public synchronized void setCompression(String[] algorithms) { + CompressionFactory.checkCompressorList(algorithms); + cryptoWishList.c2s_comp_algos = algorithms; + } + + public synchronized void enableCompression() { + cryptoWishList.c2s_comp_algos = CompressionFactory.getDefaultCompressorList(); + cryptoWishList.s2c_comp_algos = CompressionFactory.getDefaultCompressorList(); + } + + public synchronized void disableCompression() { + cryptoWishList.c2s_comp_algos = new String[] {"none"}; + cryptoWishList.s2c_comp_algos = new String[] {"none"}; + } + + /** + * Unless you know what you are doing, you will never need this. + */ + + public synchronized void setClient2ServerCiphers(final String[] ciphers) { + if ((ciphers == null) || (ciphers.length == 0)) { + throw new IllegalArgumentException(); + } + + BlockCipherFactory.checkCipherList(ciphers); + cryptoWishList.c2s_enc_algos = ciphers; + } + + /** + * Unless you know what you are doing, you will never need this. + */ + + public synchronized void setClient2ServerMACs(final String[] macs) { + MAC.checkMacList(macs); + cryptoWishList.c2s_mac_algos = macs; + } + + /** + * Sets the parameters for the diffie-hellman group exchange. Unless you + * know what you are doing, you will never need this. Default values are + * defined in the {@link DHGexParameters} class. + * + * @param dgp {@link DHGexParameters}, non null. + */ + + public synchronized void setDHGexParameters(DHGexParameters dgp) { + if (dgp == null) { + throw new IllegalArgumentException(); + } + + dhgexpara = dgp; + } + + /** + * Unless you know what you are doing, you will never need this. + */ + + public synchronized void setServer2ClientCiphers(final String[] ciphers) { + BlockCipherFactory.checkCipherList(ciphers); + cryptoWishList.s2c_enc_algos = ciphers; + } + + /** + * Unless you know what you are doing, you will never need this. + */ + + public synchronized void setServer2ClientMACs(final String[] macs) { + MAC.checkMacList(macs); + cryptoWishList.s2c_mac_algos = macs; + } + + /** + * Define the set of allowed server host key algorithms to be used for + * the following key exchange operations. + * <p/> + * Unless you know what you are doing, you will never need this. + * + * @param algos An array of allowed server host key algorithms. + * SSH-2 defines <code>ssh-dss</code> and <code>ssh-rsa</code>. + * The entries of the array must be ordered after preference, i.e., + * the entry at index 0 is the most preferred one. You must specify + * at least one entry. + */ + + public synchronized void setServerHostKeyAlgorithms(final String[] algos) { + KexManager.checkServerHostkeyAlgorithmsList(algos); + cryptoWishList.serverHostKeyAlgorithms = algos; + } + + /** + * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm) on the underlying socket. + * <p/> + * Can be called at any time. If the connection has not yet been established + * then the passed value will be stored and set after the socket has been set up. + * The default value that will be used is <code>false</code>. + * + * @param enable the argument passed to the <code>Socket.setTCPNoDelay()</code> method. + * @throws IOException + */ + + public synchronized void setTCPNoDelay(boolean enable) throws IOException { + tcpNoDelay = enable; + + if (tm != null) { + tm.setTcpNoDelay(enable); + } + } + + /** + * Used to tell the library that the connection shall be established through + * a proxy server. It only makes sense to call this method before calling + * the {@link #connect() connect()} method. + * <p> + * At the moment, only HTTP proxies are supported. + * <p> + * Note: This method can be called any number of times. The + * {@link #connect() connect()} method will use the value set in the last + * preceding invocation of this method. + * + * @see HTTPProxyData + * + * @param proxy + * Connection information about the proxy. If <code>null</code>, + * then no proxy will be used (non surprisingly, this is also the + * default). + */ + + public synchronized void setProxyData(HTTPProxyData proxy) { + this.proxy = proxy; + } + + /** + * Request a remote port forwarding. + * If successful, then forwarded connections will be redirected to the given target address. + * You can cancle a requested remote port forwarding by calling + * {@link #cancelRemotePortForwarding(int) cancelRemotePortForwarding()}. + * <p/> + * A call of this method will block until the peer either agreed or disagreed to your request- + * <p/> + * Note 1: this method typically fails if you + * <ul> + * <li>pass a port number for which the used remote user has not enough permissions (i.e., port + * < 1024)</li> + * <li>or pass a port number that is already in use on the remote server</li> + * <li>or if remote port forwarding is disabled on the server.</li> + * </ul> + * <p/> + * Note 2: (from the openssh man page): By default, the listening socket on the server will be + * bound to the loopback interface only. This may be overriden by specifying a bind address. + * Specifying a remote bind address will only succeed if the server's <b>GatewayPorts</b> option + * is enabled (see sshd_config(5)). + * + * @param bindAddress address to bind to on the server: + * <ul> + * <li>"" means that connections are to be accepted on all protocol families + * supported by the SSH implementation</li> + * <li>"0.0.0.0" means to listen on all IPv4 addresses</li> + * <li>"::" means to listen on all IPv6 addresses</li> + * <li>"localhost" means to listen on all protocol families supported by the SSH + * implementation on loopback addresses only, [RFC3330] and RFC3513]</li> + * <li>"127.0.0.1" and "::1" indicate listening on the loopback interfaces for + * IPv4 and IPv6 respectively</li> + * </ul> + * @param bindPort port number to bind on the server (must be > 0) + * @param targetAddress the target address (IP or hostname) + * @param targetPort the target port + * @throws IOException + */ + + public synchronized void requestRemotePortForwarding(String bindAddress, int bindPort, String targetAddress, + int targetPort) throws IOException { + this.checkConnection(); + + if ((bindAddress == null) || (targetAddress == null) || (bindPort <= 0) || (targetPort <= 0)) { + throw new IllegalArgumentException(); + } + + cm.requestGlobalForward(bindAddress, bindPort, targetAddress, targetPort); + } + + /** + * Cancel an earlier requested remote port forwarding. + * Currently active forwardings will not be affected (e.g., disrupted). + * Note that further connection forwarding requests may be received until + * this method has returned. + * + * @param bindPort the allocated port number on the server + * @throws IOException if the remote side refuses the cancel request or another low + * level error occurs (e.g., the underlying connection is closed) + */ + + public synchronized void cancelRemotePortForwarding(int bindPort) throws IOException { + this.checkConnection(); + cm.requestCancelGlobalForward(bindPort); + } + + /** + * Provide your own instance of SecureRandom. Can be used, e.g., if you + * want to seed the used SecureRandom generator manually. + * <p/> + * The SecureRandom instance is used during key exchanges, public key authentication, + * x11 cookie generation and the like. + * + * @param rnd a SecureRandom instance + */ + + public synchronized void setSecureRandom(SecureRandomFix rnd) { + if (rnd == null) { + throw new IllegalArgumentException(); + } + + this.generator = rnd; + } + + private void checkConnection() throws IllegalStateException { + if (tm == null) { + throw new IllegalStateException("You need to establish a connection first."); + } + + if (!authenticated) { + throw new IllegalStateException("The connection is not authenticated."); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ConnectionInfo.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * In most cases you probably do not need the information contained in here. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class ConnectionInfo { + /** + * The used key exchange (KEX) algorithm in the latest key exchange. + */ + public String keyExchangeAlgorithm; + + /** + * The currently used crypto algorithm for packets from to the client to the + * server. + */ + public String clientToServerCryptoAlgorithm; + /** + * The currently used crypto algorithm for packets from to the server to the + * client. + */ + public String serverToClientCryptoAlgorithm; + + /** + * The currently used MAC algorithm for packets from to the client to the + * server. + */ + public String clientToServerMACAlgorithm; + /** + * The currently used MAC algorithm for packets from to the server to the + * client. + */ + public String serverToClientMACAlgorithm; + + /** + * The type of the server host key (currently either "ssh-dss" or + * "ssh-rsa"). + */ + public String serverHostKeyAlgorithm; + + /** + * The server host key that was sent during the latest key exchange. + */ + public byte[] serverHostKey; + + /** + * Number of kex exchanges performed on this connection so far. + */ + public int keyExchangeCounter = 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ConnectionMonitor.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * A <code>ConnectionMonitor</code> is used to get notified when the + * underlying socket of a connection is closed. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public interface ConnectionMonitor { + /** + * This method is called after the connection's underlying + * socket has been closed. E.g., due to the {@link Connection#close()} request of the + * user, if the peer closed the connection, due to a fatal error during connect() + * (also if the socket cannot be established) or if a fatal error occured on + * an established connection. + * <p> + * This is an experimental feature. + * <p> + * You MUST NOT make any assumption about the thread that invokes this method. + * <p> + * <b>Please note: if the connection is not connected (e.g., there was no successful + * connect() call), then the invocation of {@link Connection#close()} will NOT trigger + * this method.</b> + * + * @see Connection#addConnectionMonitor(ConnectionMonitor) + * + * @param reason Includes an indication why the socket was closed. + */ + public void connectionLost(Throwable reason); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/DHGexParameters.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * A <code>DHGexParameters</code> object can be used to specify parameters for + * the diffie-hellman group exchange. + * <p> + * Depending on which constructor is used, either the use of a + * <code>SSH_MSG_KEX_DH_GEX_REQUEST</code> or <code>SSH_MSG_KEX_DH_GEX_REQUEST_OLD</code> + * can be forced. + * + * @see Connection#setDHGexParameters(DHGexParameters) + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public class DHGexParameters { + private final int min_group_len; + private final int pref_group_len; + private final int max_group_len; + + private static final int MIN_ALLOWED = 1024; + private static final int MAX_ALLOWED = 8192; + + /** + * Same as calling {@link #DHGexParameters(int, int, int) DHGexParameters(1024, 1024, 4096)}. + * This is also the default used by the Connection class. + * + */ + public DHGexParameters() { + this(1024, 1024, 4096); + } + + /** + * This constructor can be used to force the sending of a + * <code>SSH_MSG_KEX_DH_GEX_REQUEST_OLD</code> request. + * Internally, the minimum and maximum group lengths will + * be set to zero. + * + * @param pref_group_len has to be >= 1024 and <= 8192 + */ + public DHGexParameters(int pref_group_len) { + if ((pref_group_len < MIN_ALLOWED) || (pref_group_len > MAX_ALLOWED)) + throw new IllegalArgumentException("pref_group_len out of range!"); + + this.pref_group_len = pref_group_len; + this.min_group_len = 0; + this.max_group_len = 0; + } + + /** + * This constructor can be used to force the sending of a + * <code>SSH_MSG_KEX_DH_GEX_REQUEST</code> request. + * <p> + * Note: older OpenSSH servers don't understand this request, in which + * case you should use the {@link #DHGexParameters(int)} constructor. + * <p> + * All values have to be >= 1024 and <= 8192. Furthermore, + * min_group_len <= pref_group_len <= max_group_len. + * + * @param min_group_len + * @param pref_group_len + * @param max_group_len + */ + public DHGexParameters(int min_group_len, int pref_group_len, int max_group_len) { + if ((min_group_len < MIN_ALLOWED) || (min_group_len > MAX_ALLOWED)) + throw new IllegalArgumentException("min_group_len out of range!"); + + if ((pref_group_len < MIN_ALLOWED) || (pref_group_len > MAX_ALLOWED)) + throw new IllegalArgumentException("pref_group_len out of range!"); + + if ((max_group_len < MIN_ALLOWED) || (max_group_len > MAX_ALLOWED)) + throw new IllegalArgumentException("max_group_len out of range!"); + + if ((pref_group_len < min_group_len) || (pref_group_len > max_group_len)) + throw new IllegalArgumentException("pref_group_len is incompatible with min and max!"); + + if (max_group_len < min_group_len) + throw new IllegalArgumentException("max_group_len must not be smaller than min_group_len!"); + + this.min_group_len = min_group_len; + this.pref_group_len = pref_group_len; + this.max_group_len = max_group_len; + } + + /** + * Get the maximum group length. + * + * @return the maximum group length, may be <code>zero</code> if + * SSH_MSG_KEX_DH_GEX_REQUEST_OLD should be requested + */ + public int getMax_group_len() { + return max_group_len; + } + + /** + * Get the minimum group length. + * + * @return minimum group length, may be <code>zero</code> if + * SSH_MSG_KEX_DH_GEX_REQUEST_OLD should be requested + */ + public int getMin_group_len() { + return min_group_len; + } + + /** + * Get the preferred group length. + * + * @return the preferred group length + */ + public int getPref_group_len() { + return pref_group_len; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/DynamicPortForwarder.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,63 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.ethz.ssh2; + +import java.io.IOException; +import java.net.InetSocketAddress; + +import ch.ethz.ssh2.channel.ChannelManager; +import ch.ethz.ssh2.channel.DynamicAcceptThread; + +/** + * A <code>DynamicPortForwarder</code> forwards TCP/IP connections to a local + * port via the secure tunnel to another host which is selected via the + * SOCKS protocol. Checkout {@link Connection#createDynamicPortForwarder(int)} + * on how to create one. + * + * @author Kenny Root + * @version $Id: $ + */ +public class DynamicPortForwarder { + ChannelManager cm; + + DynamicAcceptThread dat; + + DynamicPortForwarder(ChannelManager cm, int local_port) + throws IOException { + this.cm = cm; + dat = new DynamicAcceptThread(cm, local_port); + dat.setDaemon(true); + dat.start(); + } + + DynamicPortForwarder(ChannelManager cm, InetSocketAddress addr) throws IOException { + this.cm = cm; + dat = new DynamicAcceptThread(cm, addr); + dat.setDaemon(true); + dat.start(); + } + + /** + * Stop TCP/IP forwarding of newly arriving connections. + * + * @throws IOException + */ + public void close() throws IOException { + dat.stopWorking(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/HTTPProxyData.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * A <code>HTTPProxyData</code> object is used to specify the needed connection data + * to connect through a HTTP proxy. + * + * @see Connection#setProxyData(ProxyData) + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public class HTTPProxyData implements ProxyData { + public final String proxyHost; + public final int proxyPort; + public final String proxyUser; + public final String proxyPass; + public final String[] requestHeaderLines; + + /** + * Same as calling {@link #HTTPProxyData(String, int, String, String) HTTPProxyData(proxyHost, proxyPort, <code>null</code>, <code>null</code>)} + * + * @param proxyHost Proxy hostname. + * @param proxyPort Proxy port. + */ + public HTTPProxyData(String proxyHost, int proxyPort) { + this(proxyHost, proxyPort, null, null); + } + + /** + * Same as calling {@link #HTTPProxyData(String, int, String, String, String[]) HTTPProxyData(proxyHost, proxyPort, <code>null</code>, <code>null</code>, <code>null</code>)} + * + * @param proxyHost Proxy hostname. + * @param proxyPort Proxy port. + * @param proxyUser Username for basic authentication (<code>null</code> if no authentication is needed). + * @param proxyPass Password for basic authentication (<code>null</code> if no authentication is needed). + */ + public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass) { + this(proxyHost, proxyPort, proxyUser, proxyPass, null); + } + + /** + * Connection data for a HTTP proxy. It is possible to specify a username and password + * if the proxy requires basic authentication. Also, additional request header lines can + * be specified (e.g., "User-Agent: CERN-LineMode/2.15 libwww/2.17b3"). + * <p> + * Please note: if you want to use basic authentication, then both <code>proxyUser</code> + * and <code>proxyPass</code> must be non-null. + * <p> + * Here is an example: + * <p> + * <code> + * new HTTPProxyData("192.168.1.1", "3128", "proxyuser", "secret", new String[] {"User-Agent: GanymedBasedClient/1.0", "X-My-Proxy-Option: something"}); + * </code> + * + * @param proxyHost Proxy hostname. + * @param proxyPort Proxy port. + * @param proxyUser Username for basic authentication (<code>null</code> if no authentication is needed). + * @param proxyPass Password for basic authentication (<code>null</code> if no authentication is needed). + * @param requestHeaderLines An array with additional request header lines (without end-of-line markers) + * that have to be sent to the server. May be <code>null</code>. + */ + + public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass, + String[] requestHeaderLines) { + if (proxyHost == null) + throw new IllegalArgumentException("proxyHost must be non-null"); + + if (proxyPort < 0) + throw new IllegalArgumentException("proxyPort must be non-negative"); + + this.proxyHost = proxyHost; + this.proxyPort = proxyPort; + this.proxyUser = proxyUser; + this.proxyPass = proxyPass; + this.requestHeaderLines = requestHeaderLines; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/HTTPProxyException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; + +/** + * May be thrown upon connect() if a HTTP proxy is being used. + * + * @see Connection#connect() + * @see Connection#setProxyData(ProxyData) + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public class HTTPProxyException extends IOException { + private static final long serialVersionUID = 2241537397104426186L; + + public final String httpResponse; + public final int httpErrorCode; + + public HTTPProxyException(String httpResponse, int httpErrorCode) { + super("HTTP Proxy Error (" + httpErrorCode + " " + httpResponse + ")"); + this.httpResponse = httpResponse; + this.httpErrorCode = httpErrorCode; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/InteractiveCallback.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * An <code>InteractiveCallback</code> is used to respond to challenges sent + * by the server if authentication mode "keyboard-interactive" is selected. + * + * @see Connection#authenticateWithKeyboardInteractive(String, + * String[], InteractiveCallback) + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public interface InteractiveCallback { + /** + * This callback interface is used during a "keyboard-interactive" + * authentication. Every time the server sends a set of challenges (however, + * most often just one challenge at a time), this callback function will be + * called to give your application a chance to talk to the user and to + * determine the response(s). + * <p> + * Some copy-paste information from the standard: a command line interface + * (CLI) client SHOULD print the name and instruction (if non-empty), adding + * newlines. Then for each prompt in turn, the client SHOULD display the + * prompt and read the user input. The name and instruction fields MAY be + * empty strings, the client MUST be prepared to handle this correctly. The + * prompt field(s) MUST NOT be empty strings. + * <p> + * Please refer to draft-ietf-secsh-auth-kbdinteract-XX.txt for the details. + * <p> + * Note: clients SHOULD use control character filtering as discussed in + * RFC4251 to avoid attacks by including + * terminal control characters in the fields to be displayed. + * + * @param name + * the name String sent by the server. + * @param instruction + * the instruction String sent by the server. + * @param numPrompts + * number of prompts - may be zero (in this case, you should just + * return a String array of length zero). + * @param prompt + * an array (length <code>numPrompts</code>) of Strings + * @param echo + * an array (length <code>numPrompts</code>) of booleans. For + * each prompt, the corresponding echo field indicates whether or + * not the user input should be echoed as characters are typed. + * @return an array of reponses - the array size must match the parameter + * <code>numPrompts</code>. + */ + public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) + throws Exception; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/KnownHosts.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,814 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2; + +import java.io.BufferedReader; +import java.io.CharArrayReader; +import java.io.CharArrayWriter; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.DigestException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import ch.ethz.ssh2.crypto.Base64; +import ch.ethz.ssh2.crypto.SecureRandomFix; +import ch.ethz.ssh2.crypto.digest.Digest; +import ch.ethz.ssh2.crypto.digest.HMAC; +import ch.ethz.ssh2.crypto.digest.MD5; +import ch.ethz.ssh2.crypto.digest.SHA1; + +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey; +import ch.ethz.ssh2.signature.DSASHA1Verify; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; +import ch.ethz.ssh2.signature.RSASHA1Verify; +import ch.ethz.ssh2.util.StringEncoder; + +/** + * The <code>KnownHosts</code> class is a handy tool to verify received server hostkeys + * based on the information in <code>known_hosts</code> files (the ones used by OpenSSH). + * <p/> + * It offers basically an in-memory database for known_hosts entries, as well as some + * helper functions. Entries from a <code>known_hosts</code> file can be loaded at construction time. + * It is also possible to add more keys later (e.g., one can parse different + * <code>known_hosts<code> files). + * <p/> + * It is a thread safe implementation, therefore, you need only to instantiate one + * <code>KnownHosts</code> for your whole application. + * + * @author Christian Plattner + * @version $Id: KnownHosts.java 152 2014-04-28 11:02:23Z dkocher@sudo.ch $ + */ + +public class KnownHosts { + public static final int HOSTKEY_IS_OK = 0; + public static final int HOSTKEY_IS_NEW = 1; + public static final int HOSTKEY_HAS_CHANGED = 2; + + private class KnownHostsEntry { + String[] patterns; + PublicKey key; + + KnownHostsEntry(String[] patterns, PublicKey key) { + this.patterns = patterns; + this.key = key; + } + } + + private final LinkedList<KnownHostsEntry> publicKeys = new LinkedList<KnownHosts.KnownHostsEntry>(); + + public KnownHosts() { + } + + public KnownHosts(char[] knownHostsData) throws IOException { + initialize(knownHostsData); + } + + public KnownHosts(String knownHosts) throws IOException { + initialize(new File(knownHosts)); + } + + public KnownHosts(File knownHosts) throws IOException { + initialize(knownHosts); + } + + /** + * Adds a single public key entry to the database. Note: this will NOT add the public key + * to any physical file (e.g., "~/.ssh/known_hosts") - use <code>addHostkeyToFile()</code> for that purpose. + * This method is designed to be used in a {@link ServerHostKeyVerifier}. + * + * @param hostnames a list of hostname patterns - at least one most be specified. Check out the + * OpenSSH sshd man page for a description of the pattern matching algorithm. + * @param serverHostKeyAlgorithm as passed to the {@link ServerHostKeyVerifier}. + * @param serverHostKey as passed to the {@link ServerHostKeyVerifier}. + * @throws IOException + */ + public void addHostkey(String hostnames[], String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { + if (hostnames == null) { + throw new IllegalArgumentException("hostnames may not be null"); + } + + if ("ssh-rsa".equals(serverHostKeyAlgorithm)) { + RSAPublicKey rpk = RSASHA1Verify.decodeSSHRSAPublicKey(serverHostKey); + + synchronized (publicKeys) { + publicKeys.add(new KnownHostsEntry(hostnames, rpk)); + } + } + else if ("ssh-dss".equals(serverHostKeyAlgorithm)) { + DSAPublicKey dpk = DSASHA1Verify.decodeSSHDSAPublicKey(serverHostKey); + + synchronized (publicKeys) { + publicKeys.add(new KnownHostsEntry(hostnames, dpk)); + } + } + else if (serverHostKeyAlgorithm.startsWith("ecdsa-sha2-")) { + ECPublicKey epk = ECDSASHA2Verify.decodeSSHECDSAPublicKey(serverHostKey); + + synchronized (publicKeys) { + publicKeys.add(new KnownHostsEntry(hostnames, epk)); + } + } + else { + throw new IOException(String.format("Unknown host key type %s", serverHostKeyAlgorithm)); + } + } + + /** + * Parses the given known_hosts data and adds entries to the database. + * + * @param knownHostsData + * @throws IOException + */ + public void addHostkeys(char[] knownHostsData) throws IOException { + initialize(knownHostsData); + } + + /** + * Parses the given known_hosts file and adds entries to the database. + * + * @param knownHosts + * @throws IOException + */ + public void addHostkeys(File knownHosts) throws IOException { + initialize(knownHosts); + } + + /** + * Generate the hashed representation of the given hostname. Useful for adding entries + * with hashed hostnames to a known_hosts file. (see -H option of OpenSSH key-gen). + * + * @param hostname + * @return the hashed representation, e.g., "|1|cDhrv7zwEUV3k71CEPHnhHZezhA=|Xo+2y6rUXo2OIWRAYhBOIijbJMA=" + */ + public static String createHashedHostname(String hostname) throws IOException { + SHA1 sha1 = new SHA1(); + byte[] salt = new byte[sha1.getDigestLength()]; + new SecureRandomFix().nextBytes(salt); + byte[] hash; + + try { + hash = hmacSha1Hash(salt, hostname); + } + catch (IOException e) { + throw new IOException(e); + } + + String base64_salt = new String(Base64.encode(salt)); + String base64_hash = new String(Base64.encode(hash)); + return String.format("|1|%s|%s", base64_salt, base64_hash); + } + + private static byte[] hmacSha1Hash(byte[] salt, String hostname) throws IOException { + SHA1 sha1 = new SHA1(); + + if (salt.length != sha1.getDigestLength()) { + throw new IllegalArgumentException("Salt has wrong length (" + salt.length + ")"); + } + + try { + HMAC hmac = new HMAC(sha1, salt, salt.length); + hmac.update(StringEncoder.GetBytes(hostname)); + byte[] dig = new byte[hmac.getDigestLength()]; + hmac.digest(dig); + return dig; + } + catch (DigestException e) { + throw new IOException(e); + } + } + + private boolean checkHashed(String entry, String hostname) { + if (entry.startsWith("|1|") == false) { + return false; + } + + int delim_idx = entry.indexOf('|', 3); + + if (delim_idx == -1) { + return false; + } + + String salt_base64 = entry.substring(3, delim_idx); + String hash_base64 = entry.substring(delim_idx + 1); + byte[] salt; + byte[] hash; + + try { + salt = Base64.decode(salt_base64.toCharArray()); + hash = Base64.decode(hash_base64.toCharArray()); + } + catch (IOException e) { + return false; + } + + SHA1 sha1 = new SHA1(); + + if (salt.length != sha1.getDigestLength()) { + return false; + } + + byte[] dig = new byte[0]; + + try { + dig = hmacSha1Hash(salt, hostname); + } + catch (IOException e) { + return false; + } + + for (int i = 0; i < dig.length; i++) { + if (dig[i] != hash[i]) { + return false; + } + } + + return true; + } + + private int checkKey(String remoteHostname, PublicKey remoteKey) { + int result = HOSTKEY_IS_NEW; + + synchronized (publicKeys) { + for (KnownHostsEntry ke : publicKeys) { + if (hostnameMatches(ke.patterns, remoteHostname) == false) { + continue; + } + + boolean res = matchKeys(ke.key, remoteKey); + + if (res == true) { + return HOSTKEY_IS_OK; + } + + result = HOSTKEY_HAS_CHANGED; + } + } + + return result; + } + + private List<Object> getAllKeys(String hostname) { + List<Object> keys = new ArrayList<Object>(); + + synchronized (publicKeys) { + for (KnownHostsEntry ke : publicKeys) { + if (hostnameMatches(ke.patterns, hostname) == false) { + continue; + } + + keys.add(ke.key); + } + } + + return keys; + } + + /** + * Try to find the preferred order of hostkey algorithms for the given hostname. + * Based on the type of hostkey that is present in the internal database + * (i.e., either <code>ssh-rsa</code> or <code>ssh-dss</code>) + * an ordered list of hostkey algorithms is returned which can be passed + * to <code>Connection.setServerHostKeyAlgorithms</code>. + * + * @param hostname + * @return <code>null</code> if no key for the given hostname is present or + * there are keys of multiple types present for the given hostname. Otherwise, + * an array with hostkey algorithms is returned (i.e., an array of length 2). + */ + public String[] getPreferredServerHostkeyAlgorithmOrder(String hostname) { + String[] algos = recommendHostkeyAlgorithms(hostname); + + if (algos != null) { + return algos; + } + + InetAddress[] ipAdresses; + + try { + ipAdresses = InetAddress.getAllByName(hostname); + } + catch (UnknownHostException e) { + return null; + } + + for (int i = 0; i < ipAdresses.length; i++) { + algos = recommendHostkeyAlgorithms(ipAdresses[i].getHostAddress()); + + if (algos != null) { + return algos; + } + } + + return null; + } + + private boolean hostnameMatches(String[] hostpatterns, String hostname) { + boolean isMatch = false; + boolean negate; + hostname = hostname.toLowerCase(); + + for (int k = 0; k < hostpatterns.length; k++) { + if (hostpatterns[k] == null) { + continue; + } + + String pattern; + + /* In contrast to OpenSSH we also allow negated hash entries (as well as hashed + * entries in lines with multiple entries). + */ + + if ((hostpatterns[k].length() > 0) && (hostpatterns[k].charAt(0) == '!')) { + pattern = hostpatterns[k].substring(1); + negate = true; + } + else { + pattern = hostpatterns[k]; + negate = false; + } + + /* Optimize, no need to check this entry */ + + if ((isMatch) && (negate == false)) { + continue; + } + + /* Now compare */ + + if (pattern.charAt(0) == '|') { + if (checkHashed(pattern, hostname)) { + if (negate) { + return false; + } + + isMatch = true; + } + } + else { + pattern = pattern.toLowerCase(); + + if ((pattern.indexOf('?') != -1) || (pattern.indexOf('*') != -1)) { + if (pseudoRegex(pattern.toCharArray(), 0, hostname.toCharArray(), 0)) { + if (negate) { + return false; + } + + isMatch = true; + } + } + else if (pattern.compareTo(hostname) == 0) { + if (negate) { + return false; + } + + isMatch = true; + } + } + } + + return isMatch; + } + + private void initialize(char[] knownHostsData) throws IOException { + BufferedReader br = new BufferedReader(new CharArrayReader(knownHostsData)); + + while (true) { + String line = br.readLine(); + + if (line == null) { + break; + } + + line = line.trim(); + + if (line.startsWith("#")) { + continue; + } + + String[] arr = line.split(" "); + + if (arr.length >= 3) { + if ((arr[1].compareTo("ssh-rsa") == 0) || + (arr[1].compareTo("ssh-dss") == 0) || + (arr[1].startsWith("ecdsa-sha2-"))) { + String[] hostnames = arr[0].split(","); + byte[] msg = Base64.decode(arr[2].toCharArray()); + + try { + addHostkey(hostnames, arr[1], msg); + } + catch (IOException e) { + continue; + } + } + } + } + } + + private void initialize(File knownHosts) throws IOException { + char[] buff = new char[512]; + CharArrayWriter cw = new CharArrayWriter(); + knownHosts.createNewFile(); + FileReader fr = new FileReader(knownHosts); + + while (true) { + int len = fr.read(buff); + + if (len < 0) { + break; + } + + cw.write(buff, 0, len); + } + + fr.close(); + initialize(cw.toCharArray()); + } + + private final boolean matchKeys(PublicKey key1, PublicKey key2) { + return key1.equals(key2); + } + + private boolean pseudoRegex(char[] pattern, int i, char[] match, int j) { + /* This matching logic is equivalent to the one present in OpenSSH 4.1 */ + while (true) { + /* Are we at the end of the pattern? */ + if (pattern.length == i) { + return (match.length == j); + } + + if (pattern[i] == '*') { + i++; + + if (pattern.length == i) { + return true; + } + + if ((pattern[i] != '*') && (pattern[i] != '?')) { + while (true) { + if ((pattern[i] == match[j]) && pseudoRegex(pattern, i + 1, match, j + 1)) { + return true; + } + + j++; + + if (match.length == j) { + return false; + } + } + } + + while (true) { + if (pseudoRegex(pattern, i, match, j)) { + return true; + } + + j++; + + if (match.length == j) { + return false; + } + } + } + + if (match.length == j) { + return false; + } + + if ((pattern[i] != '?') && (pattern[i] != match[j])) { + return false; + } + + i++; + j++; + } + } + + private String[] recommendHostkeyAlgorithms(String hostname) { + String preferredAlgo = null; + List<Object> keys = getAllKeys(hostname); + + for (Object key : keys) { + String thisAlgo; + + if (key instanceof RSAPublicKey) { + thisAlgo = "ssh-rsa"; + } + else if (key instanceof DSAPublicKey) { + thisAlgo = "ssh-dss"; + } + else if (key instanceof ECPublicKey) { + ECPublicKey ecPub = (ECPublicKey) key; + String keyType = ECDSASHA2Verify.getCurveName(ecPub.getParams().getCurve().getField().getFieldSize()); + thisAlgo = ECDSASHA2Verify.ECDSA_SHA2_PREFIX + keyType; + } + else { + continue; + } + + if (preferredAlgo != null) { + /* If we find different key types, then return null */ + if (preferredAlgo.compareTo(thisAlgo) != 0) { + return null; + } + } + else { + preferredAlgo = thisAlgo; + } + } + + /* If we did not find anything that we know of, return null */ + + if (preferredAlgo == null) { + return null; + } + + /* Now put the preferred algo to the start of the array. + * You may ask yourself why we do it that way - basically, we could just + * return only the preferred algorithm: since we have a saved key of that + * type (sent earlier from the remote host), then that should work out. + * However, imagine that the server is (for whatever reasons) not offering + * that type of hostkey anymore (e.g., "ssh-rsa" was disabled and + * now "ssh-dss" is being used). If we then do not let the server send us + * a fresh key of the new type, then we shoot ourself into the foot: + * the connection cannot be established and hence the user cannot decide + * if he/she wants to accept the new key. + */ + + if (preferredAlgo.equals("ssh-rsa")) { + return new String[] {"ssh-rsa", "ssh-dss", "ecdsa-sha2-nistp256"}; + } + + return new String[] {"ssh-dss", "ssh-rsa", "ecdsa-sha2-nistp256"}; + } + + /** + * Checks the internal hostkey database for the given hostkey. + * If no matching key can be found, then the hostname is resolved to an IP address + * and the search is repeated using that IP address. + * + * @param hostname the server's hostname, will be matched with all hostname patterns + * @param serverHostKeyAlgorithm type of hostkey, either <code>ssh-rsa</code> or <code>ssh-dss</code> + * @param serverHostKey the key blob + * @return <ul> + * <li><code>HOSTKEY_IS_OK</code>: the given hostkey matches an entry for the given hostname</li> + * <li><code>HOSTKEY_IS_NEW</code>: no entries found for this hostname and this type of hostkey</li> + * <li><code>HOSTKEY_HAS_CHANGED</code>: hostname is known, but with another key of the same type + * (man-in-the-middle attack?)</li> + * </ul> + * @throws IOException if the supplied key blob cannot be parsed or does not match the given hostkey type. + */ + public int verifyHostkey(String hostname, String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { + PublicKey remoteKey; + + if ("ssh-rsa".equals(serverHostKeyAlgorithm)) { + remoteKey = RSASHA1Verify.decodeSSHRSAPublicKey(serverHostKey); + } + else if ("ssh-dss".equals(serverHostKeyAlgorithm)) { + remoteKey = DSASHA1Verify.decodeSSHDSAPublicKey(serverHostKey); + } + else if (serverHostKeyAlgorithm.startsWith("ecdsa-sha2-")) { + remoteKey = ECDSASHA2Verify.decodeSSHECDSAPublicKey(serverHostKey); + } + else { + throw new IllegalArgumentException("Unknown hostkey type " + serverHostKeyAlgorithm); + } + + int result = checkKey(hostname, remoteKey); + + if (result == HOSTKEY_IS_OK) { + return result; + } + + InetAddress[] ipAdresses; + + try { + ipAdresses = InetAddress.getAllByName(hostname); + } + catch (UnknownHostException e) { + return result; + } + + for (int i = 0; i < ipAdresses.length; i++) { + int newresult = checkKey(ipAdresses[i].getHostAddress(), remoteKey); + + if (newresult == HOSTKEY_IS_OK) { + return newresult; + } + + if (newresult == HOSTKEY_HAS_CHANGED) { + result = HOSTKEY_HAS_CHANGED; + } + } + + return result; + } + + /** + * Adds a single public key entry to the a known_hosts file. + * This method is designed to be used in a {@link ServerHostKeyVerifier}. + * + * @param knownHosts the file where the publickey entry will be appended. + * @param hostnames a list of hostname patterns - at least one most be specified. Check out the + * OpenSSH sshd man page for a description of the pattern matching algorithm. + * @param serverHostKeyAlgorithm as passed to the {@link ServerHostKeyVerifier}. + * @param serverHostKey as passed to the {@link ServerHostKeyVerifier}. + * @throws IOException + */ + public static void addHostkeyToFile(File knownHosts, String[] hostnames, String serverHostKeyAlgorithm, + byte[] serverHostKey) throws IOException { + if ((hostnames == null) || (hostnames.length == 0)) { + throw new IllegalArgumentException("Need at least one hostname specification"); + } + + if ((serverHostKeyAlgorithm == null) || (serverHostKey == null)) { + throw new IllegalArgumentException(); + } + + CharArrayWriter writer = new CharArrayWriter(); + + for (int i = 0; i < hostnames.length; i++) { + if (i != 0) { + writer.write(','); + } + + writer.write(hostnames[i]); + } + + writer.write(' '); + writer.write(serverHostKeyAlgorithm); + writer.write(' '); + writer.write(Base64.encode(serverHostKey)); + writer.write("\n"); + char[] entry = writer.toCharArray(); + RandomAccessFile raf = new RandomAccessFile(knownHosts, "rw"); + long len = raf.length(); + + if (len > 0) { + raf.seek(len - 1); + int last = raf.read(); + + if (last != '\n') { + raf.write('\n'); + } + } + + raf.write(StringEncoder.GetBytes(new String(entry))); + raf.close(); + } + + /** + * Generates a "raw" fingerprint of a hostkey. + * + * @param type either "md5" or "sha1" + * @param keyType either "ssh-rsa" or "ssh-dss" or "ecdsa-sha2..." + * @param hostkey the hostkey + * @return the raw fingerprint + */ + static private byte[] rawFingerPrint(String type, String keyType, byte[] hostkey) throws IOException { + Digest dig; + + if ("md5".equals(type)) { + dig = new MD5(); + } + else if ("sha1".equals(type)) { + dig = new SHA1(); + } + else { + throw new IllegalArgumentException("Unknown hash type " + type); + } + + if ("ssh-rsa".equals(keyType)) { + } + else if ("ssh-dss".equals(keyType)) { + } + else if (keyType.startsWith("ecdsa-sha2-")) { + } + else { + throw new IllegalArgumentException("Unknown key type " + keyType); + } + + if (hostkey == null) { + throw new IllegalArgumentException("hostkey is null"); + } + + dig.update(hostkey); + byte[] res = new byte[dig.getDigestLength()]; + + try { + dig.digest(res); + } + catch (DigestException e) { + throw new IOException(e); + } + + return res; + } + + /** + * Convert a raw fingerprint to hex representation (XX:YY:ZZ...). + * + * @param fingerprint raw fingerprint + * @return the hex representation + */ + static private String rawToHexFingerprint(byte[] fingerprint) { + final char[] alpha = "0123456789abcdef".toCharArray(); + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < fingerprint.length; i++) { + if (i != 0) { + sb.append(':'); + } + + int b = fingerprint[i] & 0xff; + sb.append(alpha[b >> 4]); + sb.append(alpha[b & 15]); + } + + return sb.toString(); + } + + /** + * Convert a raw fingerprint to bubblebabble representation. + * + * @param raw raw fingerprint + * @return the bubblebabble representation + */ + static private String rawToBubblebabbleFingerprint(byte[] raw) { + final char[] v = "aeiouy".toCharArray(); + final char[] c = "bcdfghklmnprstvzx".toCharArray(); + StringBuilder sb = new StringBuilder(); + int seed = 1; + int rounds = (raw.length / 2) + 1; + sb.append('x'); + + for (int i = 0; i < rounds; i++) { + if (((i + 1) < rounds) || ((raw.length) % 2 != 0)) { + sb.append(v[(((raw[2 * i] >> 6) & 3) + seed) % 6]); + sb.append(c[(raw[2 * i] >> 2) & 15]); + sb.append(v[((raw[2 * i] & 3) + (seed / 6)) % 6]); + + if ((i + 1) < rounds) { + sb.append(c[(((raw[(2 * i) + 1])) >> 4) & 15]); + sb.append('-'); + sb.append(c[(((raw[(2 * i) + 1]))) & 15]); + // As long as seed >= 0, seed will be >= 0 afterwards + seed = ((seed * 5) + (((raw[2 * i] & 0xff) * 7) + (raw[(2 * i) + 1] & 0xff))) % 36; + } + } + else { + sb.append(v[seed % 6]); // seed >= 0, therefore index positive + sb.append('x'); + sb.append(v[seed / 6]); + } + } + + sb.append('x'); + return sb.toString(); + } + + /** + * Convert a ssh2 key-blob into a human readable hex fingerprint. + * Generated fingerprints are identical to those generated by OpenSSH. + * <p/> + * Example fingerprint: d0:cb:76:19:99:5a:03:fc:73:10:70:93:f2:44:63:47. + * + * @param keytype either "ssh-rsa" or "ssh-dss" or "ecdsa-sha2..." + * @param publickey key blob + * @return Hex fingerprint + */ + public static String createHexFingerprint(String keytype, byte[] publickey) throws IOException { + byte[] raw = rawFingerPrint("md5", keytype, publickey); + return rawToHexFingerprint(raw); + } + + /** + * Convert a ssh2 key-blob into a human readable bubblebabble fingerprint. + * The used bubblebabble algorithm (taken from OpenSSH) generates fingerprints + * that are easier to remember for humans. + * <p/> + * Example fingerprint: xofoc-bubuz-cazin-zufyl-pivuk-biduk-tacib-pybur-gonar-hotat-lyxux. + * + * @param keytype either "ssh-rsa" or "ssh-dss" + * @param publickey key data + * @return Bubblebabble fingerprint + */ + public static String createBubblebabbleFingerprint(String keytype, byte[] publickey) throws IOException { + byte[] raw = rawFingerPrint("sha1", keytype, publickey); + return rawToBubblebabbleFingerprint(raw); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/LocalPortForwarder.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; + +import ch.ethz.ssh2.channel.ChannelManager; +import ch.ethz.ssh2.channel.LocalAcceptThread; + +/** + * A <code>LocalPortForwarder</code> forwards TCP/IP connections to a local + * port via the secure tunnel to another host (which may or may not be identical + * to the remote SSH-2 server). Checkout {@link Connection#createLocalPortForwarder(int, String, int)} + * on how to create one. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class LocalPortForwarder { + final ChannelManager cm; + + final String host_to_connect; + + final int port_to_connect; + + final LocalAcceptThread lat; + + LocalPortForwarder(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) + throws IOException { + this.cm = cm; + this.host_to_connect = host_to_connect; + this.port_to_connect = port_to_connect; + lat = new LocalAcceptThread(cm, local_port, host_to_connect, port_to_connect); + lat.setDaemon(true); + lat.start(); + } + + LocalPortForwarder(ChannelManager cm, InetSocketAddress addr, String host_to_connect, int port_to_connect) + throws IOException { + this.cm = cm; + this.host_to_connect = host_to_connect; + this.port_to_connect = port_to_connect; + lat = new LocalAcceptThread(cm, addr, host_to_connect, port_to_connect); + lat.setDaemon(true); + lat.start(); + } + + /** + * Return the local socket address of the {@link ServerSocket} used to accept connections. + * @return + */ + public InetSocketAddress getLocalSocketAddress() { + return (InetSocketAddress) lat.getServerSocket().getLocalSocketAddress(); + } + + /** + * Stop TCP/IP forwarding of newly arriving connections. + * + * @throws IOException + */ + public void close() throws IOException { + lat.stopWorking(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/LocalStreamForwarder.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; + +import ch.ethz.ssh2.channel.Channel; +import ch.ethz.ssh2.channel.ChannelManager; + +/** + * A <code>LocalStreamForwarder</code> forwards an Input- and Outputstream + * pair via the secure tunnel to another host (which may or may not be identical + * to the remote SSH-2 server). + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class LocalStreamForwarder { + private ChannelManager cm; + + private Channel cn; + + LocalStreamForwarder(ChannelManager cm, String host_to_connect, int port_to_connect) throws IOException { + this.cm = cm; + cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, + InetAddress.getLocalHost().getHostAddress(), 0); + } + + /** + * @return An <code>InputStream</code> object. + * @throws IOException + */ + public InputStream getInputStream() throws IOException { + return cn.getStdoutStream(); + } + + /** + * Get the OutputStream. Please be aware that the implementation MAY use an + * internal buffer. To make sure that the buffered data is sent over the + * tunnel, you have to call the <code>flush</code> method of the + * <code>OutputStream</code>. To signal EOF, please use the + * <code>close</code> method of the <code>OutputStream</code>. + * + * @return An <code>OutputStream</code> object. + * @throws IOException + */ + public OutputStream getOutputStream() throws IOException { + return cn.getStdinStream(); + } + + /** + * Close the underlying SSH forwarding channel and free up resources. + * You can also use this method to force the shutdown of the underlying + * forwarding channel. Pending output (OutputStream not flushed) will NOT + * be sent. Pending input (InputStream) can still be read. If the shutdown + * operation is already in progress (initiated from either side), then this + * call is a no-op. + * + * @throws IOException + */ + public void close() throws IOException { + cm.closeChannel(cn, "Closed due to user request.", true); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/PacketFormatException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,13 @@ +package ch.ethz.ssh2; + +import java.io.IOException; + +/** + * @version $Id: PacketFormatException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class PacketFormatException extends IOException { + + public PacketFormatException(String message) { + super(message); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/PacketListener.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2011 David Kocher. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * @version $Id: PacketListener.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public interface PacketListener { + void read(String packet); + + void write(String packet); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/PacketTypeException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,24 @@ +package ch.ethz.ssh2; + +import java.io.IOException; + +/** + * @version $Id: PacketTypeException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class PacketTypeException extends IOException { + + public PacketTypeException() { + } + + public PacketTypeException(final String message) { + super(message); + } + + public PacketTypeException(final int packet) { + super(String.format("The SFTP server sent an unexpected packet type (%d)", packet)); + } + + public PacketTypeException(final int packet, final String message) { + super(String.format("The SFTP server sent an invalid packet type (%d). %s", packet, message)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ProxyData.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * An abstract marker interface implemented by all proxy data implementations. + * + * @see HTTPProxyData + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public abstract interface ProxyData { +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/PtySettings.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * PTY settings for a SSH session. Zero dimension parameters are ignored. The character/row dimensions + * override the pixel dimensions (when nonzero). Pixel dimensions refer to + * the drawable area of the window. The dimension parameters are only + * informational. The encoding of terminal modes (parameter + * <code>terminal_modes</code>) is described in RFC4254. + * + * @author Christian + */ +public class PtySettings { + /** + * TERM environment variable value (e.g., vt100) + */ + public String term; + + /** + * Terminal width, characters (e.g., 80) + */ + public int term_width_characters; + + /** + * Terminal height, rows (e.g., 24) + */ + public int term_height_characters; + + /** + * Terminal width, pixels (e.g., 640) + */ + public int term_width_pixels; + + /** + * Terminal height, pixels (e.g., 480) + */ + public int term_height_pixels; + + /** + * Encoded terminal modes + */ + public byte[] terminal_modes; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/RequestMismatchException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,17 @@ +package ch.ethz.ssh2; + +import java.io.IOException; + +/** + * @version $Id: RequestMismatchException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class RequestMismatchException extends IOException { + + public RequestMismatchException() { + super("The server sent an invalid id field."); + } + + public RequestMismatchException(final String message) { + super(message); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SCPClient.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,742 @@ +package ch.ethz.ssh2; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; + +/** + * A very basic <code>SCPClient</code> that can be used to copy files from/to + * the SSH-2 server. On the server side, the "scp" program must be in the PATH. + * <p/> + * This scp client is thread safe - you can download (and upload) different sets + * of files concurrently without any troubles. The <code>SCPClient</code> is + * actually mapping every request to a distinct {@link ch.ethz.ssh2.Session}. + * + * @author Christian Plattner, plattner@inf.ethz.ch + * @version $Id: SCPClient.java 85 2014-04-07 14:05:09Z dkocher@sudo.ch $ + */ + +public class SCPClient { + Connection conn; + + String charsetName = null; + + /** + * Set the charset used to convert between Java Unicode Strings and byte encodings + * used by the server for paths and file names. + * + * @param charset the name of the charset to be used or <code>null</code> to use the platform's + * default encoding. + * @throws IOException + * @see #getCharset() + */ + public void setCharset(String charset) throws IOException { + if (charset == null) { + charsetName = charset; + return; + } + + try { + Charset.forName(charset); + } + catch (UnsupportedCharsetException e) { + throw new IOException("This charset is not supported", e); + } + + charsetName = charset; + } + + /** + * The currently used charset for filename encoding/decoding. + * + * @return The name of the charset (<code>null</code> if the platform's default charset is being used) + * @see #setCharset(String) + */ + public String getCharset() { + return charsetName; + } + + public class LenNamePair { + public long length; + String filename; + } + + public SCPClient(Connection conn) { + if (conn == null) + throw new IllegalArgumentException("Cannot accept null argument!"); + + this.conn = conn; + } + + protected void readResponse(InputStream is) throws IOException { + int c = is.read(); + + if (c == 0) + return; + + if (c == -1) + throw new IOException("Remote scp terminated unexpectedly."); + + if ((c != 1) && (c != 2)) + throw new IOException("Remote scp sent illegal error code."); + + if (c == 2) + throw new IOException("Remote scp terminated with error."); + + String err = receiveLine(is); + throw new IOException("Remote scp terminated with error (" + err + ")."); + } + + protected String receiveLine(InputStream is) throws IOException { + StringBuilder sb = new StringBuilder(30); + + while (true) { + /* This is a random limit - if your path names are longer, then adjust it */ + if (sb.length() > 8192) + throw new IOException("Remote scp sent a too long line"); + + int c = is.read(); + + if (c < 0) + throw new IOException("Remote scp terminated unexpectedly."); + + if (c == '\n') + break; + + sb.append((char) c); + } + + return sb.toString(); + } + + protected LenNamePair parseCLine(String line) throws IOException { + /* Minimum line: "xxxx y z" ---> 8 chars */ + if (line.length() < 8) + throw new IOException("Malformed C line sent by remote SCP binary, line too short."); + + if ((line.charAt(4) != ' ') || (line.charAt(5) == ' ')) + throw new IOException("Malformed C line sent by remote SCP binary."); + + int length_name_sep = line.indexOf(' ', 5); + + if (length_name_sep == -1) + throw new IOException("Malformed C line sent by remote SCP binary."); + + String length_substring = line.substring(5, length_name_sep); + String name_substring = line.substring(length_name_sep + 1); + + if ((length_substring.length() <= 0) || (name_substring.length() <= 0)) + throw new IOException("Malformed C line sent by remote SCP binary."); + + if ((6 + length_substring.length() + name_substring.length()) != line.length()) + throw new IOException("Malformed C line sent by remote SCP binary."); + + final long len; + + try { + len = Long.parseLong(length_substring); + } + catch (NumberFormatException e) { + throw new IOException("Malformed C line sent by remote SCP binary, cannot parse file length."); + } + + if (len < 0) + throw new IOException("Malformed C line sent by remote SCP binary, illegal file length."); + + LenNamePair lnp = new LenNamePair(); + lnp.length = len; + lnp.filename = name_substring; + return lnp; + } + + /** + * The session for opened for this SCP transfer must be closed using + * SCPOutputStream#close + * + * @param remoteFile + * @param length The size of the file to send + * @param remoteTargetDirectory + * @param mode + * @return + * @throws IOException + */ + public SCPOutputStream put(final String remoteFile, long length, String remoteTargetDirectory, String mode) + throws IOException { + Session sess = null; + + if (null == remoteFile) + throw new IllegalArgumentException("Null argument."); + + if (null == remoteTargetDirectory) + remoteTargetDirectory = ""; + + if (null == mode) + mode = "0600"; + + if (mode.length() != 4) + throw new IllegalArgumentException("Invalid mode."); + + for (int i = 0; i < mode.length(); i++) + if (Character.isDigit(mode.charAt(i)) == false) + throw new IllegalArgumentException("Invalid mode."); + + remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; + String cmd = "scp -t -d \"" + remoteTargetDirectory + "\""; + sess = conn.openSession(); + sess.execCommand(cmd, charsetName); + return new SCPOutputStream(this, sess, remoteFile, length, mode); + } + + /** + * The session for opened for this SCP transfer must be closed using + * SCPInputStream#close + * + * @param remoteFile + * @return + * @throws IOException + */ + public SCPInputStream get(final String remoteFile) throws IOException { + Session sess = null; + + if (null == remoteFile) + throw new IllegalArgumentException("Null argument."); + + if (remoteFile.length() == 0) + throw new IllegalArgumentException("Cannot accept empty filename."); + + String cmd = "scp -f"; + cmd += (" \"" + remoteFile + "\""); + sess = conn.openSession(); + sess.execCommand(cmd, charsetName); + return new SCPInputStream(this, sess); + } + private void sendBytes(Session sess, byte[] data, String fileName, String mode) throws IOException { + OutputStream os = sess.getStdin(); + InputStream is = new BufferedInputStream(sess.getStdout(), 512); + readResponse(is); + String cline = "C" + mode + " " + data.length + " " + fileName + "\n"; + os.write(cline.getBytes("ISO-8859-1")); + os.flush(); + readResponse(is); + os.write(data, 0, data.length); + os.write(0); + os.flush(); + readResponse(is); + os.write("E\n".getBytes("ISO-8859-1")); + os.flush(); + } + + private void sendFiles(Session sess, String[] files, String[] remoteFiles, String mode) throws IOException { + byte[] buffer = new byte[8192]; + OutputStream os = new BufferedOutputStream(sess.getStdin(), 40000); + InputStream is = new BufferedInputStream(sess.getStdout(), 512); + readResponse(is); + + for (int i = 0; i < files.length; i++) { + File f = new File(files[i]); + long remain = f.length(); + String remoteName; + + if ((remoteFiles != null) && (remoteFiles.length > i) && (remoteFiles[i] != null)) + remoteName = remoteFiles[i]; + else + remoteName = f.getName(); + + String cline = "C" + mode + " " + remain + " " + remoteName + "\n"; + os.write(cline.getBytes("ISO-8859-1")); + os.flush(); + readResponse(is); + FileInputStream fis = null; + + try { + fis = new FileInputStream(f); + + while (remain > 0) { + int trans; + + if (remain > buffer.length) + trans = buffer.length; + else + trans = (int) remain; + + if (fis.read(buffer, 0, trans) != trans) + throw new IOException("Cannot read enough from local file " + files[i]); + + os.write(buffer, 0, trans); + remain -= trans; + } + } + finally { + if (fis != null) + fis.close(); + } + + os.write(0); + os.flush(); + readResponse(is); + } + + os.write("E\n".getBytes("ISO-8859-1")); + os.flush(); + } + + private void receiveFiles(Session sess, OutputStream[] targets) throws IOException { + byte[] buffer = new byte[8192]; + OutputStream os = new BufferedOutputStream(sess.getStdin(), 512); + InputStream is = new BufferedInputStream(sess.getStdout(), 40000); + os.write(0x0); + os.flush(); + + for (int i = 0; i < targets.length; i++) { + LenNamePair lnp = null; + + while (true) { + int c = is.read(); + + if (c < 0) + throw new IOException("Remote scp terminated unexpectedly."); + + String line = receiveLine(is); + + if (c == 'T') { + /* Ignore modification times */ + continue; + } + + if ((c == 1) || (c == 2)) + throw new IOException("Remote SCP error: " + line); + + if (c == 'C') { + lnp = parseCLine(line); + break; + } + + throw new IOException("Remote SCP error: " + ((char) c) + line); + } + + os.write(0x0); + os.flush(); + long remain = lnp.length; + + while (remain > 0) { + int trans; + + if (remain > buffer.length) + trans = buffer.length; + else + trans = (int) remain; + + int this_time_received = is.read(buffer, 0, trans); + + if (this_time_received < 0) { + throw new IOException("Remote scp terminated connection unexpectedly"); + } + + targets[i].write(buffer, 0, this_time_received); + remain -= this_time_received; + } + + readResponse(is); + os.write(0x0); + os.flush(); + } + } + + private void receiveFiles(Session sess, String[] files, String target) throws IOException { + byte[] buffer = new byte[8192]; + OutputStream os = new BufferedOutputStream(sess.getStdin(), 512); + InputStream is = new BufferedInputStream(sess.getStdout(), 40000); + os.write(0x0); + os.flush(); + + for (int i = 0; i < files.length; i++) { + LenNamePair lnp = null; + + while (true) { + int c = is.read(); + + if (c < 0) + throw new IOException("Remote scp terminated unexpectedly."); + + String line = receiveLine(is); + + if (c == 'T') { + /* Ignore modification times */ + continue; + } + + if ((c == 1) || (c == 2)) + throw new IOException("Remote SCP error: " + line); + + if (c == 'C') { + lnp = parseCLine(line); + break; + } + + throw new IOException("Remote SCP error: " + ((char) c) + line); + } + + os.write(0x0); + os.flush(); + File f = new File(target + File.separatorChar + lnp.filename); + FileOutputStream fop = null; + + try { + fop = new FileOutputStream(f); + long remain = lnp.length; + + while (remain > 0) { + int trans; + + if (remain > buffer.length) + trans = buffer.length; + else + trans = (int) remain; + + int this_time_received = is.read(buffer, 0, trans); + + if (this_time_received < 0) { + throw new IOException("Remote scp terminated connection unexpectedly"); + } + + fop.write(buffer, 0, this_time_received); + remain -= this_time_received; + } + } + finally { + if (fop != null) + fop.close(); + } + + readResponse(is); + os.write(0x0); + os.flush(); + } + } + + /** + * Copy a local file to a remote directory, uses mode 0600 when creating the + * file on the remote side. + * + * @param localFile + * Path and name of local file. + * @param remoteTargetDirectory + * Remote target directory. Use an empty string to specify the + * default directory. + * + * @throws IOException + */ + public void put(String localFile, String remoteTargetDirectory) throws IOException { + put(new String[] { localFile }, remoteTargetDirectory, "0600"); + } + + /** + * Copy a set of local files to a remote directory, uses mode 0600 when + * creating files on the remote side. + * + * @param localFiles + * Paths and names of local file names. + * @param remoteTargetDirectory + * Remote target directory. Use an empty string to specify the + * default directory. + * + * @throws IOException + */ + + public void put(String[] localFiles, String remoteTargetDirectory) throws IOException { + put(localFiles, remoteTargetDirectory, "0600"); + } + + /** + * Copy a local file to a remote directory, uses the specified mode when + * creating the file on the remote side. + * + * @param localFile + * Path and name of local file. + * @param remoteTargetDirectory + * Remote target directory. Use an empty string to specify the + * default directory. + * @param mode + * a four digit string (e.g., 0644, see "man chmod", "man open") + * @throws IOException + */ + public void put(String localFile, String remoteTargetDirectory, String mode) throws IOException { + put(new String[] { localFile }, remoteTargetDirectory, mode); + } + + /** + * Copy a local file to a remote directory, uses the specified mode and + * remote filename when creating the file on the remote side. + * + * @param localFile + * Path and name of local file. + * @param remoteFileName + * The name of the file which will be created in the remote + * target directory. + * @param remoteTargetDirectory + * Remote target directory. Use an empty string to specify the + * default directory. + * @param mode + * a four digit string (e.g., 0644, see "man chmod", "man open") + * @throws IOException + */ + public void put(String localFile, String remoteFileName, String remoteTargetDirectory, String mode) + throws IOException { + put(new String[] { localFile }, new String[] { remoteFileName }, remoteTargetDirectory, mode); + } + + /** + * Create a remote file and copy the contents of the passed byte array into + * it. Uses mode 0600 for creating the remote file. + * + * @param data + * the data to be copied into the remote file. + * @param remoteFileName + * The name of the file which will be created in the remote + * target directory. + * @param remoteTargetDirectory + * Remote target directory. Use an empty string to specify the + * default directory. + * @throws IOException + */ + + public void put(byte[] data, String remoteFileName, String remoteTargetDirectory) throws IOException { + put(data, remoteFileName, remoteTargetDirectory, "0600"); + } + + /** + * Create a remote file and copy the contents of the passed byte array into + * it. The method use the specified mode when creating the file on the + * remote side. + * + * @param data + * the data to be copied into the remote file. + * @param remoteFileName + * The name of the file which will be created in the remote + * target directory. + * @param remoteTargetDirectory + * Remote target directory. Use an empty string to specify the + * default directory. + * @param mode + * a four digit string (e.g., 0644, see "man chmod", "man open") + * @throws IOException + */ + public void put(byte[] data, String remoteFileName, String remoteTargetDirectory, String mode) throws IOException { + Session sess = null; + + if ((remoteFileName == null) || (remoteTargetDirectory == null) || (mode == null)) + throw new IllegalArgumentException("Null argument."); + + if (mode.length() != 4) + throw new IllegalArgumentException("Invalid mode."); + + for (int i = 0; i < mode.length(); i++) + if (Character.isDigit(mode.charAt(i)) == false) + throw new IllegalArgumentException("Invalid mode."); + + remoteTargetDirectory = remoteTargetDirectory.trim(); + remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; + String cmd = "scp -t -d " + remoteTargetDirectory; + + try { + sess = conn.openSession(); + sess.execCommand(cmd); + sendBytes(sess, data, remoteFileName, mode); + } + catch (IOException e) { + throw(IOException) new IOException("Error during SCP transfer.").initCause(e); + } + finally { + if (sess != null) + sess.close(); + } + } + + /** + * Copy a set of local files to a remote directory, uses the specified mode + * when creating the files on the remote side. + * + * @param localFiles + * Paths and names of the local files. + * @param remoteTargetDirectory + * Remote target directory. Use an empty string to specify the + * default directory. + * @param mode + * a four digit string (e.g., 0644, see "man chmod", "man open") + * @throws IOException + */ + public void put(String[] localFiles, String remoteTargetDirectory, String mode) throws IOException { + put(localFiles, null, remoteTargetDirectory, mode); + } + + public void put(String[] localFiles, String[] remoteFiles, String remoteTargetDirectory, String mode) + throws IOException { + Session sess = null; + + /* + * remoteFiles may be null, indicating that the local filenames shall be + * used + */ + + if ((localFiles == null) || (remoteTargetDirectory == null) || (mode == null)) + throw new IllegalArgumentException("Null argument."); + + if (mode.length() != 4) + throw new IllegalArgumentException("Invalid mode."); + + for (int i = 0; i < mode.length(); i++) + if (Character.isDigit(mode.charAt(i)) == false) + throw new IllegalArgumentException("Invalid mode."); + + if (localFiles.length == 0) + return; + + remoteTargetDirectory = remoteTargetDirectory.trim(); + remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; + String cmd = "scp -t -d " + remoteTargetDirectory; + + for (int i = 0; i < localFiles.length; i++) { + if (localFiles[i] == null) + throw new IllegalArgumentException("Cannot accept null filename."); + } + + try { + sess = conn.openSession(); + sess.execCommand(cmd); + sendFiles(sess, localFiles, remoteFiles, mode); + } + catch (IOException e) { + throw(IOException) new IOException("Error during SCP transfer.").initCause(e); + } + finally { + if (sess != null) + sess.close(); + } + } + + /** + * Download a file from the remote server to a local directory. + * + * @param remoteFile + * Path and name of the remote file. + * @param localTargetDirectory + * Local directory to put the downloaded file. + * + * @throws IOException + */ + public void get(String remoteFile, String localTargetDirectory) throws IOException { + get(new String[] { remoteFile }, localTargetDirectory); + } + + /** + * Download a file from the remote server and pipe its contents into an + * <code>OutputStream</code>. Please note that, to enable flexible usage + * of this method, the <code>OutputStream</code> will not be closed nor + * flushed. + * + * @param remoteFile + * Path and name of the remote file. + * @param target + * OutputStream where the contents of the file will be sent to. + * @throws IOException + */ + public void get(String remoteFile, OutputStream target) throws IOException { + get(new String[] { remoteFile }, new OutputStream[] { target }); + } + + private void get(String remoteFiles[], OutputStream[] targets) throws IOException { + Session sess = null; + + if ((remoteFiles == null) || (targets == null)) + throw new IllegalArgumentException("Null argument."); + + if (remoteFiles.length != targets.length) + throw new IllegalArgumentException("Length of arguments does not match."); + + if (remoteFiles.length == 0) + return; + + String cmd = "scp -f"; + + for (int i = 0; i < remoteFiles.length; i++) { + if (remoteFiles[i] == null) + throw new IllegalArgumentException("Cannot accept null filename."); + + String tmp = remoteFiles[i].trim(); + + if (tmp.length() == 0) + throw new IllegalArgumentException("Cannot accept empty filename."); + + cmd += (" " + tmp); + } + + try { + sess = conn.openSession(); + sess.execCommand(cmd); + receiveFiles(sess, targets); + } + catch (IOException e) { + throw(IOException) new IOException("Error during SCP transfer.").initCause(e); + } + finally { + if (sess != null) + sess.close(); + } + } + + /** + * Download a set of files from the remote server to a local directory. + * + * @param remoteFiles + * Paths and names of the remote files. + * @param localTargetDirectory + * Local directory to put the downloaded files. + * + * @throws IOException + */ + public void get(String remoteFiles[], String localTargetDirectory) throws IOException { + Session sess = null; + + if ((remoteFiles == null) || (localTargetDirectory == null)) + throw new IllegalArgumentException("Null argument."); + + if (remoteFiles.length == 0) + return; + + String cmd = "scp -f"; + + for (int i = 0; i < remoteFiles.length; i++) { + if (remoteFiles[i] == null) + throw new IllegalArgumentException("Cannot accept null filename."); + + String tmp = remoteFiles[i].trim(); + + if (tmp.length() == 0) + throw new IllegalArgumentException("Cannot accept empty filename."); + + cmd += (" " + tmp); + } + + try { + sess = conn.openSession(); + sess.execCommand(cmd); + receiveFiles(sess, remoteFiles, localTargetDirectory); + } + catch (IOException e) { + throw(IOException) new IOException("Error during SCP transfer.").initCause(e); + } + finally { + if (sess != null) + sess.close(); + } + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SCPInputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2011 David Kocher. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * @version $Id: SCPInputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class SCPInputStream extends BufferedInputStream { + private Session session; + + /** + * Bytes remaining to be read from the stream + */ + private long remaining; + + public SCPInputStream(SCPClient client, Session session) throws IOException { + super(session.getStdout()); + this.session = session; + OutputStream os = new BufferedOutputStream(session.getStdin(), 512); + os.write(0x0); + os.flush(); + final SCPClient.LenNamePair lnp; + + while (true) { + int c = session.getStdout().read(); + + if (c < 0) { + throw new IOException("Remote scp terminated unexpectedly."); + } + + String line = client.receiveLine(session.getStdout()); + + if (c == 'T') { + /* Ignore modification times */ + continue; + } + + if ((c == 1) || (c == 2)) { + throw new IOException("Remote SCP error: " + line); + } + + if (c == 'C') { + lnp = client.parseCLine(line); + break; + } + + throw new IOException("Remote SCP error: " + ((char) c) + line); + } + + os.write(0x0); + os.flush(); + this.remaining = lnp.length; + } + + @Override + public int read() throws IOException { + if (!(remaining > 0)) { + return -1; + } + + int b = super.read(); + + if (b < 0) { + throw new IOException("Remote scp terminated connection unexpectedly"); + } + + remaining -= 1; + return b; + } + + @Override + public int read(byte b[], int off, int len) throws IOException { + if (!(remaining > 0)) { + return -1; + } + + int trans = (int) remaining; + + if (remaining > len) { + trans = len; + } + + int read = super.read(b, off, trans); + + if (read < 0) { + throw new IOException("Remote scp terminated connection unexpectedly"); + } + + remaining -= read; + return read; + } + + @Override + public void close() throws IOException { + try { + session.getStdin().write(0x0); + session.getStdin().flush(); + } + finally { + if (session != null) { + session.close(); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SCPOutputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011 David Kocher. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import ch.ethz.ssh2.util.StringEncoder; + +/** + * @version $Id: SCPOutputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class SCPOutputStream extends BufferedOutputStream { + + private Session session; + + private SCPClient scp; + + public SCPOutputStream(SCPClient client, Session session, final String remoteFile, long length, String mode) throws IOException { + super(session.getStdin(), 40000); + this.session = session; + this.scp = client; + InputStream is = new BufferedInputStream(session.getStdout(), 512); + scp.readResponse(is); + String cline = "C" + mode + " " + length + " " + remoteFile + "\n"; + super.write(StringEncoder.GetBytes(cline)); + this.flush(); + scp.readResponse(is); + } + + @Override + public void close() throws IOException { + try { + this.write(0); + this.flush(); + scp.readResponse(session.getStdout()); + this.write(StringEncoder.GetBytes("E\n")); + this.flush(); + } + finally { + if (session != null) + session.close(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPClient.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,225 @@ +package ch.ethz.ssh2; + +import java.io.IOException; +import java.util.List; + +/** + * @version $Id: SFTPClient.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public interface SFTPClient { + + /** + * Retrieve the file attributes of an open file. + * + * @param handle a SFTPv3FileHandle handle. + * @return a SFTPv3FileAttributes object. + * @throws IOException + */ + SFTPFileAttributes fstat(SFTPFileHandle handle) throws IOException; + + /** + * Retrieve the file attributes of a file. This method + * follows symbolic links on the server. + * + * @param path See the {@link SFTPClient comment} for the class for more details. + * @return a SFTPv3FileAttributes object. + * @throws IOException + * @see #lstat(String) + */ + SFTPFileAttributes stat(String path) throws IOException; + + /** + * Retrieve the file attributes of a file. This method + * does NOT follow symbolic links on the server. + * + * @param path See the {@link SFTPClient comment} for the class for more details. + * @return a SFTPv3FileAttributes object. + * @throws IOException + * @see #stat(String) + */ + SFTPFileAttributes lstat(String path) throws IOException; + + /** + * Read the target of a symbolic link. Note: OpenSSH (as of version 4.4) gets very upset + * (SSH_FX_BAD_MESSAGE error) if you want to read the target of a file that is not a + * symbolic link. Better check first with {@link #lstat(String)}. + * + * @param path See the {@link SFTPClient comment} for the class for more details. + * @return The target of the link. + * @throws IOException + */ + String readLink(String path) throws IOException; + + /** + * Modify the attributes of a file. Used for operations such as changing + * the ownership, permissions or access times, as well as for truncating a file. + * + * @param path See the {@link SFTPClient comment} for the class for more details. + * @param attr A SFTPv3FileAttributes object. Specifies the modifications to be + * made to the attributes of the file. Empty fields will be ignored. + * @throws IOException + */ + void setstat(String path, SFTPFileAttributes attr) throws IOException; + + /** + * Modify the attributes of a file. Used for operations such as changing + * the ownership, permissions or access times, as well as for truncating a file. + * + * @param handle a SFTPv3FileHandle handle + * @param attr A SFTPv3FileAttributes object. Specifies the modifications to be + * made to the attributes of the file. Empty fields will be ignored. + * @throws IOException + */ + void fsetstat(SFTPFileHandle handle, SFTPFileAttributes attr) throws IOException; + + /** + * Create a symbolic link on the server. Creates a link "src" that points + * to "target". + * + * @param src See the {@link SFTPClient comment} for the class for more details. + * @param target See the {@link SFTPClient comment} for the class for more details. + * @throws IOException + */ + void createSymlink(String src, String target) throws IOException; + + /** + * Create a symbolic link on the server. Creates a link "src" that points + * to "target". + * + * @param src See the {@link SFTPClient comment} for the class for more details. + * @param target See the {@link SFTPClient comment} for the class for more details. + * @throws IOException + */ + void createHardlink(String src, String target) throws IOException; + + /** + * Have the server canonicalize any given path name to an absolute path. + * This is useful for converting path names containing ".." components or + * relative pathnames without a leading slash into absolute paths. + * + * @param path See the {@link SFTPClient comment} for the class for more details. + * @return An absolute path. + * @throws IOException + */ + String canonicalPath(String path) throws IOException; + + void setCharset(String charset) throws IOException; + + String getCharset(); + + SFTPFileHandle openDirectory(String path) throws IOException; + + boolean isConnected(); + + void close(); + + List<? extends SFTPDirectoryEntry> ls(String dirName) throws IOException; + + /** + * Create a new directory. + * + * @param name See the {@link SFTPClient comment} for the class for more details. + * @param posixPermissions the permissions for this directory, e.g., "0700" (remember that + * this is octal noation). The server will likely apply a umask. + * @throws IOException + */ + void mkdir(String name, int posixPermissions) throws IOException; + + /** + * Remove a file. + * + * @param filename See the {@link SFTPClient comment} for the class for more details. + * @throws IOException + */ + void rm(String filename) throws IOException; + + /** + * Remove an empty directory. + * + * @param dirName See the {@link SFTPClient comment} for the class for more details. + * @throws IOException + */ + void rmdir(String dirName) throws IOException; + + /** + * Move a file or directory. + * + * @param oldPath See the {@link SFTPClient comment} for the class for more details. + * @param newPath See the {@link SFTPClient comment} for the class for more details. + * @throws IOException + */ + void mv(String oldPath, String newPath) throws IOException; + + /** + * Create a file and open it for reading and writing. + * Same as {@link #createFile(String, SFTPFileAttributes) createFile(filename, null)}. + * + * @param filename See the {@link SFTPClient comment} for the class for more details. + * @return a SFTPv3FileHandle handle + * @throws IOException + */ + SFTPFileHandle createFile(String filename) throws IOException; + + /** + * Create a file and open it for reading and writing. + * You can specify the default attributes of the file (the server may or may + * not respect your wishes). + * + * @param filename See the {@link SFTPv3Client comment} for the class for more details. + * @param attr may be <code>null</code> to use server defaults. Probably only + * the <code>uid</code>, <code>gid</code> and <code>permissions</code> + * (remember the server may apply a umask) entries of the {@link SFTPv3FileHandle} + * structure make sense. You need only to set those fields where you want + * to override the server's defaults. + * @return a SFTPv3FileHandle handle + * @throws IOException + */ + SFTPFileHandle createFile(String filename, SFTPFileAttributes attr) throws IOException; + + SFTPFileHandle openFile(String filename, int flags) throws IOException; + + /** + * Read bytes from a file in a parallel fashion. As many bytes as you want will be read. + * <p/> + * <ul> + * <li>The server will read as many bytes as it can from the file (up to <code>len</code>), + * and return them.</li> + * <li>If EOF is encountered before reading any data, <code>-1</code> is returned. + * <li>If an error occurs, an exception is thrown</li>. + * <li>For normal disk files, it is guaranteed that the server will return the specified + * number of bytes, or up to end of file. For, e.g., device files this may return + * fewer bytes than requested.</li> + * </ul> + * + * @param handle a SFTPv3FileHandle handle + * @param fileOffset offset (in bytes) in the file + * @param dst the destination byte array + * @param dstoff offset in the destination byte array + * @param len how many bytes to read, 0 < len + * @return the number of bytes that could be read, may be less than requested if + * the end of the file is reached, -1 is returned in case of <code>EOF</code> + * @throws IOException + */ + int read(SFTPFileHandle handle, long fileOffset, byte[] dst, int dstoff, int len) throws IOException; + + /** + * Write bytes to a file. If <code>len</code> > 32768, then the write operation will + * be split into multiple writes. + * + * @param handle a SFTPv3FileHandle handle. + * @param fileOffset offset (in bytes) in the file. + * @param src the source byte array. + * @param srcoff offset in the source byte array. + * @param len how many bytes to write. + * @throws IOException + */ + void write(SFTPFileHandle handle, long fileOffset, byte[] src, int srcoff, int len) throws IOException; + + /** + * Close a file. + * + * @param handle a file handle + * @throws IOException + */ + void closeFile(SFTPFileHandle handle) throws IOException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPDirectoryEntry.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,12 @@ +package ch.ethz.ssh2; + +/** + * @version $Id: SFTPDirectoryEntry.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public interface SFTPDirectoryEntry { + + public String getFilename(); + + public SFTPFileAttributes getAttributes(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please see the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; + +import ch.ethz.ssh2.sftp.ErrorCodes; + +/** + * Used in combination with the SFTPv3Client. This exception wraps + * error messages sent by the SFTP server. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public class SFTPException extends IOException { + private static final long serialVersionUID = 578654644222421811L; + + private final String sftpErrorMessage; + private final int sftpErrorCode; + + private static String constructMessage(String s, int errorCode) { + String[] detail = ErrorCodes.getDescription(errorCode); + + if (detail == null) + return s + " (UNKNOWN SFTP ERROR CODE)"; + + return s + " (" + detail[0] + ": " + detail[1] + ")"; + } + + SFTPException(String msg, int errorCode) { + super(constructMessage(msg, errorCode)); + sftpErrorMessage = msg; + sftpErrorCode = errorCode; + } + + /** + * Get the error message sent by the server. Often, this + * message does not help a lot (e.g., "failure"). + * + * @return the plain string as sent by the server. + */ + public String getServerErrorMessage() { + return sftpErrorMessage; + } + + /** + * Get the error code sent by the server. + * + * @return an error code as defined in the SFTP specs. + */ + public int getServerErrorCode() { + return sftpErrorCode; + } + + /** + * Get the symbolic name of the error code as given in the SFTP specs. + * + * @return e.g., "SSH_FX_INVALID_FILENAME". + */ + public String getServerErrorCodeSymbol() { + String[] detail = ErrorCodes.getDescription(sftpErrorCode); + + if (detail == null) + return "UNKNOWN SFTP ERROR CODE " + sftpErrorCode; + + return detail[0]; + } + + /** + * Get the description of the error code as given in the SFTP specs. + * + * @return e.g., "The filename is not valid." + */ + public String getServerErrorCodeVerbose() { + String[] detail = ErrorCodes.getDescription(sftpErrorCode); + + if (detail == null) + return "The error code " + sftpErrorCode + " is unknown."; + + return detail[1]; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPFileAttributes.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,15 @@ +package ch.ethz.ssh2; + +/** + * @version $Id: SFTPFileAttributes.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public interface SFTPFileAttributes { + + boolean isDirectory(); + + boolean isRegularFile(); + + boolean isSymlink(); + + byte[] toBytes(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPFileHandle.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,35 @@ +package ch.ethz.ssh2; + +import java.io.IOException; + +/** + * @version $Id: SFTPFileHandle.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class SFTPFileHandle { + + private final SFTPClient client; + + private final byte[] handle; + + protected SFTPFileHandle(final SFTPClient client, final byte[] handle) { + this.client = client; + this.handle = handle; + } + + /** + * Get the SFTPv3Client instance which created this handle. + * + * @return A SFTPv3Client instance. + */ + public SFTPClient getClient() { + return client; + } + + public byte[] getHandle() { + return handle; + } + + public void close() throws IOException { + client.closeFile(this); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPInputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2011 David Kocher. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @version $Id: SFTPInputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class SFTPInputStream extends InputStream { + + private SFTPFileHandle handle; + + /** + * Offset (in bytes) in the file to read + */ + private long readOffset = 0; + + public SFTPInputStream(SFTPFileHandle handle) { + this.handle = handle; + } + + /** + * Reads up to <code>len</code> bytes of data from the input stream into + * an array of bytes. An attempt is made to read as many as + * <code>len</code> bytes, but a smaller number may be read, possibly + * zero. The number of bytes actually read is returned as an integer. + * + * @see SFTPClient#read(SFTPFileHandle, long, byte[], int, int) + */ + @Override + public int read(byte[] buffer, int offset, int len) throws IOException { + int read = handle.getClient().read(handle, readOffset, buffer, offset, len); + + if (read > 0) { + readOffset += read; + } + + return read; + } + + /** + * Reads the next byte of data from the input stream. The value byte is + * returned as an <code>int</code> in the range <code>0</code> to + * <code>255</code>. If no byte is available because the end of the stream + * has been reached, the value <code>-1</code> is returned. This method + * blocks until input data is available, the end of the stream is detected, + * or an exception is thrown. + * <p/> + * <p> A subclass must provide an implementation of this method. + * + * @return the next byte of data, or <code>-1</code> if the end of the + * stream is reached. + * @throws IOException if an I/O error occurs. + */ + @Override + public int read() throws IOException { + byte[] buffer = new byte[1]; + int b = handle.getClient().read(handle, readOffset, buffer, 0, 1); + + if (b > 0) { + readOffset += 1; + } + + return b; + } + + /** + * Skips over and discards <code>n</code> bytes of data from this input + * stream. + * + * @param n the number of bytes to be skipped. + * @return the actual number of bytes skipped. + */ + @Override + public long skip(long n) { + readOffset += n; + return n; + } + + @Override + public void close() throws IOException { + handle.getClient().closeFile(handle); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPOutputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2011 David Kocher. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * @version $Id: SFTPOutputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class SFTPOutputStream extends OutputStream { + + private SFTPFileHandle handle; + + /** + * Offset (in bytes) in the file to write + */ + private long writeOffset = 0; + + public SFTPOutputStream(SFTPFileHandle handle) { + this.handle = handle; + } + + /** + * Writes <code>len</code> bytes from the specified byte array + * starting at offset <code>off</code> to this output stream. + * The general contract for <code>write(b, off, len)</code> is that + * some of the bytes in the array <code>b</code> are written to the + * output stream in order; element <code>b[off]</code> is the first + * byte written and <code>b[off+len-1]</code> is the last byte written + * by this operation. + * + * @see SFTPClient#write(SFTPFileHandle, long, byte[], int, int) + */ + @Override + public void write(byte[] buffer, int offset, int len) throws IOException { + // We can just blindly write the whole buffer at once. + // if <code>len</code> > 32768, then the write operation will + // be split into multiple writes in SFTPv3Client#write. + handle.getClient().write(handle, writeOffset, buffer, offset, len); + writeOffset += len; + } + + @Override + public void write(int b) throws IOException { + byte[] buffer = new byte[1]; + buffer[0] = (byte) b; + handle.getClient().write(handle, writeOffset, buffer, 0, 1); + writeOffset += 1; + } + + public long skip(long n) { + writeOffset += n; + return n; + } + + @Override + public void close() throws IOException { + handle.getClient().closeFile(handle); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPv3Client.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.packets.TypesWriter; +import ch.ethz.ssh2.sftp.ErrorCodes; +import ch.ethz.ssh2.sftp.Packet; + +/** + * A <code>SFTPv3Client</code> represents a SFTP (protocol version 3) + * client connection tunnelled over a SSH-2 connection. This is a very simple + * (synchronous) implementation. + * <p/> + * Basically, most methods in this class map directly to one of + * the packet types described in draft-ietf-secsh-filexfer-02.txt. + * <p/> + * Note: this is experimental code. + * <p/> + * Error handling: the methods of this class throw IOExceptions. However, unless + * there is catastrophic failure, exceptions of the type {@link SFTPv3Client} will + * be thrown (a subclass of IOException). Therefore, you can implement more verbose + * behavior by checking if a thrown exception if of this type. If yes, then you + * can cast the exception and access detailed information about the failure. + * <p/> + * Notes about file names, directory names and paths, copy-pasted + * from the specs: + * <ul> + * <li>SFTP v3 represents file names as strings. File names are + * assumed to use the slash ('/') character as a directory separator.</li> + * <li>File names starting with a slash are "absolute", and are relative to + * the root of the file system. Names starting with any other character + * are relative to the user's default directory (home directory).</li> + * <li>Servers SHOULD interpret a path name component ".." as referring to + * the parent directory, and "." as referring to the current directory. + * If the server implementation limits access to certain parts of the + * file system, it must be extra careful in parsing file names when + * enforcing such restrictions. There have been numerous reported + * security bugs where a ".." in a path name has allowed access outside + * the intended area.</li> + * <li>An empty path name is valid, and it refers to the user's default + * directory (usually the user's home directory).</li> + * </ul> + * <p/> + * If you are still not tired then please go on and read the comment for + * {@link #setCharset(String)}. + * + * @author Christian Plattner, plattner@inf.ethz.ch + * @version $Id: SFTPv3Client.java 133 2014-04-14 12:26:29Z dkocher@sudo.ch $ + */ +public class SFTPv3Client extends AbstractSFTPClient { + private static final Logger log = Logger.getLogger(SFTPv3Client.class); + + /** + * Open the file for reading. + */ + public static final int SSH_FXF_READ = 0x00000001; + /** + * Open the file for writing. If both this and SSH_FXF_READ are + * specified, the file is opened for both reading and writing. + */ + public static final int SSH_FXF_WRITE = 0x00000002; + /** + * Force all writes to append data at the end of the file. + */ + public static final int SSH_FXF_APPEND = 0x00000004; + /** + * If this flag is specified, then a new file will be created if one + * does not alread exist (if O_TRUNC is specified, the new file will + * be truncated to zero length if it previously exists). + */ + public static final int SSH_FXF_CREAT = 0x00000008; + /** + * Forces an existing file with the same name to be truncated to zero + * length when creating a file by specifying SSH_FXF_CREAT. + * SSH_FXF_CREAT MUST also be specified if this flag is used. + */ + public static final int SSH_FXF_TRUNC = 0x00000010; + /** + * Causes the request to fail if the named file already exists. + */ + public static final int SSH_FXF_EXCL = 0x00000020; + + private PacketListener listener; + + /** + * Create a SFTP v3 client. + * + * @param conn The underlying SSH-2 connection to be used. + * @throws IOException + */ + public SFTPv3Client(Connection conn) throws IOException { + this(conn, new PacketListener() { + public void read(String packet) { + log.debug("Read packet " + packet); + } + public void write(String packet) { + log.debug("Write packet " + packet); + } + }); + } + + /** + * Create a SFTP v3 client. + * + * @param conn The underlying SSH-2 connection to be used. + * @throws IOException + */ + public SFTPv3Client(Connection conn, PacketListener listener) throws IOException { + super(conn, 3, listener); + this.listener = listener; + } + + public SFTPv3FileAttributes fstat(SFTPFileHandle handle) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(handle.getHandle(), 0, handle.getHandle().length); + sendMessage(Packet.SSH_FXP_FSTAT, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_ATTRS) { + return new SFTPv3FileAttributes(tr); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + private SFTPv3FileAttributes statBoth(String path, int statMethod) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(path, this.getCharset()); + sendMessage(statMethod, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_ATTRS) { + return new SFTPv3FileAttributes(tr); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + public SFTPv3FileAttributes stat(String path) throws IOException { + return statBoth(path, Packet.SSH_FXP_STAT); + } + + public SFTPv3FileAttributes lstat(String path) throws IOException { + return statBoth(path, Packet.SSH_FXP_LSTAT); + } + + + private List<SFTPv3DirectoryEntry> scanDirectory(byte[] handle) throws IOException { + List<SFTPv3DirectoryEntry> files = new ArrayList<SFTPv3DirectoryEntry>(); + + while (true) { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(handle, 0, handle.length); + sendMessage(Packet.SSH_FXP_READDIR, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_NAME) { + int count = tr.readUINT32(); + + if (log.isDebugEnabled()) { + log.debug(String.format("Parsing %d name entries", count)); + } + + while (count > 0) { + SFTPv3DirectoryEntry file = new SFTPv3DirectoryEntry(); + file.filename = tr.readString(this.getCharset()); + file.longEntry = tr.readString(this.getCharset()); + listener.read(file.longEntry); + file.attributes = new SFTPv3FileAttributes(tr); + + if (log.isDebugEnabled()) { + log.debug(String.format("Adding file %s", file)); + } + + files.add(file); + count--; + } + + continue; + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + + if (errorCode == ErrorCodes.SSH_FX_EOF) { + return files; + } + + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + } + + public final SFTPv3FileHandle openDirectory(String path) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(path, this.getCharset()); + sendMessage(Packet.SSH_FXP_OPENDIR, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_HANDLE) { + return new SFTPv3FileHandle(this, tr.readByteString()); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + /** + * List the contents of a directory. + * + * @param dirName See the {@link SFTPv3Client comment} for the class for more details. + * @return A Vector containing {@link SFTPv3DirectoryEntry} objects. + * @throws IOException + */ + public List<SFTPv3DirectoryEntry> ls(String dirName) throws IOException { + SFTPv3FileHandle handle = openDirectory(dirName); + List<SFTPv3DirectoryEntry> result = scanDirectory(handle.getHandle()); + closeFile(handle); + return result; + } + + /** + * Open a file for reading. + * + * @param filename See the {@link SFTPv3Client comment} for the class for more details. + * @return a SFTPv3FileHandle handle + * @throws IOException + */ + public SFTPv3FileHandle openFileRO(String filename) throws IOException { + return openFile(filename, SSH_FXF_READ, new SFTPv3FileAttributes()); + } + + /** + * Open a file for reading and writing. + * + * @param filename See the {@link SFTPv3Client comment} for the class for more details. + * @return a SFTPv3FileHandle handle + * @throws IOException + */ + public SFTPv3FileHandle openFileRW(String filename) throws IOException { + return openFile(filename, SSH_FXF_READ | SSH_FXF_WRITE, new SFTPv3FileAttributes()); + } + + /** + * Open a file in append mode. The SFTP v3 draft says nothing but assuming normal POSIX + * behavior, all writes will be appendend to the end of the file, no matter which offset + * one specifies. + * <p/> + * A side note for the curious: OpenSSH does an lseek() to the specified writing offset before each write(), + * even for writes to files opened in O_APPEND mode. However, bear in mind that when working + * in the O_APPEND mode, each write() includes an implicit lseek() to the end of the file + * (well, this is what the newsgroups say). + * + * @param filename See the {@link SFTPv3Client comment} for the class for more details. + * @return a SFTPv3FileHandle handle + * @throws IOException + */ + public SFTPv3FileHandle openFileRWAppend(String filename) throws IOException { + return openFile(filename, SSH_FXF_READ | SSH_FXF_WRITE | SSH_FXF_APPEND, new SFTPv3FileAttributes()); + } + + /** + * Open a file in append mode. The SFTP v3 draft says nothing but assuming normal POSIX + * behavior, all writes will be appendend to the end of the file, no matter which offset + * one specifies. + * <p/> + * A side note for the curious: OpenSSH does an lseek() to the specified writing offset before each write(), + * even for writes to files opened in O_APPEND mode. However, bear in mind that when working + * in the O_APPEND mode, each write() includes an implicit lseek() to the end of the file + * (well, this is what the newsgroups say). + * + * @param filename See the {@link SFTPv3Client comment} for the class for more details. + * @return a SFTPv3FileHandle handle + * @throws IOException + */ + public SFTPv3FileHandle openFileWAppend(String filename) throws IOException { + return openFile(filename, SSH_FXF_WRITE | SSH_FXF_APPEND, new SFTPv3FileAttributes()); + } + + public SFTPv3FileHandle createFile(String filename) throws IOException { + return createFile(filename, new SFTPv3FileAttributes()); + } + + public SFTPv3FileHandle createFile(String filename, SFTPFileAttributes attr) throws IOException { + return openFile(filename, SSH_FXF_CREAT | SSH_FXF_READ | SSH_FXF_WRITE, attr); + } + + /** + * Create a file (truncate it if it already exists) and open it for writing. + * Same as {@link #createFileTruncate(String, SFTPFileAttributes) createFileTruncate(filename, null)}. + * + * @param filename See the {@link SFTPv3Client comment} for the class for more details. + * @return a SFTPv3FileHandle handle + * @throws IOException + */ + public SFTPv3FileHandle createFileTruncate(String filename) throws IOException { + return createFileTruncate(filename, new SFTPv3FileAttributes()); + } + + /** + * reate a file (truncate it if it already exists) and open it for writing. + * You can specify the default attributes of the file (the server may or may + * not respect your wishes). + * + * @param filename See the {@link SFTPv3Client comment} for the class for more details. + * @param attr may be <code>null</code> to use server defaults. Probably only + * the <code>uid</code>, <code>gid</code> and <code>permissions</code> + * (remember the server may apply a umask) entries of the {@link SFTPv3FileHandle} + * structure make sense. You need only to set those fields where you want + * to override the server's defaults. + * @return a SFTPv3FileHandle handle + * @throws IOException + */ + public SFTPv3FileHandle createFileTruncate(String filename, SFTPFileAttributes attr) throws IOException { + return openFile(filename, SSH_FXF_CREAT | SSH_FXF_TRUNC | SSH_FXF_WRITE, attr); + } + + public SFTPv3FileHandle openFile(String filename, int flags) throws IOException { + return openFile(filename, flags, new SFTPv3FileAttributes()); + } + + @Override + public SFTPv3FileHandle openFile(String filename, int flags, SFTPFileAttributes attr) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(filename, this.getCharset()); + tw.writeUINT32(flags); + tw.writeBytes(attr.toBytes()); + sendMessage(Packet.SSH_FXP_OPEN, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_HANDLE) { + return new SFTPv3FileHandle(this, tr.readByteString()); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + @Override + public void createSymlink(String src, String target) throws IOException { + int req_id = generateNextRequestID(); + // Changed semantics of src and target. The bug is known on SFTP servers shipped with all + // versions of OpenSSH (Bug #861). + TypesWriter tw = new TypesWriter(); + tw.writeString(target, this.getCharset()); + tw.writeString(src, this.getCharset()); + sendMessage(Packet.SSH_FXP_SYMLINK, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPv3DirectoryEntry.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * A <code>SFTPv3DirectoryEntry</code> as returned by {@link SFTPv3Client#ls(String)}. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class SFTPv3DirectoryEntry implements SFTPDirectoryEntry { + /** + * A relative name within the directory, without any path components. + */ + public String filename; + + /** + * An expanded format for the file name, similar to what is returned by + * "ls -l" on Un*x systems. + * <p/> + * The format of this field is unspecified by the SFTP v3 protocol. + * It MUST be suitable for use in the output of a directory listing + * command (in fact, the recommended operation for a directory listing + * command is to simply display this data). However, clients SHOULD NOT + * attempt to parse the longname field for file attributes; they SHOULD + * use the attrs field instead. + * <p/> + * The recommended format for the longname field is as follows:<br> + * <code>-rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer</code> + */ + public String longEntry; + + /** + * The attributes of this entry. + */ + public SFTPv3FileAttributes attributes; + + public String getFilename() { + return filename; + } + + public SFTPv3FileAttributes getAttributes() { + return attributes; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("SFTPv3DirectoryEntry{"); + sb.append("filename='").append(filename).append('\''); + sb.append(", attributes=").append(attributes); + sb.append('}'); + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPv3FileAttributes.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; + +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.packets.TypesWriter; +import ch.ethz.ssh2.sftp.AttribFlags; + +/** + * A <code>SFTPv3FileAttributes</code> object represents detail information + * about a file on the server. Not all fields may/must be present. + * + * @author Christian Plattner, plattner@inf.ethz.ch + * @version $Id: SFTPv3FileAttributes.java 133 2014-04-14 12:26:29Z dkocher@sudo.ch $ + */ +public class SFTPv3FileAttributes implements SFTPFileAttributes { + /** + * The SIZE attribute. <code>NULL</code> if not present. + */ + public Long size = null; + + /** + * The UID attribute. <code>NULL</code> if not present. + */ + public Integer uid = null; + + /** + * The GID attribute. <code>NULL</code> if not present. + */ + public Integer gid = null; + + /** + * The POSIX permissions. <code>NULL</code> if not present. + * <p/> + * Here is a list: + * <p/> + * <pre>Note: these numbers are all OCTAL. + * <p/> + * S_IFMT 0170000 bitmask for the file type bitfields + * S_IFSOCK 0140000 socket + * S_IFLNK 0120000 symbolic link + * S_IFREG 0100000 regular file + * S_IFBLK 0060000 block device + * S_IFDIR 0040000 directory + * S_IFCHR 0020000 character device + * S_IFIFO 0010000 fifo + * S_ISUID 0004000 set UID bit + * S_ISGID 0002000 set GID bit + * S_ISVTX 0001000 sticky bit + * <p/> + * S_IRWXU 00700 mask for file owner permissions + * S_IRUSR 00400 owner has read permission + * S_IWUSR 00200 owner has write permission + * S_IXUSR 00100 owner has execute permission + * S_IRWXG 00070 mask for group permissions + * S_IRGRP 00040 group has read permission + * S_IWGRP 00020 group has write permission + * S_IXGRP 00010 group has execute permission + * S_IRWXO 00007 mask for permissions for others (not in group) + * S_IROTH 00004 others have read permission + * S_IWOTH 00002 others have write permisson + * S_IXOTH 00001 others have execute permission + * </pre> + */ + public Integer permissions = null; + + /** + * Last access time of the file. + * <p/> + * The atime attribute. Represented as seconds from Jan 1, 1970 in UTC. + * <code>NULL</code> if not present. + */ + public Integer atime = null; + + /** + * The mtime attribute. Represented as seconds from Jan 1, 1970 in UTC. + * <code>NULL</code> if not present. + */ + public Integer mtime = null; + + /** + * Checks if this entry is a directory. + * + * @return Returns true if permissions are available and they indicate + * that this entry represents a directory. + */ + public boolean isDirectory() { + if (permissions == null) { + return false; + } + + return ((permissions & 0040000) == 0040000); + } + + /** + * Checks if this entry is a regular file. + * + * @return Returns true if permissions are available and they indicate + * that this entry represents a regular file. + */ + public boolean isRegularFile() { + if (permissions == null) { + return false; + } + + return ((permissions & 0100000) == 0100000); + } + + /** + * Checks if this entry is a a symlink. + * + * @return Returns true if permissions are available and they indicate + * that this entry represents a symlink. + */ + public boolean isSymlink() { + if (permissions == null) { + return false; + } + + return ((permissions & 0120000) == 0120000); + } + + /** + * Turn the POSIX permissions into a 7 digit octal representation. + * Note: the returned value is first masked with <code>0177777</code>. + * + * @return <code>NULL</code> if permissions are not available. + */ + public String getOctalPermissions() { + if (permissions == null) { + return null; + } + + String res = Integer.toString(permissions.intValue() & 0177777, 8); + StringBuilder sb = new StringBuilder(); + int leadingZeros = 7 - res.length(); + + while (leadingZeros > 0) { + sb.append('0'); + leadingZeros--; + } + + sb.append(res); + return sb.toString(); + } + + public SFTPv3FileAttributes() { + // + } + + /** + * uint32 valid-attribute-flags + * byte type always present + * uint64 size if flag SIZE + * uint64 allocation-size if flag ALLOCATION_SIZE + * string owner if flag OWNERGROUP + * string group if flag OWNERGROUP + * uint32 permissions if flag PERMISSIONS + * int64 atime if flag ACCESSTIME + * uint32 atime-nseconds if flag SUBSECOND_TIMES + * int64 createtime if flag CREATETIME + * uint32 createtime-nseconds if flag SUBSECOND_TIMES + * int64 mtime if flag MODIFYTIME + * uint32 mtime-nseconds if flag SUBSECOND_TIMES + * int64 ctime if flag CTIME + * uint32 ctime-nseconds if flag SUBSECOND_TIMES + * string acl if flag ACL + * uint32 attrib-bits if flag BITS + * uint32 attrib-bits-valid if flag BITS + * byte text-hint if flag TEXT_HINT + * string mime-type if flag MIME_TYPE + * uint32 link-count if flag LINK_COUNT + * string untranslated-name if flag UNTRANSLATED_NAME + * uint32 extended-count if flag EXTENDED + * extension-pair extensions + */ + public SFTPv3FileAttributes(final TypesReader tr) throws IOException { + int flags = tr.readUINT32(); + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SIZE) != 0) { + this.size = tr.readUINT64(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_V3_UIDGID) != 0) { + this.uid = tr.readUINT32(); + this.gid = tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { + this.permissions = tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_V3_ACMODTIME) != 0) { + this.atime = tr.readUINT32(); + this.mtime = tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_EXTENDED) != 0) { + int count = tr.readUINT32(); + + // Read it anyway to detect corrupt packets + while (count > 0) { + tr.readByteString(); + tr.readByteString(); + count--; + } + } + } + + /** + * The same encoding is used both when returning file + * attributes from the server and when sending file attributes to the + * server. + * + * @return Encoded attributes + */ + public byte[] toBytes() { + TypesWriter tw = new TypesWriter(); + int attrFlags = 0; + + if (this.size != null) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_SIZE; + } + + if ((this.uid != null) && (this.gid != null)) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_V3_UIDGID; + } + + if (this.permissions != null) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS; + } + + if ((this.atime != null) && (this.mtime != null)) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_V3_ACMODTIME; + } + + tw.writeUINT32(attrFlags); + + if (this.size != null) { + tw.writeUINT64(this.size); + } + + if ((this.uid != null) && (this.gid != null)) { + tw.writeUINT32(this.uid); + tw.writeUINT32(this.gid); + } + + if (this.permissions != null) { + tw.writeUINT32(this.permissions); + } + + if ((this.atime != null) && (this.mtime != null)) { + tw.writeUINT32(this.atime); + tw.writeUINT32(this.mtime); + } + + return tw.getBytes(); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("SFTPv3FileAttributes{"); + sb.append("size=").append(size); + sb.append(", uid=").append(uid); + sb.append(", gid=").append(gid); + sb.append(", permissions=").append(permissions); + sb.append(", atime=").append(atime); + sb.append(", mtime=").append(mtime); + sb.append('}'); + return sb.toString(); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPv3FileHandle.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * A <code>SFTPv3FileHandle</code>. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class SFTPv3FileHandle extends SFTPFileHandle { + protected SFTPv3FileHandle(final SFTPv3Client client, final byte[] handle) { + super(client, handle); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPv6Client.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,300 @@ +package ch.ethz.ssh2; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.packets.TypesWriter; +import ch.ethz.ssh2.sftp.AceMask; +import ch.ethz.ssh2.sftp.ErrorCodes; +import ch.ethz.ssh2.sftp.OpenFlags; +import ch.ethz.ssh2.sftp.Packet; + +/** + * @version $Id: SFTPv6Client.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class SFTPv6Client extends AbstractSFTPClient { + private static final Logger log = Logger.getLogger(SFTPv6Client.class); + + private PacketListener listener; + + public SFTPv6Client(Connection conn) throws IOException { + this(conn, new PacketListener() { + public void read(String packet) { + log.debug("Read packet " + packet); + } + public void write(String packet) { + log.debug("Write packet " + packet); + } + }); + } + + public SFTPv6Client(Connection conn, PacketListener listener) throws IOException { + super(conn, 6, listener); + this.listener = listener; + } + + public SFTPv6FileAttributes fstat(SFTPFileHandle handle) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(handle.getHandle(), 0, handle.getHandle().length); + sendMessage(Packet.SSH_FXP_FSTAT, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_ATTRS) { + return new SFTPv6FileAttributes(tr); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + private SFTPv6FileAttributes statBoth(String path, int statMethod) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(path, this.getCharset()); + sendMessage(statMethod, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_ATTRS) { + return new SFTPv6FileAttributes(tr); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + public SFTPv6FileAttributes stat(String path) throws IOException { + return statBoth(path, Packet.SSH_FXP_STAT); + } + + public SFTPv6FileAttributes lstat(String path) throws IOException { + return statBoth(path, Packet.SSH_FXP_LSTAT); + } + + + private List<SFTPv6DirectoryEntry> scanDirectory(byte[] handle) throws IOException { + List<SFTPv6DirectoryEntry> files = new ArrayList<SFTPv6DirectoryEntry>(); + + while (true) { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(handle, 0, handle.length); + sendMessage(Packet.SSH_FXP_READDIR, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_NAME) { + int count = tr.readUINT32(); + + if (log.isDebugEnabled()) { + log.debug(String.format("Parsing %d name entries", count)); + } + + while (count > 0) { + SFTPv6DirectoryEntry file = new SFTPv6DirectoryEntry(); + file.filename = tr.readString(this.getCharset()); + listener.read(file.filename); + file.attributes = new SFTPv6FileAttributes(tr); + + if (log.isDebugEnabled()) { + log.debug(String.format("Adding file %s", file)); + } + + files.add(file); + count--; + } + + continue; + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + + if (errorCode == ErrorCodes.SSH_FX_EOF) { + return files; + } + + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + } + + public final SFTPFileHandle openDirectory(String path) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(path, this.getCharset()); + sendMessage(Packet.SSH_FXP_OPENDIR, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_HANDLE) { + return new SFTPFileHandle(this, tr.readByteString()); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + /** + * List the contents of a directory. + * + * @param dirName See the {@link SFTPv6Client comment} for the class for more details. + * @return A Vector containing {@link SFTPv6DirectoryEntry} objects. + * @throws IOException + */ + public List<SFTPv6DirectoryEntry> ls(String dirName) throws IOException { + SFTPFileHandle handle = openDirectory(dirName); + List<SFTPv6DirectoryEntry> result = scanDirectory(handle.getHandle()); + closeFile(handle); + return result; + } + + /** + * Create a file and open it for reading and writing. + * Same as {@link #createFile(String, SFTPFileAttributes) createFile(fileName, null)}. + * + * @param filename See the {@link SFTPv6Client comment} for the class for more details. + * @return a SFTPFileHandle handle + * @throws IOException + */ + public SFTPFileHandle createFile(String filename) throws IOException { + return createFile(filename, new SFTPv6FileAttributes()); + } + + /** + * Create a file and open it for reading and writing. + * You can specify the default attributes of the file (the server may or may + * not respect your wishes). + * + * @param filename See the {@link SFTPv6Client comment} for the class for more details. + * @param attr may be <code>null</code> to use server defaults. Probably only + * the <code>uid</code>, <code>gid</code> and <code>permissions</code> + * (remember the server may apply a umask) entries of the {@link SFTPFileHandle} + * structure make sense. You need only to set those fields where you want + * to override the server's defaults. + * @return a SFTPFileHandle handle + * @throws IOException + */ + public SFTPFileHandle createFile(String filename, SFTPFileAttributes attr) throws IOException { + return openFile(filename, OpenFlags.SSH_FXF_CREATE_NEW, attr); + } + + public SFTPFileHandle openFile(String filename, int flags) throws IOException { + return this.openFile(filename, flags, new SFTPv6FileAttributes()); + } + + @Override + public SFTPFileHandle openFile(String filename, int flags, SFTPFileAttributes attr) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + tw.writeString(filename, this.getCharset()); + tw.writeUINT32(AceMask.ACE4_READ_DATA | AceMask.ACE4_READ_ATTRIBUTES | AceMask.ACE4_READ_ACL | AceMask.ACE4_READ_NAMED_ATTRS + | AceMask.ACE4_WRITE_DATA | AceMask.ACE4_APPEND_DATA | AceMask.ACE4_WRITE_ATTRIBUTES | AceMask.ACE4_WRITE_ACL | AceMask.ACE4_WRITE_NAMED_ATTRS); + tw.writeUINT32(flags); + tw.writeBytes(attr.toBytes()); + sendMessage(Packet.SSH_FXP_OPEN, req_id, tw.getBytes()); + byte[] resp = receiveMessage(34000); + TypesReader tr = new TypesReader(resp); + int t = tr.readByte(); + listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); + + if (rep_id != req_id) { + throw new RequestMismatchException(); + } + + if (t == Packet.SSH_FXP_HANDLE) { + return new SFTPFileHandle(this, tr.readByteString()); + } + + if (t != Packet.SSH_FXP_STATUS) { + throw new PacketTypeException(t); + } + + int errorCode = tr.readUINT32(); + String errorMessage = tr.readString(); + listener.read(errorMessage); + throw new SFTPException(errorMessage, errorCode); + } + + @Override + public void createSymlink(String src, String target) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + // new-link-path + tw.writeString(src, this.getCharset()); + // existing-path + tw.writeString(target, this.getCharset()); + tw.writeBoolean(true); + sendMessage(Packet.SSH_FXP_LINK, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } + + @Override + public void createHardlink(String src, String target) throws IOException { + int req_id = generateNextRequestID(); + TypesWriter tw = new TypesWriter(); + // new-link-path + tw.writeString(src, this.getCharset()); + // existing-path + tw.writeString(target, this.getCharset()); + tw.writeBoolean(false); + sendMessage(Packet.SSH_FXP_LINK, req_id, tw.getBytes()); + expectStatusOKMessage(req_id); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPv6DirectoryEntry.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,33 @@ +package ch.ethz.ssh2; + +/** + * @version $Id: SFTPv6DirectoryEntry.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class SFTPv6DirectoryEntry implements SFTPDirectoryEntry { + /** + * A relative name within the directory, without any path components. + */ + public String filename; + + /** + * The attributes of this entry. + */ + public SFTPv6FileAttributes attributes; + + public String getFilename() { + return filename; + } + + public SFTPv6FileAttributes getAttributes() { + return attributes; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("SFTPv6DirectoryEntry{"); + sb.append("filename='").append(filename).append('\''); + sb.append(", attributes=").append(attributes); + sb.append('}'); + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SFTPv6FileAttributes.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; + +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.packets.TypesWriter; +import ch.ethz.ssh2.sftp.AttribFlags; +import ch.ethz.ssh2.sftp.AttribTypes; + +/** + * A <code>SFTPv3FileAttributes</code> object represents detail information + * about a file on the server. Not all fields may/must be present. + * + * @author Christian Plattner, plattner@inf.ethz.ch + * @version $Id: SFTPv6FileAttributes.java 133 2014-04-14 12:26:29Z dkocher@sudo.ch $ + */ + +public class SFTPv6FileAttributes implements SFTPFileAttributes { + + /** + * The type field is always present + * + * @see ch.ethz.ssh2.sftp.AttribTypes + */ + private Integer type = null; + + /** + * The SIZE attribute. <code>NULL</code> if not present. + */ + public Long size = null; + + /** + * The POSIX permissions. <code>NULL</code> if not present. + * <p/> + * Here is a list: + * <p/> + * <pre>Note: these numbers are all OCTAL. + * <p/> + * S_IFMT 0170000 bitmask for the file type bitfields + * S_IFSOCK 0140000 socket + * S_IFLNK 0120000 symbolic link + * S_IFREG 0100000 regular file + * S_IFBLK 0060000 block device + * S_IFDIR 0040000 directory + * S_IFCHR 0020000 character device + * S_IFIFO 0010000 fifo + * S_ISUID 0004000 set UID bit + * S_ISGID 0002000 set GID bit + * S_ISVTX 0001000 sticky bit + * <p/> + * S_IRWXU 00700 mask for file owner permissions + * S_IRUSR 00400 owner has read permission + * S_IWUSR 00200 owner has write permission + * S_IXUSR 00100 owner has execute permission + * S_IRWXG 00070 mask for group permissions + * S_IRGRP 00040 group has read permission + * S_IWGRP 00020 group has write permission + * S_IXGRP 00010 group has execute permission + * S_IRWXO 00007 mask for permissions for others (not in group) + * S_IROTH 00004 others have read permission + * S_IWOTH 00002 others have write permisson + * S_IXOTH 00001 others have execute permission + * </pre> + */ + public Integer permissions = null; + + /** + * Creation time of the file. + * <p/> + * The createtime attribute. Represented as seconds from Jan 1, 1970 in UTC. + * <code>NULL</code> if not present. + */ + public Long createtime = null; + + /** + * Last access time of the file. + * <p/> + * The atime attribute. Represented as seconds from Jan 1, 1970 in UTC. + * <code>NULL</code> if not present. + */ + public Long atime = null; + + /** + * The mtime attribute. Represented as seconds from Jan 1, 1970 in UTC. + * <code>NULL</code> if not present. + */ + public Long mtime = null; + + /** + * Last time the file attributes were changed. The exact meaning of this field depends on the server. + * <p/> + * The ctime attribute. Represented as seconds from Jan 1, 1970 in UTC. + * <code>NULL</code> if not present. + */ + public Long ctime = null; + + /** + * The 'owner' and 'group' fields are represented as UTF-8 strings. user@localhost represents + * a user in the context of the server. + */ + public String owner = null; + + /** + * The 'owner' and 'group' fields are represented as UTF-8 strings + */ + public String group = null; + + /** + * Checks if this entry is a directory. + * + * @return Returns true if permissions are available and they indicate + * that this entry represents a directory. + */ + public boolean isDirectory() { + return (type & AttribTypes.SSH_FILEXFER_TYPE_DIRECTORY) == AttribTypes.SSH_FILEXFER_TYPE_DIRECTORY; + } + + /** + * Checks if this entry is a regular file. + * + * @return Returns true if permissions are available and they indicate + * that this entry represents a regular file. + */ + public boolean isRegularFile() { + return (type & AttribTypes.SSH_FILEXFER_TYPE_REGULAR) == AttribTypes.SSH_FILEXFER_TYPE_REGULAR; + } + + /** + * Checks if this entry is a a symlink. + * + * @return Returns true if permissions are available and they indicate + * that this entry represents a symlink. + */ + public boolean isSymlink() { + return (type & AttribTypes.SSH_FILEXFER_TYPE_SYMLINK) == AttribTypes.SSH_FILEXFER_TYPE_SYMLINK; + } + + public SFTPv6FileAttributes() { + // + } + + /** + * uint32 valid-attribute-flags + * byte type always present + * uint64 size if flag SIZE + * uint64 allocation-size if flag ALLOCATION_SIZE + * string owner if flag OWNERGROUP + * string group if flag OWNERGROUP + * uint32 permissions if flag PERMISSIONS + * int64 atime if flag ACCESSTIME + * uint32 atime-nseconds if flag SUBSECOND_TIMES + * int64 createtime if flag CREATETIME + * uint32 createtime-nseconds if flag SUBSECOND_TIMES + * int64 mtime if flag MODIFYTIME + * uint32 mtime-nseconds if flag SUBSECOND_TIMES + * int64 ctime if flag CTIME + * uint32 ctime-nseconds if flag SUBSECOND_TIMES + * string acl if flag ACL + * uint32 attrib-bits if flag BITS + * uint32 attrib-bits-valid if flag BITS + * byte text-hint if flag TEXT_HINT + * string mime-type if flag MIME_TYPE + * uint32 link-count if flag LINK_COUNT + * string untranslated-name if flag UNTRANSLATED_NAME + * uint32 extended-count if flag EXTENDED + * extension-pair extensions + */ + public SFTPv6FileAttributes(final TypesReader tr) throws IOException { + int flags = tr.readUINT32(); + // The type field is always present + this.type = tr.readByte(); + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SIZE) != 0) { + this.size = tr.readUINT64(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_ALLOCATION_SIZE) != 0) { + // Ignore + tr.readUINT64(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_OWNERGROUP) != 0) { + this.owner = tr.readString(); + this.group = tr.readString(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { + this.permissions = tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_ACCESSTIME) != 0) { + this.atime = tr.readUINT64(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { + // Ignore + tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_CREATETIME) != 0) { + this.createtime = tr.readUINT64(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { + // Ignore + tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_MODIFYTIME) != 0) { + this.mtime = tr.readUINT64(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { + // Ignore + tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_CTIME) != 0) { + this.ctime = tr.readUINT64(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { + // Ignore + tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_ACL) != 0) { + // Ignore + tr.readString(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_BITS) != 0) { + // Ignore attrib-bits + tr.readUINT32(); + // Ignore attrib-bits-valid + tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_TEXT_HINT) != 0) { + // Ignore + tr.readByte(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_MIME_TYPE) != 0) { + // Ignore + tr.readString(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_LINK_COUNT) != 0) { + // Ignore + tr.readUINT32(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_UNTRANSLATED_NAME) != 0) { + // Ignore + tr.readString(); + } + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_EXTENDED) != 0) { + int count = tr.readUINT32(); + + // Read it anyway to detect corrupt packets + while (count > 0) { + // extension-name + tr.readByteString(); + // extension-data + tr.readByteString(); + count--; + } + } + } + + /** + * The same encoding is used both when returning file + * attributes from the server and when sending file attributes to the + * server. + * + * @return Encoded attributes + */ + public byte[] toBytes() { + TypesWriter tw = new TypesWriter(); + // The 'valid-attribute-flags' specifies which of the fields are present. Those fields + // for which the corresponding flag is not set are not present + int attrFlags = 0; + + if (this.size != null) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_SIZE; + } + + if ((this.owner != null) && (this.group != null)) { + // If either the owner or group field is zero length, the field should + // be considered absent, and no change should be made to that specific + // field during a modification operation. + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_OWNERGROUP; + } + + if (this.permissions != null) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS; + } + + if (this.atime != null) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_ACCESSTIME; + } + + if (this.createtime != null) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_CREATETIME; + } + + if (this.mtime != null) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_MODIFYTIME; + } + + if (this.ctime != null) { + attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_CTIME; + } + + tw.writeUINT32(attrFlags); + + // The type field is always present. + if (this.size != null) { + tw.writeUINT64(this.size); + } + + if ((this.owner != null) && (this.group != null)) { + tw.writeString(owner); + tw.writeString(group); + } + + if (this.permissions != null) { + tw.writeUINT32(this.permissions); + } + + if (this.atime != null) { + tw.writeUINT64(this.atime); + } + + if (this.createtime != null) { + tw.writeUINT64(this.createtime); + } + + if (this.mtime != null) { + tw.writeUINT64(this.mtime); + } + + if (this.ctime != null) { + tw.writeUINT64(this.ctime); + } + + return tw.getBytes(); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("SFTPv6FileAttributes{"); + sb.append("type=").append(type); + sb.append(", size=").append(size); + sb.append(", permissions=").append(permissions); + sb.append(", createtime=").append(createtime); + sb.append(", atime=").append(atime); + sb.append(", mtime=").append(mtime); + sb.append(", ctime=").append(ctime); + sb.append(", owner='").append(owner).append('\''); + sb.append(", group='").append(group).append('\''); + sb.append('}'); + return sb.toString(); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ServerAuthenticationCallback.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2; + +/** + * A callback used during the authentication phase (see RFC 4252) when + * implementing a SSH server. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public interface ServerAuthenticationCallback { + /** + * The method name for host-based authentication. + */ + public final String METHOD_HOSTBASED = "hostbased"; + + /** + * The method name for public-key authentication. + */ + public final String METHOD_PUBLICKEY = "publickey"; + + /** + * The method name for password authentication. + */ + public final String METHOD_PASSWORD = "password"; + + /** + * Called when the client enters authentication. + * This gives you the chance to set a custom authentication banner + * for this SSH-2 session. This is the first method called in this interface. + * It will only called at most once per <code>ServerConnection</code>. + * + * @param sc The corresponding <code>ServerConnection</code> + * @return The authentication banner or <code>NULL</code> in case no banner should be send. + */ + public String initAuthentication(ServerConnection sc); + + /** + * Return the authentication methods that are currently available to the client. + * Be prepared to return this information at any time during the authentication procedure. + * <p/> + * The returned name-list of 'method names' (see RFC4252) indicate the authentication methods + * that may productively continue the authentication dialog. + * </p> + * It is RECOMMENDED that servers only include those 'method name' + * values in the name-list that are actually useful. However, it is not + * illegal to include 'method name' values that cannot be used to + * authenticate the user. + * <p/> + * Already successfully completed authentications SHOULD NOT be included + * in the name-list, unless they should be performed again for some reason. + * + * @see #METHOD_HOSTBASED + * @see #METHOD_PASSWORD + * @see #METHOD_PUBLICKEY + * + * @param sc + * @return A list of method names. + */ + public String[] getRemainingAuthMethods(ServerConnection sc); + + /** + * Typically, this will be called be the client to get the list of + * authentication methods that can continue. You should simply return + * {@link AuthenticationResult#FAILURE}. + * + * @param sc + * @param username Name of the user that wants to log in with the "none" method. + * @return + */ + public AuthenticationResult authenticateWithNone(ServerConnection sc, String username); + + public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password); + + /** + * NOTE: Not implemented yet. + * + * @param sc + * @param username + * @param algorithm + * @param publickey + * @param signature + * @return + */ + public AuthenticationResult authenticateWithPublicKey(ServerConnection sc, String username, String algorithm, + byte[] publickey, byte[] signature); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ServerConnection.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2; + +import java.io.CharArrayWriter; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.net.Socket; +import java.util.List; +import java.util.ArrayList; + +import ch.ethz.ssh2.crypto.CryptoWishList; +import ch.ethz.ssh2.crypto.PEMDecoder; +import ch.ethz.ssh2.server.ServerConnectionState; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.RSAPrivateKey; +import ch.ethz.ssh2.transport.ServerTransportManager; + +/** + * A server-side SSH-2 connection. + * + * @author Christian + * + */ +public class ServerConnection { + /** + * The softwareversion presented to the SSH-2 client. + */ + private String softwareversion = String.format("Ganymed_SSHD_%s", Version.getSpecification()); + + private final ServerConnectionState state = new ServerConnectionState(this); + + /** + * Creates a new <code>ServerConnection</code> that will communicate + * with the client over the given <code>Socket</code>. + * <p> + * Note: you need to call {@link #connect()} or {@link #connect(int)} to + * perform the initial handshake and establish the encrypted communication. + * + * @see #connect(int) + * + * @param s The socket + */ + public ServerConnection(Socket s) { + this(s, null, null, null); + } + + public ServerConnection(Socket s, String softwareversion) { + this(s, null, null, null); + this.softwareversion = softwareversion; + } + + /** + * Creates a new <code>ServerConnection</code> that will communicate + * with the client over the given <code>Socket</code>. + * <p> + * Note: you need to call {@link #connect()} or {@link #connect(int)} to + * perform the initial handshake and establish the encrypted communication. + * <p> + * Please read the javadoc for the {@link #connect(int)} method. + * + * @see #connect(int) + * + * @param s The socket + * @param dsa_key The DSA hostkey, may be <code>NULL</code> + * @param rsa_key The RSA hostkey, may be <code>NULL</code> + * @param ec_key The EC hostkey, may be <code>NULL</code> + */ + public ServerConnection(Socket s, KeyPair dsa_key, KeyPair rsa_key, KeyPair ec_key) { + state.s = s; + state.softwareversion = softwareversion; + state.next_dsa_key = dsa_key; + state.next_rsa_key = rsa_key; + state.next_ec_key = ec_key; + fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } + + /** + * Establish the connection and block until the first handshake has completed. + * <p> + * Note: this is a wrapper that calls <code>connect(0)</code> (i.e., connect with no timeout). + * <p> + * Please read the javadoc for the {@link #connect(int)} method. + * + * @see #connect(int) + * + * @throws IOException + */ + + public synchronized void connect() throws IOException { + connect(0); + } + + /** + * Establish the connection and block until the first handshake has completed. + * <p> + * Note 1: at least one DSA, RSA or EC hostkey must be set before calling this method. + * <p> + * Note 2: You must set the callbacks for authentication ({@link #setAuthenticationCallback(ServerAuthenticationCallback)}) + * and connection events ({@link #setServerConnectionCallback(ServerConnectionCallback)}). + * + * @see #setPEMHostKey(char[], String) + * @see #setPEMHostKey(File, String) + * @see #setRsaHostKey(RSAPrivateKey) + * @see #setDsaHostKey(DSAPrivateKey) + * + * @param timeout_milliseconds Timeout in milliseconds, <code>0</code> means no timeout. + * @throws IOException + */ + + public synchronized void connect(int timeout_milliseconds) throws IOException { + synchronized (state) { + if (state.cb_conn == null) + throw new IllegalStateException("The callback for connection events has not been set."); + + if (state.cb_auth == null) + throw new IllegalStateException("The callback for authentication events has not been set."); + + if (state.tm != null) + throw new IllegalStateException("The initial handshake has already been started."); + + if ((state.next_dsa_key == null) && (state.next_rsa_key == null) && (state.next_ec_key == null)) + throw new IllegalStateException("Neither an RSA nor a DSA nor an EC host key has been specified!"); + + state.tm = new ServerTransportManager(state.s); + } + + state.tm.connect(state); + /* Wait until first KEX has finished */ + state.tm.getConnectionInfo(1); + } + + /** + * Retrieve the underlying socket. + * + * @return the socket that has been passed to the constructor. + */ + public Socket getSocket() { + return state.s; + } + + /** + * Force an asynchronous key re-exchange (the call does not block). The + * latest values set for MAC, Cipher and DH group exchange parameters will + * be used. If a key exchange is currently in progress, then this method has + * the only effect that the so far specified parameters will be used for the + * next (client driven) key exchange. You may call this method only after + * the initial key exchange has been established. + * <p> + * Note: This implementation will never start automatically a key exchange (other than the initial one) + * unless you or the connected SSH-2 client ask for it. + * + * @throws IOException + * In case of any failure behind the scenes. + */ + + public synchronized void forceKeyExchange() throws IOException { + synchronized (state) { + if (state.tm == null) + throw new IllegalStateException( + "Cannot force another key exchange, you need to start the key exchange first."); + + state.tm.forceKeyExchange(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } + } + + /** + * Returns a {@link ConnectionInfo} object containing the details of + * the connection. May be called as soon as the first key exchange has been + * started. The method blocks in case the first key exchange has not been completed. + * <p> + * Note: upon return of this method, authentication may still be pending. + * + * @return A {@link ConnectionInfo} object. + * @throws IOException + * In case of any failure behind the scenes; e.g., first key exchange was aborted. + */ + + public synchronized ConnectionInfo getConnectionInfo() throws IOException { + synchronized (state) { + if (state.tm == null) + throw new IllegalStateException( + "Cannot get details of connection, you need to start the key exchange first."); + } + + return state.tm.getConnectionInfo(1); + } + + /** + * Change the current DSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with + * the client. + * <p> + * Note: You can change an existing DSA hostkey after the initial kex exchange (the new value will + * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the + * current DSA key, otherwise the next key exchange may fail in case the client supports only DSA hostkeys. + * + * @param dsa_hostkey + */ + + public synchronized void setDsaHostKey(KeyPair dsa_hostkey) { + synchronized (state) { + if ((dsa_hostkey == null) && (state.next_dsa_key != null) && (state.tm != null)) + throw new IllegalStateException("Cannot remove DSA hostkey after first key exchange."); + + state.next_dsa_key = dsa_hostkey; + fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } + } + + /** + * Change the current RSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with + * the client. + * <p> + * Note: You can change an existing RSA hostkey after the initial kex exchange (the new value will + * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the + * current RSA key, otherwise the next key exchange may fail in case the client supports only RSA hostkeys. + * + * @param rsa_hostkey + */ + + public synchronized void setRsaHostKey(KeyPair rsa_hostkey) { + synchronized (state) { + if ((rsa_hostkey == null) && (state.next_rsa_key != null) && (state.tm != null)) + throw new IllegalStateException("Cannot remove RSA hostkey after first key exchange."); + + state.next_rsa_key = rsa_hostkey; + fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } + } + + /** + * Change the current EC hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with + * the client. + * <p> + * Note: You can change an existing EC hostkey after the initial kex exchange (the new value will + * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the + * current EC key, otherwise the next key exchange may fail in case the client supports only EC hostkeys. + * + * @param rsa_hostkey + */ + + public synchronized void setEcHostKey(KeyPair ec_hostkey) { + synchronized (state) { + if ((ec_hostkey == null) && (state.next_ec_key != null) && (state.tm != null)) + throw new IllegalStateException("Cannot remove EC hostkey after first key exchange."); + + state.next_ec_key = ec_hostkey; + fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } + } + + /** + * Utility method that loads a PEM based hostkey (either RSA or DSA based) and + * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. + * + * @param pemdata The PEM data + * @param password Password, may be null in case the PEM data is not password protected + * @throws IOException In case of any error. + */ + public void setPEMHostKey(char[] pemdata, String password) throws IOException { + KeyPair pair = PEMDecoder.decode(pemdata, password); + PrivateKey key = pair.getPrivate(); + + if (key instanceof DSAPrivateKey) setDsaHostKey(pair); + + if (key instanceof RSAPrivateKey) setRsaHostKey(pair); + + if (key instanceof ECPrivateKey) setEcHostKey(pair); + } + + /** + * Utility method that loads a hostkey from a PEM file (either RSA or DSA based) and + * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. + * + * @param pemFile The PEM file + * @param password Password, may be null in case the PEM file is not password protected + * @throws IOException + */ + public void setPEMHostKey(File pemFile, String password) throws IOException { + if (pemFile == null) + throw new IllegalArgumentException("pemfile argument is null"); + + char[] buff = new char[256]; + CharArrayWriter cw = new CharArrayWriter(); + FileReader fr = new FileReader(pemFile); + + while (true) { + int len = fr.read(buff); + + if (len < 0) + break; + + cw.write(buff, 0, len); + } + + fr.close(); + setPEMHostKey(cw.toCharArray(), password); + } + + private void fixCryptoWishList(CryptoWishList next_cryptoWishList, KeyPair next_dsa_key, KeyPair next_rsa_key, KeyPair next_ec_key) { + List<String> algos = new ArrayList<String>(); + + if (next_rsa_key != null) algos.add("ssh-rsa"); + if (next_dsa_key != null) algos.add("ssh-dss"); + if (next_ec_key != null) algos.add("ecdsa-sha2-nistp521"); + if (next_ec_key != null) algos.add("ecdsa-sha2-nistp384"); + if (next_ec_key != null) algos.add("ecdsa-sha2-nistp256"); + + next_cryptoWishList.serverHostKeyAlgorithms = new String[algos.size()]; + algos.toArray(next_cryptoWishList.serverHostKeyAlgorithms); + } + + /** + * Callback interface with methods that will be called upon events + * generated by the client (e.g., client opens a new Session which results in a <code>ServerSession</code>). + * <p> + * Note: This must be set before the first handshake. + * + * @param cb The callback implementation + */ + + public synchronized void setServerConnectionCallback(ServerConnectionCallback cb) { + synchronized (state) { + state.cb_conn = cb; + } + } + + /** + * Callback interface with methods that will be called upon authentication events. + * <p> + * Note: This must be set before the first handshake. + * + * @param cb The callback implementation + */ + + public synchronized void setAuthenticationCallback(ServerAuthenticationCallback cb) { + synchronized (state) { + state.cb_auth = cb; + } + } + + /** + * Close the connection to the SSH-2 server. All assigned sessions will be + * closed, too. Can be called at any time. Don't forget to call this once + * you don't need a connection anymore - otherwise the receiver thread may + * run forever. + */ + public void close() { + synchronized (state) { + if (state.cm != null) + state.cm.closeAllChannels(); + + if (state.tm != null) { + state.tm.close(new Throwable("Closed due to user request."), false); + } + } + } + + public void close(IOException t) { + synchronized (state) { + if (state.cm != null) + state.cm.closeAllChannels(); + + if (state.tm != null) { + state.tm.close(t, false); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ServerConnectionCallback.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +public interface ServerConnectionCallback { + public ServerSessionCallback acceptSession(ServerSession session); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ServerHostKeyVerifier.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +/** + * A callback interface used to implement a client specific method of checking + * server host keys. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public interface ServerHostKeyVerifier { + /** + * The actual verifier method, it will be called by the key exchange code + * on EVERY key exchange - this can happen several times during the lifetime + * of a connection. + * <p> + * Note: SSH-2 servers are allowed to change their hostkey at ANY time. + * + * @param hostname the hostname used to create the {@link Connection} object + * @param port the remote TCP port + * @param serverHostKeyAlgorithm the public key algorithm (<code>ssh-rsa</code> or <code>ssh-dss</code>) + * @param serverHostKey the server's public key blob + * @return if the client wants to accept the server's host key - if not, the + * connection will be closed. + * @throws Exception Will be wrapped with an IOException, extended version of returning false =) + */ + public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) + throws Exception; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ServerSession.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.InputStream; +import java.io.OutputStream; + +/** + * A ServerSession represents the server-side of a session channel. + * + * @see Session + * + * @author Christian + * + */ +public interface ServerSession { + public InputStream getStdout(); + + public InputStream getStderr(); + + public OutputStream getStdin(); + + public void close(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/ServerSessionCallback.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2; + +import java.io.IOException; + +/** + * The interface for an object that receives events based on requests that + * a client sends on a session channel. Once the session channel has been set up, + * a program is started at the server end. The program can be a shell, an application + * program, or a subsystem with a host-independent name. Only one of these requests + * can succeed per channel. + * <p/> + * <b>CAUTION: These event methods are being called from the receiver thread. The receiving of + * messages will be blocked until your event handler returns. To signal to the client that you + * are willing to accept its request, return a {@link Runnable} object which will be executed + * in a new thread <i>after</i> the acknowledgment has been sent back to the client.</b> + * <p/> + * <b>If a method does not allow you to return a {@link Runnable}, then the + * SSH protocol does not allow to send a status back to the client (more exactly, the client cannot + * request an acknowledgment). In these cases, if you need to invoke + * methods on the {@link ServerSession} or plan to execute long-running activity, then please do this from within a new {@link Thread}.</b> + * <p/> + * If you want to signal a fatal error, then please throw an <code>IOException</code>. Currently, this will + * tear down the whole SSH connection. + * + * @see ServerSession + * + * @author Christian + * + */ +public interface ServerSessionCallback { + public Runnable requestPtyReq(ServerSession ss, PtySettings pty) throws IOException; + + public Runnable requestEnv(ServerSession ss, String name, String value) throws IOException; + + public Runnable requestShell(ServerSession ss) throws IOException; + + public Runnable requestExec(ServerSession ss, String command) throws IOException; + + public Runnable requestSubsystem(ServerSession ss, String subsystem) throws IOException; + + /** + * When the window (terminal) size changes on the client side, it MAY send a message to the other side to inform it of the new dimensions. + * + * @param ss the corresponding session + * @param term_width_columns + * @param term_height_rows + * @param term_width_pixels + */ + public void requestWindowChange(ServerSession ss, int term_width_columns, int term_height_rows, + int term_width_pixels, int term_height_pixels) throws IOException; + + /** + * A signal can be delivered to the remote process/service. Some systems may not implement signals, in which case they SHOULD ignore this message. + * + * @param ss the corresponding session + * @param signal (a string without the "SIG" prefix) + * @return + * @throws IOException + */ + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/Session.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.SecureRandom; + +import ch.ethz.ssh2.channel.Channel; +import ch.ethz.ssh2.channel.ChannelManager; +import ch.ethz.ssh2.channel.X11ServerData; + +/** + * A <code>Session</code> is a remote execution of a program. "Program" means + * in this context either a shell, an application or a system command. The + * program may or may not have a tty. Only one single program can be started on + * a session. However, multiple sessions can be active simultaneously. + * + * @author Christian Plattner + * @version $Id: Session.java 96 2014-04-08 15:14:37Z dkocher@sudo.ch $ + */ +public class Session { + private ChannelManager cm; + private Channel cn; + + private boolean flag_pty_requested = false; + private boolean flag_x11_requested = false; + private boolean flag_execution_started = false; + private boolean flag_closed = false; + + private String x11FakeCookie = null; + + private final SecureRandom rnd; + + protected Session(ChannelManager cm, SecureRandom rnd) throws IOException { + this.cm = cm; + this.cn = cm.openSessionChannel(); + this.rnd = rnd; + } + + /** + * Basically just a wrapper for lazy people - identical to calling + * <code>requestPTY("dumb", 0, 0, 0, 0, null)</code>. + * + * @throws IOException + */ + public void requestDumbPTY() throws IOException { + requestPTY("dumb", 0, 0, 0, 0, null); + } + + /** + * Basically just another wrapper for lazy people - identical to calling + * <code>requestPTY(term, 0, 0, 0, 0, null)</code>. + * + * @throws IOException + */ + public void requestPTY(String term) throws IOException { + requestPTY(term, 0, 0, 0, 0, null); + } + + /** + * Allocate a pseudo-terminal for this session. + * <p/> + * This method may only be called before a program or shell is started in + * this session. + * <p/> + * Different aspects can be specified: + * <p/> + * <ul> + * <li>The TERM environment variable value (e.g., vt100)</li> + * <li>The terminal's dimensions.</li> + * <li>The encoded terminal modes.</li> + * </ul> + * Zero dimension parameters are ignored. The character/row dimensions + * override the pixel dimensions (when nonzero). Pixel dimensions refer to + * the drawable area of the window. The dimension parameters are only + * informational. The encoding of terminal modes (parameter + * <code>terminal_modes</code>) is described in RFC4254. + * + * @param term The TERM environment variable value (e.g., vt100) + * @param term_width_characters terminal width, characters (e.g., 80) + * @param term_height_characters terminal height, rows (e.g., 24) + * @param term_width_pixels terminal width, pixels (e.g., 640) + * @param term_height_pixels terminal height, pixels (e.g., 480) + * @param terminal_modes encoded terminal modes (may be <code>null</code>) + * @throws IOException + */ + public void requestPTY(String term, int term_width_characters, int term_height_characters, int term_width_pixels, + int term_height_pixels, byte[] terminal_modes) throws IOException { + if (term == null) + throw new IllegalArgumentException("TERM cannot be null."); + + if ((terminal_modes != null) && (terminal_modes.length > 0)) { + if (terminal_modes[terminal_modes.length - 1] != 0) + throw new IOException("Illegal terminal modes description, does not end in zero byte"); + } + else + terminal_modes = new byte[] {0}; + + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); + + if (flag_pty_requested) + throw new IOException("A PTY was already requested."); + + if (flag_execution_started) + throw new IOException( + "Cannot request PTY at this stage anymore, a remote execution has already started."); + + flag_pty_requested = true; + } + + cm.requestPTY(cn, term, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels, + terminal_modes); + } + + /** + * Tells the server that the size of the terminal has changed. + * + * See {@link #requestPTY(String, int, int, int, int, byte[])} for more details about how parameters are interpreted. + * + * @param term_width_characters + * terminal width, characters (e.g., 80) + * @param term_height_characters + * terminal height, rows (e.g., 24) + * @param term_width_pixels + * terminal width, pixels (e.g., 640) + * @param term_height_pixels + * terminal height, pixels (e.g., 480) + * @throws IOException + */ + public void resizePTY(int term_width_characters, int term_height_characters, int term_width_pixels, int term_height_pixels) throws IOException { + requestWindowChange(term_width_characters, term_height_characters, term_width_pixels, term_height_pixels); + } + + public void requestWindowChange(int term_width_characters, int term_height_characters, int term_width_pixels, + int term_height_pixels) throws IOException { + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); + + if (!flag_pty_requested) + throw new IOException("A PTY was not requested."); + } + + cm.requestWindowChange(cn, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels); + } + + /** + * Request X11 forwarding for the current session. + * <p/> + * You have to supply the name and port of your X-server. + * <p/> + * This method may only be called before a program or shell is started in + * this session. + * + * @param hostname the hostname of the real (target) X11 server (e.g., 127.0.0.1) + * @param port the port of the real (target) X11 server (e.g., 6010) + * @param cookie if non-null, then present this cookie to the real X11 server + * @param singleConnection if true, then the server is instructed to only forward one single + * connection, no more connections shall be forwarded after first, or after the session + * channel has been closed + * @throws IOException + */ + public void requestX11Forwarding(String hostname, int port, byte[] cookie, boolean singleConnection) + throws IOException { + if (hostname == null) + throw new IllegalArgumentException("hostname argument may not be null"); + + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); + + if (flag_x11_requested) + throw new IOException("X11 forwarding was already requested."); + + if (flag_execution_started) + throw new IOException( + "Cannot request X11 forwarding at this stage anymore, a remote execution has already started."); + + flag_x11_requested = true; + } + + /* X11ServerData - used to store data about the target X11 server */ + X11ServerData x11data = new X11ServerData(); + x11data.hostname = hostname; + x11data.port = port; + x11data.x11_magic_cookie = cookie; /* if non-null, then present this cookie to the real X11 server */ + /* Generate fake cookie - this one is used between remote clients and the ganymed proxy */ + byte[] fakeCookie = new byte[16]; + String hexEncodedFakeCookie; + + /* Make sure that this fake cookie is unique for this connection */ + + while (true) { + rnd.nextBytes(fakeCookie); + /* Generate also hex representation of fake cookie */ + StringBuilder tmp = new StringBuilder(32); + + for (int i = 0; i < fakeCookie.length; i++) { + String digit2 = Integer.toHexString(fakeCookie[i] & 0xff); + tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2); + } + + hexEncodedFakeCookie = tmp.toString(); + + /* Well, yes, chances are low, but we want to be on the safe side */ + + if (cm.checkX11Cookie(hexEncodedFakeCookie) == null) + break; + } + + /* Ask for X11 forwarding */ + cm.requestX11(cn, singleConnection, "MIT-MAGIC-COOKIE-1", hexEncodedFakeCookie, 0); + + /* OK, that went fine, get ready to accept X11 connections... */ + /* ... but only if the user has not called close() in the meantime =) */ + + synchronized (this) { + if (flag_closed == false) { + this.x11FakeCookie = hexEncodedFakeCookie; + cm.registerX11Cookie(hexEncodedFakeCookie, x11data); + } + } + + /* Now it is safe to start remote X11 programs */ + } + + /** + * Execute a command on the remote machine. + * + * @param cmd The command to execute on the remote host. + * @throws IOException + */ + public void execCommand(String cmd) throws IOException { + this.execCommand(cmd, null); + } + + /** + * Execute a command on the remote machine. + * + * @param cmd The command to execute on the remote host. + * @param charsetName The charset used to convert between Java Unicode Strings and byte encodings + * @throws IOException + */ + public void execCommand(String cmd, String charsetName) throws IOException { + if (cmd == null) + throw new IllegalArgumentException("cmd argument may not be null"); + + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); + + if (flag_execution_started) + throw new IOException("A remote execution has already started."); + + flag_execution_started = true; + } + + cm.requestExecCommand(cn, cmd, charsetName); + } + + /** + * Start a shell on the remote machine. + * + * @throws IOException + */ + public void startShell() throws IOException { + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); + + if (flag_execution_started) + throw new IOException("A remote execution has already started."); + + flag_execution_started = true; + } + + cm.requestShell(cn); + } + + /** + * Start a subsystem on the remote machine. + * Unless you know what you are doing, you will never need this. + * + * @param name the name of the subsystem. + * @throws IOException + */ + public void startSubSystem(String name) throws IOException { + if (name == null) + throw new IllegalArgumentException("name argument may not be null"); + + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); + + if (flag_execution_started) + throw new IOException("A remote execution has already started."); + + flag_execution_started = true; + } + + cm.requestSubSystem(cn, name); + } + + /** + * Request authentication agent forwarding. + * @param agent object that implements the callbacks + * + * @throws IOException in case of any problem or when the session is closed + */ + + public synchronized void requestAuthAgentForwarding(AuthAgentCallback agent) throws IOException { + synchronized (this) { + /* + * The following is just a nicer error, we would catch it anyway + * later in the channel code + */ + if (flag_closed) + throw new IOException("This session is closed."); + } + + cm.requestChannelAgentForwarding(cn, agent); + } + + public int getState() { + return cn.getState(); + } + + public InputStream getStdout() { + return cn.getStdoutStream(); + } + + public InputStream getStderr() { + return cn.getStderrStream(); + } + + public OutputStream getStdin() { + return cn.getStdinStream(); + } + + /** + * This method blocks until there is more data available on either the + * stdout or stderr InputStream of this <code>Session</code>. Very useful + * if you do not want to use two parallel threads for reading from the two + * InputStreams. One can also specify a timeout. NOTE: do NOT call this + * method if you use concurrent threads that operate on either of the two + * InputStreams of this <code>Session</code> (otherwise this method may + * block, even though more data is available). + * + * @param timeout The (non-negative) timeout in <code>ms</code>. <code>0</code> means no + * timeout, the call may block forever. + * @return <ul> + * <li><code>0</code> if no more data will arrive.</li> + * <li><code>1</code> if more data is available.</li> + * <li><code>-1</code> if a timeout occurred.</li> + * </ul> + * @throws IOException + * @deprecated This method has been replaced with a much more powerful wait-for-condition + * interface and therefore acts only as a wrapper. + */ + public int waitUntilDataAvailable(long timeout) throws IOException { + if (timeout < 0) + throw new IllegalArgumentException("timeout must not be negative!"); + + int conditions = cm.waitForCondition(cn, timeout, ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA + | ChannelCondition.EOF); + + if ((conditions & ChannelCondition.TIMEOUT) != 0) + return -1; + + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) != 0) + return 1; + + /* Here we do not need to check separately for CLOSED, since CLOSED implies EOF */ + + if ((conditions & ChannelCondition.EOF) != 0) + return 0; + + throw new IllegalStateException("Unexpected condition result (" + conditions + ")"); + } + + /** + * This method blocks until certain conditions hold true on the underlying SSH-2 channel. + * <p/> + * This method returns as soon as one of the following happens: + * <ul> + * <li>at least of the specified conditions (see {@link ChannelCondition}) holds true</li> + * <li>timeout > 0 and a timeout occured (TIMEOUT will be set in result conditions)</a> + * <li>the underlying channel was closed (CLOSED will be set in result conditions)</a> + * </ul> + * <p/> + * In any case, the result value contains ALL current conditions, which may be more + * than the specified condition set (i.e., never use the "==" operator to test for conditions + * in the bitmask, see also comments in {@link ChannelCondition}). + * <p/> + * Note: do NOT call this method if you want to wait for STDOUT_DATA or STDERR_DATA and + * there are concurrent threads (e.g., StreamGobblers) that operate on either of the two + * InputStreams of this <code>Session</code> (otherwise this method may + * block, even though more data is available in the StreamGobblers). + * + * @param condition_set a bitmask based on {@link ChannelCondition} values + * @param timeout non-negative timeout in ms, <code>0</code> means no timeout + * @return all bitmask specifying all current conditions that are true + */ + + public int waitForCondition(int condition_set, long timeout) throws IOException { + if (timeout < 0) + throw new IllegalArgumentException("timeout must be non-negative!"); + + return cm.waitForCondition(cn, timeout, condition_set); + } + + /** + * Get the exit code/status from the remote command - if available. Be + * careful - not all server implementations return this value. It is + * generally a good idea to call this method only when all data from the + * remote side has been consumed (see also the <code<WaitForCondition</code> method). + * + * @return An <code>Integer</code> holding the exit code, or + * <code>null</code> if no exit code is (yet) available. + */ + public Integer getExitStatus() { + return cn.getExitStatus(); + } + + /** + * Get the name of the signal by which the process on the remote side was + * stopped - if available and applicable. Be careful - not all server + * implementations return this value. + * + * @return An <code>String</code> holding the name of the signal, or + * <code>null</code> if the process exited normally or is still + * running (or if the server forgot to send this information). + */ + public String getExitSignal() { + return cn.getExitSignal(); + } + + /** + * Close this session. NEVER forget to call this method to free up resources - + * even if you got an exception from one of the other methods (or when + * getting an Exception on the Input- or OutputStreams). Sometimes these other + * methods may throw an exception, saying that the underlying channel is + * closed (this can happen, e.g., if the other server sent a close message.) + * However, as long as you have not called the <code>close()</code> + * method, you may be wasting (local) resources. + */ + public void close() { + synchronized (this) { + if (flag_closed) + return; + + flag_closed = true; + + if (x11FakeCookie != null) + cm.unRegisterX11Cookie(x11FakeCookie, true); + + try { + cm.closeChannel(cn, "Closed due to user request", true); + } + catch (IOException ignored) { + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/SimpleServerSessionCallback.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2; + +import java.io.IOException; + +/** + * A basic ServerSessionCallback implementation. + * <p> + * Note: you should derive from this class instead of implementing + * the {@link ServerSessionCallback} interface directly. This way + * your code works also in case the interface gets extended in future + * versions. + * + * @author Christian + * + */ +public class SimpleServerSessionCallback implements ServerSessionCallback { + public Runnable requestShell(ServerSession ss) throws IOException { + return null; + } + + public Runnable requestExec(ServerSession ss, String command) throws IOException { + return null; + } + + public Runnable requestSubsystem(ServerSession ss, String subsystem) throws IOException { + return null; + } + + public Runnable requestPtyReq(ServerSession ss, PtySettings pty) throws IOException { + return null; + } + + /** + * By default, silently ignore passwd environment variables. + */ + public Runnable requestEnv(ServerSession ss, String name, String value) throws IOException { + return new Runnable() { + public void run() { + /* Do nothing */ + } + }; + } + + public void requestWindowChange(ServerSession ss, int term_width_columns, int term_height_rows, + int term_width_pixels, int term_height_pixels) throws IOException { + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/StreamGobbler.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; + +/** + * A <code>StreamGobbler</code> is an InputStream that uses an internal worker + * thread to constantly consume input from another InputStream. It uses a buffer + * to store the consumed data. The buffer size is automatically adjusted, if needed. + * <p/> + * This class is sometimes very convenient - if you wrap a session's STDOUT and STDERR + * InputStreams with instances of this class, then you don't have to bother about + * the shared window of STDOUT and STDERR in the low level SSH-2 protocol, + * since all arriving data will be immediatelly consumed by the worker threads. + * Also, as a side effect, the streams will be buffered (e.g., single byte + * read() operations are faster). + * <p/> + * Other SSH for Java libraries include this functionality by default in + * their STDOUT and STDERR InputStream implementations, however, please be aware + * that this approach has also a downside: + * <p/> + * If you do not call the StreamGobbler's <code>read()</code> method often enough + * and the peer is constantly sending huge amounts of data, then you will sooner or later + * encounter a low memory situation due to the aggregated data (well, it also depends on the Java heap size). + * Joe Average will like this class anyway - a paranoid programmer would never use such an approach. + * <p/> + * The term "StreamGobbler" was taken from an article called "When Runtime.exec() won't", + * see http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public class StreamGobbler extends InputStream { + class GobblerThread extends Thread { + @Override + public void run() { + byte[] buff = new byte[8192]; + + while (true) { + try { + int avail = is.read(buff); + + synchronized (synchronizer) { + if (avail <= 0) { + isEOF = true; + synchronizer.notifyAll(); + break; + } + + int space_available = buffer.length - write_pos; + + if (space_available < avail) { + /* compact/resize buffer */ + int unread_size = write_pos - read_pos; + int need_space = unread_size + avail; + byte[] new_buffer = buffer; + + if (need_space > buffer.length) { + int inc = need_space / 3; + inc = (inc < 256) ? 256 : inc; + inc = (inc > 8192) ? 8192 : inc; + new_buffer = new byte[need_space + inc]; + } + + if (unread_size > 0) + System.arraycopy(buffer, read_pos, new_buffer, 0, unread_size); + + buffer = new_buffer; + read_pos = 0; + write_pos = unread_size; + } + + System.arraycopy(buff, 0, buffer, write_pos, avail); + write_pos += avail; + synchronizer.notifyAll(); + } + } + catch (IOException e) { + synchronized (synchronizer) { + exception = e; + synchronizer.notifyAll(); + break; + } + } + } + } + } + + private InputStream is; + + private final Object synchronizer = new Object(); + + private boolean isEOF = false; + private boolean isClosed = false; + private IOException exception = null; + + private byte[] buffer = new byte[2048]; + private int read_pos = 0; + private int write_pos = 0; + + public StreamGobbler(InputStream is) { + this.is = is; + GobblerThread t = new GobblerThread(); + t.setDaemon(true); + t.start(); + } + + @Override + public int read() throws IOException { + synchronized (synchronizer) { + if (isClosed) + throw new IOException("This StreamGobbler is closed."); + + while (read_pos == write_pos) { + if (exception != null) + throw exception; + + if (isEOF) + return -1; + + try { + synchronizer.wait(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(); + } + } + + return buffer[read_pos++] & 0xff; + } + } + + @Override + public int available() throws IOException { + synchronized (synchronizer) { + if (isClosed) + throw new IOException("This StreamGobbler is closed."); + + return write_pos - read_pos; + } + } + + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + @Override + public void close() throws IOException { + synchronized (synchronizer) { + if (isClosed) + return; + + isClosed = true; + isEOF = true; + synchronizer.notifyAll(); + is.close(); + } + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (b == null) + throw new NullPointerException(); + + if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) + throw new IndexOutOfBoundsException(); + + if (len == 0) + return 0; + + synchronized (synchronizer) { + if (isClosed) + throw new IOException("This StreamGobbler is closed."); + + while (read_pos == write_pos) { + if (exception != null) + throw exception; + + if (isEOF) + return -1; + + try { + synchronizer.wait(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(); + } + } + + int avail = write_pos - read_pos; + avail = (avail > len) ? len : avail; + System.arraycopy(buffer, read_pos, b, off, avail); + read_pos += avail; + return avail; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/Version.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,26 @@ +package ch.ethz.ssh2; + +/** + * Provides version information from the manifest. + * + * @version $Id: Version.java 140 2014-04-15 13:16:25Z dkocher@sudo.ch $ + */ +public class Version { + public static String getSpecification() { + Package pkg = Version.class.getPackage(); + return (pkg == null) ? "SNAPSHOT" : pkg.getSpecificationVersion() == null ? "SNAPSHOT" : pkg.getSpecificationVersion(); + } + + public static String getImplementation() { + Package pkg = Version.class.getPackage(); + return (pkg == null) ? "SNAPSHOT" : pkg.getImplementationVersion() == null ? "SNAPSHOT" : pkg.getImplementationVersion(); + } + + /** + * A simple main method that prints the version and exits + */ + public static void main(String[] args) { + System.out.println("Version: " + getSpecification()); + System.out.println("Implementation: " + getImplementation()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/auth/AgentIdentity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.auth; + +public interface AgentIdentity { + String getAlgName(); + byte[] getPublicKeyBlob(); + byte[] sign(byte[] data); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/auth/AgentProxy.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.auth; + +import java.util.Collection; + +public interface AgentProxy { + public Collection<AgentIdentity> getIdentities(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/auth/AuthenticationManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.auth; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +import ch.ethz.ssh2.InteractiveCallback; +import ch.ethz.ssh2.PacketTypeException; +import ch.ethz.ssh2.crypto.PEMDecoder; +import ch.ethz.ssh2.packets.PacketServiceAccept; +import ch.ethz.ssh2.packets.PacketServiceRequest; +import ch.ethz.ssh2.packets.PacketUserauthBanner; +import ch.ethz.ssh2.packets.PacketUserauthFailure; +import ch.ethz.ssh2.packets.PacketUserauthInfoRequest; +import ch.ethz.ssh2.packets.PacketUserauthInfoResponse; +import ch.ethz.ssh2.packets.PacketUserauthRequestInteractive; +import ch.ethz.ssh2.packets.PacketUserauthRequestNone; +import ch.ethz.ssh2.packets.PacketUserauthRequestPassword; +import ch.ethz.ssh2.packets.PacketUserauthRequestPublicKey; +import ch.ethz.ssh2.packets.Packets; +import ch.ethz.ssh2.packets.TypesWriter; +import ch.ethz.ssh2.signature.DSASHA1Verify; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; +import ch.ethz.ssh2.signature.RSASHA1Verify; +import ch.ethz.ssh2.transport.ClientTransportManager; +import ch.ethz.ssh2.transport.MessageHandler; + +/** + * @author Christian Plattner + * @version $Id: AuthenticationManager.java 161 2014-05-01 18:01:55Z dkocher@sudo.ch $ + */ +public class AuthenticationManager implements MessageHandler { + private ClientTransportManager tm; + + private final BlockingQueue<byte[]> packets + = new ArrayBlockingQueue<byte[]>(5); + + private boolean connectionClosed = false; + + private String banner; + + private Set<String> remainingMethods + = new HashSet<String>(); + + private boolean isPartialSuccess = false; + + private boolean authenticated = false; + private boolean initDone = false; + + public AuthenticationManager(ClientTransportManager tm) { + this.tm = tm; + } + + private byte[] deQueue() throws IOException { + if (connectionClosed) { + throw(IOException) new IOException("The connection is closed.").initCause(tm.getReasonClosedCause()); + } + + // Wait for packet + try { + return packets.take(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(e.getMessage()); + } + } + + byte[] getNextMessage() throws IOException { + while (true) { + byte[] message = deQueue(); + + switch (message[0]) { + case Packets.SSH_MSG_USERAUTH_BANNER: + // The server may send an SSH_MSG_USERAUTH_BANNER message at any + // time after this authentication protocol starts and before + // authentication is successful. + PacketUserauthBanner sb = new PacketUserauthBanner(message); + banner = sb.getBanner(); + break; + + default: + return message; + } + } + } + + public Set<String> getRemainingMethods(String user) throws IOException { + initialize(user); + return remainingMethods; + } + + public String getBanner() { + return banner; + } + + public boolean getPartialSuccess() { + return isPartialSuccess; + } + + private boolean initialize(String user) throws IOException { + if (initDone == false) { + tm.registerMessageHandler(this, 0, 255); + PacketServiceRequest sr = new PacketServiceRequest("ssh-userauth"); + tm.sendMessage(sr.getPayload()); + final PacketServiceAccept accept = new PacketServiceAccept(this.getNextMessage()); + PacketUserauthRequestNone auth = new PacketUserauthRequestNone("ssh-connection", user); + tm.sendMessage(auth.getPayload()); + byte[] message = this.getNextMessage(); + initDone = true; + + switch (message[0]) { + case Packets.SSH_MSG_USERAUTH_SUCCESS: + authenticated = true; + tm.removeMessageHandler(this); + return true; + + case Packets.SSH_MSG_USERAUTH_FAILURE: + PacketUserauthFailure puf = new PacketUserauthFailure(message); + remainingMethods = puf.getAuthThatCanContinue(); + isPartialSuccess = puf.isPartialSuccess(); + return false; + } + + throw new PacketTypeException(message[0]); + } + + return authenticated; + } + + public boolean authenticatePublicKey(String user, AgentProxy proxy) throws IOException { + initialize(user); + boolean success; + + for (AgentIdentity identity : proxy.getIdentities()) { + success = authenticatePublicKey(user, identity); + + if (success) { + return true; + } + } + + return false; + } + + private boolean authenticatePublicKey(String user, AgentIdentity identity) throws IOException { + if (!remainingMethods.contains("publickey")) { + throw new IOException("Authentication method not supported"); + } + + byte[] pubKeyBlob = identity.getPublicKeyBlob(); + + if (pubKeyBlob == null) { + return false; + } + + TypesWriter tw = new TypesWriter(); + byte[] H = tm.getSessionIdentifier(); + tw.writeString(H, 0, H.length); + tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); + tw.writeString(user); + tw.writeString("ssh-connection"); + tw.writeString("publickey"); + tw.writeBoolean(true); + tw.writeString(identity.getAlgName()); + tw.writeString(pubKeyBlob, 0, pubKeyBlob.length); + byte[] msg = tw.getBytes(); + byte[] response = identity.sign(msg); + PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey( + "ssh-connection", user, identity.getAlgName(), pubKeyBlob, response); + tm.sendMessage(ua.getPayload()); + byte[] message = getNextMessage(); + final int type = message[0]; + + switch (type) { + case Packets.SSH_MSG_USERAUTH_SUCCESS: + authenticated = true; + tm.removeMessageHandler(this); + return true; + + case Packets.SSH_MSG_USERAUTH_FAILURE: + PacketUserauthFailure puf = new PacketUserauthFailure(message); + remainingMethods = puf.getAuthThatCanContinue(); + isPartialSuccess = puf.isPartialSuccess(); + return false; + } + + throw new PacketTypeException(type); + } + + public boolean authenticatePublicKey(String user, char[] PEMPrivateKey, String password, SecureRandom rnd) + throws IOException { + KeyPair pair = PEMDecoder.decode(PEMPrivateKey, password); + return authenticatePublicKey(user, pair, rnd); + } + + public boolean authenticatePublicKey(String user, KeyPair pair, SecureRandom rnd) + throws IOException { + PrivateKey key = pair.getPrivate(); + + try { + initialize(user); + + if (!remainingMethods.contains("publickey")) { + throw new IOException("Authentication method publickey not supported by the server at this stage."); + } + + if (key instanceof DSAPrivateKey) { + DSAPrivateKey pk = (DSAPrivateKey) key; + byte[] pk_enc = DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey) pair.getPublic()); + TypesWriter tw = new TypesWriter(); + byte[] H = tm.getSessionIdentifier(); + tw.writeString(H, 0, H.length); + tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); + tw.writeString(user); + tw.writeString("ssh-connection"); + tw.writeString("publickey"); + tw.writeBoolean(true); + tw.writeString("ssh-dss"); + tw.writeString(pk_enc, 0, pk_enc.length); + byte[] msg = tw.getBytes(); + byte[] ds = DSASHA1Verify.generateSignature(msg, pk, rnd); + byte[] ds_enc = DSASHA1Verify.encodeSSHDSASignature(ds); + PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, + "ssh-dss", pk_enc, ds_enc); + tm.sendMessage(ua.getPayload()); + } + else if (key instanceof RSAPrivateKey) { + RSAPrivateKey pk = (RSAPrivateKey) key; + byte[] pk_enc = RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey) pair.getPublic()); + TypesWriter tw = new TypesWriter(); + { + byte[] H = tm.getSessionIdentifier(); + tw.writeString(H, 0, H.length); + tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); + tw.writeString(user); + tw.writeString("ssh-connection"); + tw.writeString("publickey"); + tw.writeBoolean(true); + tw.writeString("ssh-rsa"); + tw.writeString(pk_enc, 0, pk_enc.length); + } + byte[] msg = tw.getBytes(); + byte[] ds = RSASHA1Verify.generateSignature(msg, pk); + byte[] rsa_sig_enc = RSASHA1Verify.encodeSSHRSASignature(ds); + PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, + "ssh-rsa", pk_enc, rsa_sig_enc); + tm.sendMessage(ua.getPayload()); + } + else if (key instanceof ECPrivateKey) { + ECPrivateKey pk = (ECPrivateKey) key; + final String algo = ECDSASHA2Verify.ECDSA_SHA2_PREFIX + + ECDSASHA2Verify.getCurveName(pk.getParams()); + byte[] pk_enc = ECDSASHA2Verify.encodeSSHECDSAPublicKey((ECPublicKey) pair.getPublic()); + TypesWriter tw = new TypesWriter(); + { + byte[] H = tm.getSessionIdentifier(); + tw.writeString(H, 0, H.length); + tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); + tw.writeString(user); + tw.writeString("ssh-connection"); + tw.writeString("publickey"); + tw.writeBoolean(true); + tw.writeString(algo); + tw.writeString(pk_enc, 0, pk_enc.length); + } + byte[] msg = tw.getBytes(); + byte[] ds = ECDSASHA2Verify.generateSignature(msg, pk); + byte[] ec_sig_enc = ECDSASHA2Verify.encodeSSHECDSASignature(ds, pk.getParams()); + PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, + algo, pk_enc, ec_sig_enc); + tm.sendMessage(ua.getPayload()); + } + else { + throw new IOException("Unknown private key type returned by the PEM decoder."); + } + + byte[] message = getNextMessage(); + final int type = message[0]; + + switch (type) { + case Packets.SSH_MSG_USERAUTH_SUCCESS: + authenticated = true; + tm.removeMessageHandler(this); + return true; + + case Packets.SSH_MSG_USERAUTH_FAILURE: + PacketUserauthFailure puf = new PacketUserauthFailure(message); + remainingMethods = puf.getAuthThatCanContinue(); + isPartialSuccess = puf.isPartialSuccess(); + return false; + } + + throw new PacketTypeException(type); + } + catch (IOException e) { + tm.close(e, false); + throw e; + } + } + + public boolean authenticateNone(String user) throws IOException { + try { + initialize(user); + return authenticated; + } + catch (IOException e) { + tm.close(e, false); + throw e; + } + } + + public boolean authenticatePassword(String user, String pass) throws IOException { + try { + initialize(user); + + if (!remainingMethods.contains("password")) { + throw new IOException("Authentication method not supported"); + } + + PacketUserauthRequestPassword ua = new PacketUserauthRequestPassword("ssh-connection", user, pass); + tm.sendMessage(ua.getPayload()); + byte[] message = getNextMessage(); + final int type = message[0]; + + switch (type) { + case Packets.SSH_MSG_USERAUTH_SUCCESS: + authenticated = true; + tm.removeMessageHandler(this); + return true; + + case Packets.SSH_MSG_USERAUTH_FAILURE: + PacketUserauthFailure puf = new PacketUserauthFailure(message); + remainingMethods = puf.getAuthThatCanContinue(); + isPartialSuccess = puf.isPartialSuccess(); + return false; + } + + throw new PacketTypeException(type); + } + catch (IOException e) { + tm.close(e, false); + throw e; + } + } + + public boolean authenticateInteractive(String user, String[] submethods, InteractiveCallback cb) throws IOException { + try { + initialize(user); + + if (!remainingMethods.contains("keyboard-interactive")) { + throw new IOException( + "Authentication method keyboard-interactive not supported by the server at this stage."); + } + + PacketUserauthRequestInteractive ua = new PacketUserauthRequestInteractive("ssh-connection", user, + submethods); + tm.sendMessage(ua.getPayload()); + + while (true) { + byte[] message = getNextMessage(); + final int type = message[0]; + + switch (type) { + case Packets.SSH_MSG_USERAUTH_SUCCESS: + authenticated = true; + tm.removeMessageHandler(this); + return true; + + case Packets.SSH_MSG_USERAUTH_FAILURE: + PacketUserauthFailure puf = new PacketUserauthFailure(message); + remainingMethods = puf.getAuthThatCanContinue(); + isPartialSuccess = puf.isPartialSuccess(); + return false; + + case Packets.SSH_MSG_USERAUTH_INFO_REQUEST: + PacketUserauthInfoRequest info = new PacketUserauthInfoRequest(message); + String[] responses; + + try { + responses = cb.replyToChallenge(info.getName(), info.getInstruction(), info.getNumPrompts(), + info.getPrompt(), info.getEcho()); + } + catch (Exception e) { + throw new IOException("Exception in callback.", e); + } + + PacketUserauthInfoResponse puir = new PacketUserauthInfoResponse(responses); + tm.sendMessage(puir.getPayload()); + continue; + } + + throw new PacketTypeException(type); + } + } + catch (IOException e) { + tm.close(e, false); + throw e; + } + } + + public void handleFailure(final IOException failure) { + connectionClosed = true; + } + + public void handleMessage(byte[] message) throws IOException { + packets.add(message); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/auth/ServerAuthenticationManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,128 @@ + +package ch.ethz.ssh2.auth; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import ch.ethz.ssh2.AuthenticationResult; +import ch.ethz.ssh2.PacketTypeException; +import ch.ethz.ssh2.ServerAuthenticationCallback; +import ch.ethz.ssh2.channel.ChannelManager; +import ch.ethz.ssh2.packets.PacketServiceAccept; +import ch.ethz.ssh2.packets.PacketServiceRequest; +import ch.ethz.ssh2.packets.PacketUserauthBanner; +import ch.ethz.ssh2.packets.PacketUserauthFailure; +import ch.ethz.ssh2.packets.PacketUserauthSuccess; +import ch.ethz.ssh2.packets.Packets; +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.server.ServerConnectionState; +import ch.ethz.ssh2.transport.MessageHandler; + +public class ServerAuthenticationManager implements MessageHandler { + private final ServerConnectionState state; + + public ServerAuthenticationManager(ServerConnectionState state) { + this.state = state; + state.tm.registerMessageHandler(this, 0, 255); + } + + private void sendresult(AuthenticationResult result) throws IOException { + if (AuthenticationResult.SUCCESS == result) { + PacketUserauthSuccess pus = new PacketUserauthSuccess(); + state.tm.sendAsynchronousMessage(pus.getPayload()); + state.tm.removeMessageHandler(this); + state.tm.registerMessageHandler(this, 50, 79); + state.cm = new ChannelManager(state); + state.flag_auth_completed = true; + } + else { + Set<String> remaining_methods = new HashSet<String>(); + + if (state.cb_auth != null) { + remaining_methods.addAll(Arrays.asList( + state.cb_auth.getRemainingAuthMethods(state.conn))); + } + + PacketUserauthFailure puf = new PacketUserauthFailure(remaining_methods, + AuthenticationResult.PARTIAL_SUCCESS == result); + state.tm.sendAsynchronousMessage(puf.getPayload()); + } + } + + public void handleFailure(final IOException failure) { + // + } + + public void handleMessage(byte[] msg) throws IOException { + /* Ignore all authentication messages after successful auth */ + if (state.flag_auth_completed) { + return; + } + + if (!state.flag_auth_serviceRequested) { + /* Must be PacketServiceRequest */ + PacketServiceRequest psr = new PacketServiceRequest(msg); + + if (!"ssh-userauth".equals(psr.getServiceName())) { + throw new IOException("SSH protocol error, expected ssh-userauth service request"); + } + + PacketServiceAccept psa = new PacketServiceAccept("ssh-userauth"); + state.tm.sendAsynchronousMessage(psa.getPayload()); + String banner = state.cb_auth.initAuthentication(state.conn); + + if (banner != null) { + PacketUserauthBanner pub = new PacketUserauthBanner(banner); + state.tm.sendAsynchronousMessage(pub.getPayload()); + } + + state.flag_auth_serviceRequested = true; + return; + } + + ServerAuthenticationCallback cb = state.cb_auth; + TypesReader tr = new TypesReader(msg); + int packet_type = tr.readByte(); + + if (packet_type == Packets.SSH_MSG_USERAUTH_REQUEST) { + String username = tr.readString("UTF-8"); + String service = tr.readString(); + String method = tr.readString(); + + if (!"ssh-connection".equals(service)) { + sendresult(AuthenticationResult.FAILURE); + return; + } + + if ("none".equals(method)) { + if (cb != null) { + sendresult(cb.authenticateWithNone(state.conn, username)); + return; + } + } + + if ("password".equals(method)) { + boolean flag_change_pass = tr.readBoolean(); + + if (flag_change_pass) { + sendresult(AuthenticationResult.FAILURE); + return; + } + + String password = tr.readString("UTF-8"); + + if (cb != null) { + sendresult(cb.authenticateWithPassword(state.conn, username, password)); + return; + } + } + + sendresult(AuthenticationResult.FAILURE); + return; + } + + throw new PacketTypeException(packet_type); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/AuthAgentForwardThread.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,546 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.DSAPrivateKeySpec; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.RSAPrivateCrtKeySpec; +import java.security.spec.RSAPublicKeySpec; +import java.util.Map; +import java.util.Map.Entry; + +import ch.ethz.ssh2.AuthAgentCallback; +import ch.ethz.ssh2.crypto.SecureRandomFix; +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.packets.TypesWriter; +import ch.ethz.ssh2.signature.DSASHA1Verify; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; +import ch.ethz.ssh2.signature.RSASHA1Verify; + +/** + * AuthAgentForwardThread. + * + * @author Kenny Root + * @version $Id$ + */ +public class AuthAgentForwardThread extends Thread implements IChannelWorkerThread { + private static final byte[] SSH_AGENT_FAILURE = {0, 0, 0, 1, 5}; // 5 + private static final byte[] SSH_AGENT_SUCCESS = {0, 0, 0, 1, 6}; // 6 + + private static final int SSH2_AGENTC_REQUEST_IDENTITIES = 11; + private static final int SSH2_AGENT_IDENTITIES_ANSWER = 12; + + private static final int SSH2_AGENTC_SIGN_REQUEST = 13; + private static final int SSH2_AGENT_SIGN_RESPONSE = 14; + + private static final int SSH2_AGENTC_ADD_IDENTITY = 17; + private static final int SSH2_AGENTC_REMOVE_IDENTITY = 18; + private static final int SSH2_AGENTC_REMOVE_ALL_IDENTITIES = 19; + +// private static final int SSH_AGENTC_ADD_SMARTCARD_KEY = 20; +// private static final int SSH_AGENTC_REMOVE_SMARTCARD_KEY = 21; + + private static final int SSH_AGENTC_LOCK = 22; + private static final int SSH_AGENTC_UNLOCK = 23; + + private static final int SSH2_AGENTC_ADD_ID_CONSTRAINED = 25; +// private static final int SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED = 26; + + // Constraints for adding keys + private static final int SSH_AGENT_CONSTRAIN_LIFETIME = 1; + private static final int SSH_AGENT_CONSTRAIN_CONFIRM = 2; + + // Flags for signature requests +// private static final int SSH_AGENT_OLD_SIGNATURE = 1; + + private static final Logger log = Logger.getLogger(RemoteAcceptThread.class); + + AuthAgentCallback authAgent; + OutputStream os; + InputStream is; + Channel c; + + byte[] buffer = new byte[Channel.CHANNEL_BUFFER_SIZE]; + + public AuthAgentForwardThread(Channel c, AuthAgentCallback authAgent) { + this.c = c; + this.authAgent = authAgent; + log.debug("AuthAgentForwardThread started"); + } + + @Override + public void run() { + try { + c.cm.registerThread(this); + } + catch (IOException e) { + stopWorking(); + return; + } + + try { + c.cm.sendOpenConfirmation(c); + is = c.getStdoutStream(); + os = c.getStdinStream(); + int totalSize = 4; + int readSoFar = 0; + + while (true) { + int len; + + try { + len = is.read(buffer, readSoFar, buffer.length - readSoFar); + } + catch (IOException e) { + stopWorking(); + return; + } + + if (len <= 0) + break; + + readSoFar += len; + + if (readSoFar >= 4) { + TypesReader tr = new TypesReader(buffer, 0, 4); + totalSize = tr.readUINT32() + 4; + } + + if (totalSize == readSoFar) { + TypesReader tr = new TypesReader(buffer, 4, readSoFar - 4); + int messageType = tr.readByte(); + + switch (messageType) { + case SSH2_AGENTC_REQUEST_IDENTITIES: + sendIdentities(); + break; + + case SSH2_AGENTC_ADD_IDENTITY: + addIdentity(tr, false); + break; + + case SSH2_AGENTC_ADD_ID_CONSTRAINED: + addIdentity(tr, true); + break; + + case SSH2_AGENTC_REMOVE_IDENTITY: + removeIdentity(tr); + break; + + case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: + removeAllIdentities(tr); + break; + + case SSH2_AGENTC_SIGN_REQUEST: + processSignRequest(tr); + break; + + case SSH_AGENTC_LOCK: + processLockRequest(tr); + break; + + case SSH_AGENTC_UNLOCK: + processUnlockRequest(tr); + break; + + default: + os.write(SSH_AGENT_FAILURE); + break; + } + + readSoFar = 0; + } + } + + c.cm.closeChannel(c, "EOF on both streams reached.", true); + } + catch (IOException e) { + log.debug("IOException in agent forwarder: " + e.getMessage()); + + try { + is.close(); + } + catch (IOException e1) { + } + + try { + os.close(); + } + catch (IOException e2) { + } + + try { + c.cm.closeChannel(c, "IOException in agent forwarder (" + e.getMessage() + ")", true); + } + catch (IOException e3) { + } + } + } + + public void stopWorking() { + try { + /* This will lead to an IOException in the is.read() call */ + is.close(); + } + catch (IOException e) { + } + } + + /** + * @return whether the agent is locked + */ + private boolean failWhenLocked() throws IOException { + if (authAgent.isAgentLocked()) { + os.write(SSH_AGENT_FAILURE); + return true; + } + else + return false; + } + + private void sendIdentities() throws IOException { + Map<String, byte[]> keys = null; + TypesWriter tw = new TypesWriter(); + tw.writeByte(SSH2_AGENT_IDENTITIES_ANSWER); + int numKeys = 0; + + if (!authAgent.isAgentLocked()) + keys = authAgent.retrieveIdentities(); + + if (keys != null) + numKeys = keys.size(); + + tw.writeUINT32(numKeys); + + if (keys != null) { + for (Entry<String, byte[]> entry : keys.entrySet()) { + byte[] keyBytes = entry.getValue(); + tw.writeString(keyBytes, 0, keyBytes.length); + tw.writeString(entry.getKey()); + } + } + + sendPacket(tw.getBytes()); + } + + /** + * @param tr + */ + private void addIdentity(TypesReader tr, boolean checkConstraints) { + try { + if (failWhenLocked()) + return; + + String type = tr.readString(); + String comment; + String keyType; + KeySpec pubSpec; + KeySpec privSpec; + + if (type.equals("ssh-rsa")) { + keyType = "RSA"; + BigInteger n = tr.readMPINT(); + BigInteger e = tr.readMPINT(); + BigInteger d = tr.readMPINT(); + BigInteger iqmp = tr.readMPINT(); + BigInteger p = tr.readMPINT(); + BigInteger q = tr.readMPINT(); + comment = tr.readString(); + // Derive the extra values Java needs. + BigInteger dmp1 = d.mod(p.subtract(BigInteger.ONE)); + BigInteger dmq1 = d.mod(q.subtract(BigInteger.ONE)); + pubSpec = new RSAPublicKeySpec(n, e); + privSpec = new RSAPrivateCrtKeySpec(n, e, d, p, q, dmp1, dmq1, iqmp); + } + else if (type.equals("ssh-dss")) { + keyType = "DSA"; + BigInteger p = tr.readMPINT(); + BigInteger q = tr.readMPINT(); + BigInteger g = tr.readMPINT(); + BigInteger y = tr.readMPINT(); + BigInteger x = tr.readMPINT(); + comment = tr.readString(); + pubSpec = new DSAPublicKeySpec(y, p, q, g); + privSpec = new DSAPrivateKeySpec(x, p, q, g); + } + else if (type.equals("ecdsa-sha2-nistp256")) { + keyType = "EC"; + String curveName = tr.readString(); + byte[] groupBytes = tr.readByteString(); + BigInteger exponent = tr.readMPINT(); + comment = tr.readString(); + + if (!"nistp256".equals(curveName)) { + log.debug("Invalid curve name for ecdsa-sha2-nistp256: " + curveName); + os.write(SSH_AGENT_FAILURE); + return; + } + + ECParameterSpec nistp256 = ECDSASHA2Verify.EllipticCurves.nistp256; + ECPoint group = ECDSASHA2Verify.decodeECPoint(groupBytes, nistp256.getCurve()); + + if (group == null) { + log.debug("No groupfor ecdsa-sha2-nistp256: "); + os.write(SSH_AGENT_FAILURE); + return; + } + + pubSpec = new ECPublicKeySpec(group, nistp256); + privSpec = new ECPrivateKeySpec(exponent, nistp256); + } + else { + log.debug("Unknown key type: " + type); + os.write(SSH_AGENT_FAILURE); + return; + } + + PublicKey pubKey; + PrivateKey privKey; + + try { + KeyFactory kf = KeyFactory.getInstance(keyType); + pubKey = kf.generatePublic(pubSpec); + privKey = kf.generatePrivate(privSpec); + } + catch (NoSuchAlgorithmException ex) { + // TODO: log error + os.write(SSH_AGENT_FAILURE); + return; + } + catch (InvalidKeySpecException ex) { + // TODO: log error + os.write(SSH_AGENT_FAILURE); + return; + } + + KeyPair pair = new KeyPair(pubKey, privKey); + boolean confirmUse = false; + int lifetime = 0; + + if (checkConstraints) { + while (tr.remain() > 0) { + int constraint = tr.readByte(); + + if (constraint == SSH_AGENT_CONSTRAIN_CONFIRM) + confirmUse = true; + else if (constraint == SSH_AGENT_CONSTRAIN_LIFETIME) + lifetime = tr.readUINT32(); + else { + // Unknown constraint. Bail. + os.write(SSH_AGENT_FAILURE); + return; + } + } + } + + if (authAgent.addIdentity(pair, comment, confirmUse, lifetime)) + os.write(SSH_AGENT_SUCCESS); + else + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e) { + try { + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e1) { + } + } + } + + /** + * @param tr + */ + private void removeIdentity(TypesReader tr) { + try { + if (failWhenLocked()) + return; + + byte[] publicKey = tr.readByteString(); + + if (authAgent.removeIdentity(publicKey)) + os.write(SSH_AGENT_SUCCESS); + else + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e) { + try { + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e1) { + } + } + } + + /** + * @param tr + */ + private void removeAllIdentities(TypesReader tr) { + try { + if (failWhenLocked()) + return; + + if (authAgent.removeAllIdentities()) + os.write(SSH_AGENT_SUCCESS); + else + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e) { + try { + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e1) { + } + } + } + + private void processSignRequest(TypesReader tr) { + try { + if (failWhenLocked()) + return; + + byte[] publicKeyBytes = tr.readByteString(); + byte[] challenge = tr.readByteString(); + int flags = tr.readUINT32(); + + if (flags != 0) { + // We don't understand any flags; abort! + os.write(SSH_AGENT_FAILURE); + return; + } + + KeyPair pair = authAgent.getKeyPair(publicKeyBytes); + + if (pair == null) { + os.write(SSH_AGENT_FAILURE); + return; + } + + byte[] response; + PrivateKey privKey = pair.getPrivate(); + + if (privKey instanceof RSAPrivateKey) { + byte[] signature = RSASHA1Verify.generateSignature(challenge, + (RSAPrivateKey) privKey); + response = RSASHA1Verify.encodeSSHRSASignature(signature); + } + else if (privKey instanceof DSAPrivateKey) { + byte[] signature = DSASHA1Verify.generateSignature(challenge, + (DSAPrivateKey) privKey, new SecureRandomFix()); + response = DSASHA1Verify.encodeSSHDSASignature(signature); + } + else if (privKey instanceof ECPrivateKey) { + ECPrivateKey pk = (ECPrivateKey) privKey; + byte[] signature = ECDSASHA2Verify.generateSignature(challenge, pk); + response = ECDSASHA2Verify.encodeSSHECDSASignature(signature, pk.getParams()); + } + else { + os.write(SSH_AGENT_FAILURE); + return; + } + + TypesWriter tw = new TypesWriter(); + tw.writeByte(SSH2_AGENT_SIGN_RESPONSE); + tw.writeString(response, 0, response.length); + sendPacket(tw.getBytes()); + } + catch (IOException e) { + try { + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e1) { + } + } + } + + /** + * @param tr + */ + private void processLockRequest(TypesReader tr) { + try { + if (failWhenLocked()) + return; + + String lockPassphrase = tr.readString(); + + if (!authAgent.setAgentLock(lockPassphrase)) { + os.write(SSH_AGENT_FAILURE); + return; + } + else + os.write(SSH_AGENT_SUCCESS); + } + catch (IOException e) { + try { + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e1) { + } + } + } + + /** + * @param tr + */ + private void processUnlockRequest(TypesReader tr) { + try { + String unlockPassphrase = tr.readString(); + + if (authAgent.requestAgentUnlock(unlockPassphrase)) + os.write(SSH_AGENT_SUCCESS); + else + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e) { + try { + os.write(SSH_AGENT_FAILURE); + } + catch (IOException e1) { + } + } + } + + /** + * @param tw + * @throws IOException + */ + private void sendPacket(byte[] message) throws IOException { + TypesWriter packet = new TypesWriter(); + packet.writeUINT32(message.length); + packet.writeBytes(message); + os.write(packet.getBytes()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/Channel.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +import java.io.IOException; + +import ch.ethz.ssh2.transport.TransportManager; + +/** + * Channel. + * + * @author Christian Plattner + * @version $Id: Channel.java 123 2014-04-12 21:11:47Z dkocher@sudo.ch $ + */ +public class Channel { + /* + * OK. Here is an important part of the JVM Specification: + * (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html#22214) + * + * Any association between locks and variables is purely conventional. + * Locking any lock conceptually flushes all variables from a thread's + * working memory, and unlocking any lock forces the writing out to main + * memory of all variables that the thread has assigned. That a lock may be + * associated with a particular object or a class is purely a convention. + * (...) + * + * If a thread uses a particular shared variable only after locking a + * particular lock and before the corresponding unlocking of that same lock, + * then the thread will read the shared value of that variable from main + * memory after the lock operation, if necessary, and will copy back to main + * memory the value most recently assigned to that variable before the + * unlock operation. + * + * This, in conjunction with the mutual exclusion rules for locks, suffices + * to guarantee that values are correctly transmitted from one thread to + * another through shared variables. + * + * ====> Always keep that in mind when modifying the Channel/ChannelManger + * code. + * + */ + + public static final int STATE_OPENING = 1; + public static final int STATE_OPEN = 2; + public static final int STATE_CLOSED = 4; + + static final int CHANNEL_BUFFER_SIZE = 32 * 1024 * 3 * 2; + + /* + * To achieve correctness, the following rules have to be respected when + * accessing this object: + */ + + // These fields can always be read + final ChannelManager cm; + final ChannelOutputStream stdinStream; + final ChannelInputStream stdoutStream; + final ChannelInputStream stderrStream; + + // In case this channel belongs to a server-side session. + ServerSessionImpl ss; + + // These two fields will only be written while the Channel is in state + // STATE_OPENING. + // The code makes sure that the two fields are written out when the state is + // changing to STATE_OPEN. + // Therefore, if you know that the Channel is in state STATE_OPEN, then you + // can read these two fields without synchronizing on the Channel. However, make + // sure that you get the latest values (e.g., flush caches by synchronizing on any + // object). However, to be on the safe side, you can lock the channel. + + int localID = -1; + int remoteID = -1; + + /* + * Make sure that we never send a data/EOF/WindowChange msg after a CLOSE + * msg. + * + * This is a little bit complicated, but we have to do it in that way, since + * we cannot keep a lock on the Channel during the send operation (this + * would block sometimes the receiver thread, and, in extreme cases, can + * lead to a deadlock on both sides of the connection (senders are blocked + * since the receive buffers on the other side are full, and receiver + * threads wait for the senders to finish). It all depends on the + * implementation on the other side. But we cannot make any assumptions, we + * have to assume the worst case. Confused? Just believe me. + */ + + /* + * If you send a message on a channel, then you have to aquire the + * "channelSendLock" and check the "closeMessageSent" flag (this variable + * may only be accessed while holding the "channelSendLock" !!! + * + * BTW: NEVER EVER SEND MESSAGES FROM THE RECEIVE THREAD - see explanation + * above. + */ + + final Object channelSendLock = new Object(); + boolean closeMessageSent = false; + + /* + * Stop memory fragmentation by allocating this often used buffer. + * May only be used while holding the channelSendLock + */ + + final byte[] msgWindowAdjust = new byte[9]; + + // If you access (read or write) any of the following fields, then you have + // to synchronize on the channel. + + int state = STATE_OPENING; + + boolean closeMessageRecv = false; + + /* This is a stupid implementation. At the moment we can only wait + * for one pending request per channel. + */ + int successCounter = 0; + int failedCounter = 0; + + int localWindow = 0; /* locally, we use a small window, < 2^31 */ + long remoteWindow = 0; /* long for readable 2^32 - 1 window support */ + + int localMaxPacketSize = -1; + int remoteMaxPacketSize = -1; + + final byte[] stdoutBuffer = new byte[CHANNEL_BUFFER_SIZE]; + final byte[] stderrBuffer = new byte[CHANNEL_BUFFER_SIZE]; + + int stdoutReadpos = 0; + int stdoutWritepos = 0; + int stderrReadpos = 0; + int stderrWritepos = 0; + + boolean EOF = false; + + Integer exit_status; + + String exit_signal; + + // we keep the x11 cookie so that this channel can be closed when this + // specific x11 forwarding gets stopped + + String hexX11FakeCookie; + + // reasonClosed is special, since we sometimes need to access it + // while holding the channelSendLock. + // We protect it with a private short term lock. + + private final Object reasonClosedLock = new Object(); + private IOException reasonClosed = null; + + public Channel(ChannelManager cm) { + this.cm = cm; + this.localWindow = CHANNEL_BUFFER_SIZE; + this.localMaxPacketSize = TransportManager.MAX_PACKET_SIZE; + this.stdinStream = new ChannelOutputStream(this); + this.stdoutStream = new ChannelInputStream(this, false); + this.stderrStream = new ChannelInputStream(this, true); + } + + /* Methods to allow access from classes outside of this package */ + + public ChannelInputStream getStderrStream() { + return stderrStream; + } + + public ChannelOutputStream getStdinStream() { + return stdinStream; + } + + public ChannelInputStream getStdoutStream() { + return stdoutStream; + } + + public String getExitSignal() { + synchronized (this) { + return exit_signal; + } + } + + public Integer getExitStatus() { + synchronized (this) { + return exit_status; + } + } + + public IOException getReasonClosed() { + synchronized (reasonClosedLock) { + return reasonClosed; + } + } + + public void setReasonClosed(IOException e) { + synchronized (reasonClosedLock) { + this.reasonClosed = e; + } + } + + public int getState() { + return this.state; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/ChannelClosedException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2011 David Kocher. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2.channel; + +import java.io.IOException; + +/** + * @version $Id: ChannelClosedException.java 3183 2007-07-30 19:22:34Z dkocher $ + */ +public class ChannelClosedException extends IOException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public ChannelClosedException(String s) { + super(s); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/ChannelInputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.io.InputStream; + +/** + * ChannelInputStream. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class ChannelInputStream extends InputStream { + Channel c; + + boolean isClosed = false; + boolean isEOF = false; + boolean extendedFlag = false; + + ChannelInputStream(Channel c, boolean isExtended) { + this.c = c; + this.extendedFlag = isExtended; + } + + @Override + public int available() throws IOException { + if (isEOF) + return 0; + + int avail = c.cm.getAvailable(c, extendedFlag); + /* We must not return -1 on EOF */ + return (avail > 0) ? avail : 0; + } + + @Override + public void close() throws IOException { + isClosed = true; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (b == null) + throw new NullPointerException(); + + if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) + throw new IndexOutOfBoundsException(); + + if (len == 0) + return 0; + + if (isEOF) + return -1; + + int ret = c.cm.getChannelData(c, extendedFlag, b, off, len); + + if (ret == -1) { + isEOF = true; + } + + return ret; + } + + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + @Override + public int read() throws IOException { + /* Yes, this stream is pure and unbuffered, a single byte read() is slow */ + final byte b[] = new byte[1]; + int ret = read(b, 0, 1); + + if (ret != 1) + return -1; + + return b[0] & 0xff; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/ChannelManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1653 @@ +/* + + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import ch.ethz.ssh2.AuthAgentCallback; +import ch.ethz.ssh2.ChannelCondition; +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; +import ch.ethz.ssh2.PtySettings; +import ch.ethz.ssh2.ServerConnectionCallback; +import ch.ethz.ssh2.ServerSessionCallback; +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.PacketChannelAuthAgentReq; +import ch.ethz.ssh2.packets.PacketChannelFailure; +import ch.ethz.ssh2.packets.PacketChannelOpenConfirmation; +import ch.ethz.ssh2.packets.PacketChannelOpenFailure; +import ch.ethz.ssh2.packets.PacketChannelSuccess; +import ch.ethz.ssh2.packets.PacketGlobalCancelForwardRequest; +import ch.ethz.ssh2.packets.PacketGlobalForwardRequest; +import ch.ethz.ssh2.packets.PacketOpenDirectTCPIPChannel; +import ch.ethz.ssh2.packets.PacketOpenSessionChannel; +import ch.ethz.ssh2.packets.PacketSessionExecCommand; +import ch.ethz.ssh2.packets.PacketSessionPtyRequest; +import ch.ethz.ssh2.packets.PacketSessionStartShell; +import ch.ethz.ssh2.packets.PacketSessionSubsystemRequest; +import ch.ethz.ssh2.packets.PacketSessionX11Request; +import ch.ethz.ssh2.packets.PacketWindowChange; +import ch.ethz.ssh2.packets.Packets; +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.server.ServerConnectionState; +import ch.ethz.ssh2.transport.MessageHandler; +import ch.ethz.ssh2.transport.TransportManager; + +/** + * ChannelManager. Please read the comments in Channel.java. + * <p/> + * Besides the crypto part, this is the core of the library. + * + * @author Christian Plattner + * @version $Id: ChannelManager.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public class ChannelManager implements MessageHandler { + private static final Logger log = Logger.getLogger(ChannelManager.class); + + private final ServerConnectionState server_state; + private final TransportManager tm; + + private final Map<String, X11ServerData> x11_magic_cookies = new HashMap<String, X11ServerData>(); + + private final List<Channel> channels = new ArrayList<Channel>(); + private int nextLocalChannel = 100; + private boolean shutdown = false; + private int globalSuccessCounter = 0; + private int globalFailedCounter = 0; + + private final HashMap<Integer, RemoteForwardingData> remoteForwardings = new HashMap<Integer, RemoteForwardingData>(); + + private AuthAgentCallback authAgent; + + private final List<IChannelWorkerThread> listenerThreads = new ArrayList<IChannelWorkerThread>(); + + private boolean listenerThreadsAllowed = true; + + /** + * Constructor for client-mode. + * + * @param tm + */ + public ChannelManager(TransportManager tm) { + this.server_state = null; + this.tm = tm; + tm.registerMessageHandler(this, 80, 100); + } + + /** + * Constructor for server-mode. + * + * @param state + */ + public ChannelManager(ServerConnectionState state) { + this.server_state = state; + this.tm = state.tm; + tm.registerMessageHandler(this, 80, 100); + } + + private Channel getChannel(int id) { + synchronized (channels) { + for (Channel c : channels) { + if (c.localID == id) { + return c; + } + } + } + + return null; + } + + private void removeChannel(int id) { + synchronized (channels) { + for (Channel c : channels) { + if (c.localID == id) { + channels.remove(c); + break; + } + } + } + } + + private int addChannel(Channel c) { + synchronized (channels) { + channels.add(c); + return nextLocalChannel++; + } + } + + private void waitUntilChannelOpen(Channel c) throws IOException { + synchronized (c) { + while (c.state == Channel.STATE_OPENING) { + try { + c.wait(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(e.getMessage()); + } + } + + if (c.state != Channel.STATE_OPEN) { + removeChannel(c.localID); + throw c.getReasonClosed(); + } + } + } + + private void waitForGlobalSuccessOrFailure() throws IOException { + synchronized (channels) { + while ((globalSuccessCounter == 0) && (globalFailedCounter == 0)) { + if (shutdown) { + throw new IOException("The connection is being shutdown"); + } + + try { + channels.wait(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(e.getMessage()); + } + } + + if ((globalFailedCounter == 0) && (globalSuccessCounter == 1)) { + return; + } + + if ((globalFailedCounter == 1) && (globalSuccessCounter == 0)) { + throw new IOException("The server denied the request (did you enable port forwarding?)"); + } + + throw new IOException("Illegal state. The server sent " + globalSuccessCounter + + " SSH_MSG_REQUEST_SUCCESS and " + globalFailedCounter + " SSH_MSG_REQUEST_FAILURE messages."); + } + } + + private void waitForChannelSuccessOrFailure(Channel c) throws IOException { + synchronized (c) { + while ((c.successCounter == 0) && (c.failedCounter == 0)) { + if (c.state != Channel.STATE_OPEN) { + throw c.getReasonClosed(); + } + + try { + c.wait(); + } + catch (InterruptedException ignore) { + throw new InterruptedIOException(); + } + } + + if ((c.failedCounter == 0) && (c.successCounter == 1)) { + return; + } + + if ((c.failedCounter == 1) && (c.successCounter == 0)) { + throw new IOException("The server denied the request."); + } + + throw new IOException("Illegal state. The server sent " + c.successCounter + + " SSH_MSG_CHANNEL_SUCCESS and " + c.failedCounter + " SSH_MSG_CHANNEL_FAILURE messages."); + } + } + + public void registerX11Cookie(String hexFakeCookie, X11ServerData data) { + synchronized (x11_magic_cookies) { + x11_magic_cookies.put(hexFakeCookie, data); + } + } + + public void unRegisterX11Cookie(String hexFakeCookie, boolean killChannels) { + if (hexFakeCookie == null) { + throw new IllegalStateException("hexFakeCookie may not be null"); + } + + synchronized (x11_magic_cookies) { + x11_magic_cookies.remove(hexFakeCookie); + } + + if (killChannels == false) { + return; + } + + log.debug("Closing all X11 channels for the given fake cookie"); + List<Channel> channel_copy = new ArrayList<Channel>(); + + synchronized (channels) { + channel_copy.addAll(channels); + } + + for (Channel c : channel_copy) { + synchronized (c) { + if (hexFakeCookie.equals(c.hexX11FakeCookie) == false) { + continue; + } + } + + try { + closeChannel(c, "Closing X11 channel since the corresponding session is closing", true); + } + catch (IOException ignored) { + } + } + } + + public X11ServerData checkX11Cookie(String hexFakeCookie) { + synchronized (x11_magic_cookies) { + if (hexFakeCookie != null) { + return x11_magic_cookies.get(hexFakeCookie); + } + } + + return null; + } + + public void closeAllChannels() { + log.debug("Closing all channels"); + List<Channel> channel_copy = new ArrayList<Channel>(); + + synchronized (channels) { + channel_copy.addAll(channels); + } + + for (Channel c : channel_copy) { + try { + closeChannel(c, "Closing all channels", true); + } + catch (IOException ignored) { + } + } + } + + public void closeChannel(Channel c, String reason, boolean force) throws IOException { + this.closeChannel(c, new ChannelClosedException(reason), force); + } + + public void closeChannel(Channel c, IOException reason, boolean force) throws IOException { + byte msg[] = new byte[5]; + + synchronized (c) { + if (force) { + c.state = Channel.STATE_CLOSED; + c.EOF = true; + } + + c.setReasonClosed(reason); + msg[0] = Packets.SSH_MSG_CHANNEL_CLOSE; + msg[1] = (byte)(c.remoteID >> 24); + msg[2] = (byte)(c.remoteID >> 16); + msg[3] = (byte)(c.remoteID >> 8); + msg[4] = (byte)(c.remoteID); + c.notifyAll(); + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { + return; + } + + tm.sendMessage(msg); + c.closeMessageSent = true; + } + + log.debug("Sent SSH_MSG_CHANNEL_CLOSE (channel " + c.localID + ")"); + } + + public void sendEOF(Channel c) throws IOException { + byte[] msg = new byte[5]; + + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { + return; + } + + msg[0] = Packets.SSH_MSG_CHANNEL_EOF; + msg[1] = (byte)(c.remoteID >> 24); + msg[2] = (byte)(c.remoteID >> 16); + msg[3] = (byte)(c.remoteID >> 8); + msg[4] = (byte)(c.remoteID); + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent == true) { + return; + } + + tm.sendMessage(msg); + } + + log.debug("Sent EOF (Channel " + c.localID + "/" + c.remoteID + ")"); + } + + public void sendOpenConfirmation(Channel c) throws IOException { + PacketChannelOpenConfirmation pcoc = null; + + synchronized (c) { + if (c.state != Channel.STATE_OPENING) { + return; + } + + c.state = Channel.STATE_OPEN; + pcoc = new PacketChannelOpenConfirmation(c.remoteID, c.localID, c.localWindow, c.localMaxPacketSize); + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent == true) { + return; + } + + tm.sendMessage(pcoc.getPayload()); + } + } + + public void sendData(Channel c, byte[] buffer, int pos, int len) throws IOException { + while (len > 0) { + int thislen = 0; + byte[] msg; + + synchronized (c) { + while (true) { + if (c.state == Channel.STATE_CLOSED) { + throw c.getReasonClosed(); + } + + if (c.state != Channel.STATE_OPEN) { + throw new ChannelClosedException("SSH channel in strange state. (" + c.state + ")"); + } + + if (c.remoteWindow != 0) { + break; + } + + try { + c.wait(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(e.getMessage()); + } + } + + /* len > 0, no sign extension can happen when comparing */ + thislen = (c.remoteWindow >= len) ? len : (int) c.remoteWindow; + int estimatedMaxDataLen = c.remoteMaxPacketSize - (tm.getPacketOverheadEstimate() + 9); + + /* The worst case scenario =) a true bottleneck */ + + if (estimatedMaxDataLen <= 0) { + estimatedMaxDataLen = 1; + } + + if (thislen > estimatedMaxDataLen) { + thislen = estimatedMaxDataLen; + } + + c.remoteWindow -= thislen; + msg = new byte[1 + 8 + thislen]; + msg[0] = Packets.SSH_MSG_CHANNEL_DATA; + msg[1] = (byte)(c.remoteID >> 24); + msg[2] = (byte)(c.remoteID >> 16); + msg[3] = (byte)(c.remoteID >> 8); + msg[4] = (byte)(c.remoteID); + msg[5] = (byte)(thislen >> 24); + msg[6] = (byte)(thislen >> 16); + msg[7] = (byte)(thislen >> 8); + msg[8] = (byte)(thislen); + System.arraycopy(buffer, pos, msg, 9, thislen); + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { + throw c.getReasonClosed(); + } + + tm.sendMessage(msg); + } + + pos += thislen; + len -= thislen; + } + } + + public int requestGlobalForward(String bindAddress, int bindPort, String targetAddress, int targetPort) + throws IOException { + RemoteForwardingData rfd = new RemoteForwardingData(); + rfd.bindAddress = bindAddress; + rfd.bindPort = bindPort; + rfd.targetAddress = targetAddress; + rfd.targetPort = targetPort; + + synchronized (remoteForwardings) { + if (remoteForwardings.get(bindPort) != null) { + throw new IOException("There is already a forwarding for remote port " + bindPort); + } + + remoteForwardings.put(bindPort, rfd); + } + + synchronized (channels) { + globalSuccessCounter = globalFailedCounter = 0; + } + + PacketGlobalForwardRequest pgf = new PacketGlobalForwardRequest(true, bindAddress, bindPort); + tm.sendMessage(pgf.getPayload()); + log.debug("Requesting a remote forwarding ('" + bindAddress + "', " + bindPort + ")"); + + try { + waitForGlobalSuccessOrFailure(); + } + catch (IOException e) { + synchronized (remoteForwardings) { + remoteForwardings.remove(bindPort); + } + + throw e; + } + + return bindPort; + } + + public void requestCancelGlobalForward(int bindPort) throws IOException { + RemoteForwardingData rfd; + + synchronized (remoteForwardings) { + rfd = remoteForwardings.get(bindPort); + + if (rfd == null) { + throw new IOException("Sorry, there is no known remote forwarding for remote port " + bindPort); + } + } + + synchronized (channels) { + globalSuccessCounter = globalFailedCounter = 0; + } + + PacketGlobalCancelForwardRequest pgcf = new PacketGlobalCancelForwardRequest(true, rfd.bindAddress, + rfd.bindPort); + tm.sendMessage(pgcf.getPayload()); + log.debug("Requesting cancelation of remote forward ('" + rfd.bindAddress + "', " + rfd.bindPort + ")"); + waitForGlobalSuccessOrFailure(); + + /* Only now we are sure that no more forwarded connections will arrive */ + + synchronized (remoteForwardings) { + remoteForwardings.remove(bindPort); + } + } + + /** + * @param agent + * @throws IOException + */ + public void requestChannelAgentForwarding(Channel c, AuthAgentCallback authAgent) throws IOException { + synchronized (this) { + if (this.authAgent != null) + throw new IllegalStateException("Auth agent already exists"); + + this.authAgent = authAgent; + } + + synchronized (channels) { + globalSuccessCounter = globalFailedCounter = 0; + } + + log.debug("Requesting agent forwarding"); + PacketChannelAuthAgentReq aar = new PacketChannelAuthAgentReq(c.remoteID); + + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { + throw c.getReasonClosed(); + } + + tm.sendMessage(aar.getPayload()); + } + + try { + waitForChannelSuccessOrFailure(c); + } + catch (IOException e) { + authAgent = null; + throw e; + } + } + + public void registerThread(IChannelWorkerThread thr) throws IOException { + synchronized (listenerThreads) { + if (listenerThreadsAllowed == false) { + throw new IOException("Too late, this connection is closed."); + } + + listenerThreads.add(thr); + } + } + + public Channel openDirectTCPIPChannel(String host_to_connect, int port_to_connect, String originator_IP_address, + int originator_port) throws IOException { + Channel c = new Channel(this); + + synchronized (c) { + c.localID = addChannel(c); + // end of synchronized block forces writing out to main memory + } + + PacketOpenDirectTCPIPChannel dtc = new PacketOpenDirectTCPIPChannel(c.localID, c.localWindow, + c.localMaxPacketSize, host_to_connect, port_to_connect, originator_IP_address, originator_port); + tm.sendMessage(dtc.getPayload()); + waitUntilChannelOpen(c); + return c; + } + + public Channel openSessionChannel() throws IOException { + Channel c = new Channel(this); + + synchronized (c) { + c.localID = addChannel(c); + // end of synchronized block forces the writing out to main memory + } + + log.debug("Sending SSH_MSG_CHANNEL_OPEN (Channel " + c.localID + ")"); + PacketOpenSessionChannel smo = new PacketOpenSessionChannel(c.localID, c.localWindow, c.localMaxPacketSize); + tm.sendMessage(smo.getPayload()); + waitUntilChannelOpen(c); + return c; + } + + public void requestPTY(Channel c, String term, int term_width_characters, int term_height_characters, + int term_width_pixels, int term_height_pixels, byte[] terminal_modes) throws IOException { + PacketSessionPtyRequest spr; + + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { + throw c.getReasonClosed(); + } + + spr = new PacketSessionPtyRequest(c.remoteID, true, term, term_width_characters, term_height_characters, + term_width_pixels, term_height_pixels, terminal_modes); + c.successCounter = c.failedCounter = 0; + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { + throw c.getReasonClosed(); + } + + tm.sendMessage(spr.getPayload()); + } + + try { + waitForChannelSuccessOrFailure(c); + } + catch (IOException e) { + throw new IOException("PTY request failed", e); + } + } + + public void requestWindowChange(Channel c, int term_width_characters, int term_height_characters, + int term_width_pixels, int term_height_pixels) throws IOException { + PacketWindowChange pwc; + + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { + throw c.getReasonClosed(); + } + + pwc = new PacketWindowChange(c.remoteID, term_width_characters, term_height_characters, + term_width_pixels, term_height_pixels); + c.successCounter = c.failedCounter = 0; + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { + throw c.getReasonClosed(); + } + + tm.sendMessage(pwc.getPayload()); + } + } + + public void requestX11(Channel c, boolean singleConnection, String x11AuthenticationProtocol, + String x11AuthenticationCookie, int x11ScreenNumber) throws IOException { + PacketSessionX11Request psr; + + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { + throw c.getReasonClosed(); + } + + psr = new PacketSessionX11Request(c.remoteID, true, singleConnection, x11AuthenticationProtocol, + x11AuthenticationCookie, x11ScreenNumber); + c.successCounter = c.failedCounter = 0; + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { + throw c.getReasonClosed(); + } + + tm.sendMessage(psr.getPayload()); + } + + log.debug("Requesting X11 forwarding (Channel " + c.localID + "/" + c.remoteID + ")"); + + try { + waitForChannelSuccessOrFailure(c); + } + catch (IOException e) { + throw new IOException("The X11 request failed.", e); + } + } + + public void requestSubSystem(Channel c, String subSystemName) throws IOException { + PacketSessionSubsystemRequest ssr; + + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { + throw c.getReasonClosed(); + } + + ssr = new PacketSessionSubsystemRequest(c.remoteID, true, subSystemName); + c.successCounter = c.failedCounter = 0; + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { + throw c.getReasonClosed(); + } + + tm.sendMessage(ssr.getPayload()); + } + + try { + waitForChannelSuccessOrFailure(c); + } + catch (IOException e) { + throw new IOException("The subsystem request failed.", e); + } + } + + public void requestExecCommand(Channel c, String cmd) throws IOException { + this.requestExecCommand(c, cmd, null); + } + + /** + * @param charsetName The charset used to convert between Java Unicode Strings and byte encodings + */ + public void requestExecCommand(Channel c, String cmd, String charsetName) throws IOException { + PacketSessionExecCommand sm; + + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { + throw c.getReasonClosed(); + } + + sm = new PacketSessionExecCommand(c.remoteID, true, cmd, charsetName); + c.successCounter = c.failedCounter = 0; + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { + throw c.getReasonClosed(); + } + + tm.sendMessage(sm.getPayload()); + } + + log.debug("Executing command (channel " + c.localID + ", '" + cmd + "')"); + + try { + waitForChannelSuccessOrFailure(c); + } + catch (IOException e) { + throw new IOException("The execute request failed.", e); + } + } + + public void requestShell(Channel c) throws IOException { + PacketSessionStartShell sm; + + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { + throw c.getReasonClosed(); + } + + sm = new PacketSessionStartShell(c.remoteID, true); + c.successCounter = c.failedCounter = 0; + } + + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { + throw c.getReasonClosed(); + } + + tm.sendMessage(sm.getPayload()); + } + + try { + waitForChannelSuccessOrFailure(c); + } + catch (IOException e) { + throw new IOException("The shell request failed.", e); + } + } + + public void msgChannelExtendedData(byte[] msg) throws IOException { + if (msg.length <= 13) { + throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong size (%d)", msg.length)); + } + + int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); + int dataType = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); + int len = ((msg[9] & 0xff) << 24) | ((msg[10] & 0xff) << 16) | ((msg[11] & 0xff) << 8) | (msg[12] & 0xff); + Channel c = getChannel(id); + + if (c == null) { + throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_EXTENDED_DATA message for non-existent channel " + id); + } + + if (dataType != Packets.SSH_EXTENDED_DATA_STDERR) { + throw new PacketFormatException("SSH_MSG_CHANNEL_EXTENDED_DATA message has unknown type (" + dataType + ")"); + } + + if (len != (msg.length - 13)) { + throw new PacketFormatException("SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong len (calculated " + (msg.length - 13) + + ", got " + len + ")"); + } + + log.debug("Got SSH_MSG_CHANNEL_EXTENDED_DATA (channel " + id + ", " + len + ")"); + + synchronized (c) { + if (c.state == Channel.STATE_CLOSED) { + return; // ignore + } + + if (c.state != Channel.STATE_OPEN) { + throw new PacketTypeException("Got SSH_MSG_CHANNEL_EXTENDED_DATA, but channel is not in correct state (" + + c.state + ")"); + } + + if (c.localWindow < len) { + throw new PacketFormatException("Remote sent too much data, does not fit into window."); + } + + c.localWindow -= len; + System.arraycopy(msg, 13, c.stderrBuffer, c.stderrWritepos, len); + c.stderrWritepos += len; + c.notifyAll(); + } + } + + /** + * Wait until for a condition. + * + * @param c Channel + * @param timeout in ms, 0 means no timeout. + * @param condition_mask minimum event mask (at least one of the conditions must be fulfilled) + * @return all current events + */ + public int waitForCondition(Channel c, long timeout, int condition_mask) throws IOException { + long end_time = 0; + boolean end_time_set = false; + + synchronized (c) { + while (true) { + int current_cond = 0; + int stdoutAvail = c.stdoutWritepos - c.stdoutReadpos; + int stderrAvail = c.stderrWritepos - c.stderrReadpos; + + if (stdoutAvail > 0) { + current_cond = current_cond | ChannelCondition.STDOUT_DATA; + } + + if (stderrAvail > 0) { + current_cond = current_cond | ChannelCondition.STDERR_DATA; + } + + if (c.EOF) { + current_cond = current_cond | ChannelCondition.EOF; + } + + if (c.getExitStatus() != null) { + current_cond = current_cond | ChannelCondition.EXIT_STATUS; + } + + if (c.getExitSignal() != null) { + current_cond = current_cond | ChannelCondition.EXIT_SIGNAL; + } + + if (c.state == Channel.STATE_CLOSED) { + return current_cond | ChannelCondition.CLOSED | ChannelCondition.EOF; + } + + if ((current_cond & condition_mask) != 0) { + return current_cond; + } + + if (timeout > 0) { + if (!end_time_set) { + end_time = System.currentTimeMillis() + timeout; + end_time_set = true; + } + else { + timeout = end_time - System.currentTimeMillis(); + + if (timeout <= 0) { + return current_cond | ChannelCondition.TIMEOUT; + } + } + } + + try { + if (timeout > 0) { + c.wait(timeout); + } + else { + c.wait(); + } + } + catch (InterruptedException e) { + throw new InterruptedIOException(e.getMessage()); + } + } + } + } + + public int getAvailable(Channel c, boolean extended) throws IOException { + synchronized (c) { + int avail; + + if (extended) { + avail = c.stderrWritepos - c.stderrReadpos; + } + else { + avail = c.stdoutWritepos - c.stdoutReadpos; + } + + return ((avail > 0) ? avail : (c.EOF ? -1 : 0)); + } + } + + public int getChannelData(Channel c, boolean extended, byte[] target, int off, int len) throws IOException { + int copylen = 0; + int increment = 0; + int remoteID = 0; + int localID = 0; + + synchronized (c) { + int stdoutAvail = 0; + int stderrAvail = 0; + + while (true) { + /* + * Data available? We have to return remaining data even if the + * channel is already closed. + */ + stdoutAvail = c.stdoutWritepos - c.stdoutReadpos; + stderrAvail = c.stderrWritepos - c.stderrReadpos; + + if ((!extended) && (stdoutAvail != 0)) { + break; + } + + if ((extended) && (stderrAvail != 0)) { + break; + } + + /* Do not wait if more data will never arrive (EOF or CLOSED) */ + + if ((c.EOF) || (c.state != Channel.STATE_OPEN)) { + return -1; + } + + try { + c.wait(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(e.getMessage()); + } + } + + /* OK, there is some data. Return it. */ + + if (!extended) { + copylen = (stdoutAvail > len) ? len : stdoutAvail; + System.arraycopy(c.stdoutBuffer, c.stdoutReadpos, target, off, copylen); + c.stdoutReadpos += copylen; + + if (c.stdoutReadpos != c.stdoutWritepos) { + System.arraycopy(c.stdoutBuffer, c.stdoutReadpos, c.stdoutBuffer, 0, c.stdoutWritepos + - c.stdoutReadpos); + } + + c.stdoutWritepos -= c.stdoutReadpos; + c.stdoutReadpos = 0; + } + else { + copylen = (stderrAvail > len) ? len : stderrAvail; + System.arraycopy(c.stderrBuffer, c.stderrReadpos, target, off, copylen); + c.stderrReadpos += copylen; + + if (c.stderrReadpos != c.stderrWritepos) { + System.arraycopy(c.stderrBuffer, c.stderrReadpos, c.stderrBuffer, 0, c.stderrWritepos + - c.stderrReadpos); + } + + c.stderrWritepos -= c.stderrReadpos; + c.stderrReadpos = 0; + } + + if (c.state != Channel.STATE_OPEN) { + return copylen; + } + + if (c.localWindow < ((Channel.CHANNEL_BUFFER_SIZE + 1) / 2)) { + int minFreeSpace = Math.min(Channel.CHANNEL_BUFFER_SIZE - c.stdoutWritepos, + Channel.CHANNEL_BUFFER_SIZE - c.stderrWritepos); + increment = minFreeSpace - c.localWindow; + c.localWindow = minFreeSpace; + } + + remoteID = c.remoteID; /* read while holding the lock */ + localID = c.localID; /* read while holding the lock */ + } + + /* + * If a consumer reads stdout and stdin in parallel, we may end up with + * sending two msgWindowAdjust messages. Luckily, it + * does not matter in which order they arrive at the server. + */ + + if (increment > 0) { + log.debug("Sending SSH_MSG_CHANNEL_WINDOW_ADJUST (channel " + localID + ", " + increment + ")"); + + synchronized (c.channelSendLock) { + byte[] msg = c.msgWindowAdjust; + msg[0] = Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST; + msg[1] = (byte)(remoteID >> 24); + msg[2] = (byte)(remoteID >> 16); + msg[3] = (byte)(remoteID >> 8); + msg[4] = (byte)(remoteID); + msg[5] = (byte)(increment >> 24); + msg[6] = (byte)(increment >> 16); + msg[7] = (byte)(increment >> 8); + msg[8] = (byte)(increment); + + if (!c.closeMessageSent) { + tm.sendMessage(msg); + } + } + } + + return copylen; + } + + public void msgChannelData(byte[] msg) throws IOException { + if (msg.length <= 9) { + throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_DATA message has wrong size (%d)", msg.length)); + } + + int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); + int len = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); + Channel c = getChannel(id); + + if (c == null) { + throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_DATA message for non-existent channel " + id); + } + + if (len != (msg.length - 9)) { + throw new PacketFormatException("SSH_MSG_CHANNEL_DATA message has wrong len (calculated " + (msg.length - 9) + ", got " + + len + ")"); + } + + log.debug("Got SSH_MSG_CHANNEL_DATA (channel " + id + ", " + len + ")"); + + synchronized (c) { + if (c.state == Channel.STATE_CLOSED) { + return; // ignore + } + + if (c.state != Channel.STATE_OPEN) { + throw new PacketTypeException("Got SSH_MSG_CHANNEL_DATA, but channel is not in correct state (" + c.state + ")"); + } + + if (c.localWindow < len) { + throw new IOException("Remote sent too much data, does not fit into window."); + } + + c.localWindow -= len; + System.arraycopy(msg, 9, c.stdoutBuffer, c.stdoutWritepos, len); + c.stdoutWritepos += len; + c.notifyAll(); + } + } + + public void msgChannelWindowAdjust(byte[] msg) throws IOException { + if (msg.length != 9) { + throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_WINDOW_ADJUST message has wrong size (%d)", msg.length)); + } + + int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); + int windowChange = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); + Channel c = getChannel(id); + + if (c == null) { + throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_WINDOW_ADJUST message for non-existent channel " + id); + } + + synchronized (c) { + final long huge = 0xFFFFffffL; /* 2^32 - 1 */ + c.remoteWindow += (windowChange & huge); /* avoid sign extension */ + + /* TODO - is this a good heuristic? */ + + if ((c.remoteWindow > huge)) { + c.remoteWindow = huge; + } + + c.notifyAll(); + } + + log.debug("Got SSH_MSG_CHANNEL_WINDOW_ADJUST (channel " + id + ", " + windowChange + ")"); + } + + public void msgChannelOpen(byte[] msg) throws IOException { + TypesReader tr = new TypesReader(msg); + tr.readByte(); // skip packet type + String channelType = tr.readString(); + int remoteID = tr.readUINT32(); /* sender channel */ + int remoteWindow = tr.readUINT32(); /* initial window size */ + int remoteMaxPacketSize = tr.readUINT32(); /* maximum packet size */ + + if ("x11".equals(channelType)) { + synchronized (x11_magic_cookies) { + /* If we did not request X11 forwarding, then simply ignore this bogus request. */ + if (x11_magic_cookies.size() == 0) { + PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, + Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "X11 forwarding not activated", ""); + tm.sendAsynchronousMessage(pcof.getPayload()); + log.warning("Unexpected X11 request, denying it!"); + return; + } + } + + String remoteOriginatorAddress = tr.readString(); + int remoteOriginatorPort = tr.readUINT32(); + Channel c = new Channel(this); + + synchronized (c) { + c.remoteID = remoteID; + c.remoteWindow = remoteWindow & 0xFFFFffffL; /* properly convert UINT32 to long */ + c.remoteMaxPacketSize = remoteMaxPacketSize; + c.localID = addChannel(c); + } + + /* + * The open confirmation message will be sent from another thread + */ + RemoteX11AcceptThread rxat = new RemoteX11AcceptThread(c, remoteOriginatorAddress, remoteOriginatorPort); + rxat.setDaemon(true); + rxat.start(); + return; + } + + if ("forwarded-tcpip".equals(channelType)) { + String remoteConnectedAddress = tr.readString(); /* address that was connected */ + int remoteConnectedPort = tr.readUINT32(); /* port that was connected */ + String remoteOriginatorAddress = tr.readString(); /* originator IP address */ + int remoteOriginatorPort = tr.readUINT32(); /* originator port */ + RemoteForwardingData rfd; + + synchronized (remoteForwardings) { + rfd = remoteForwardings.get(remoteConnectedPort); + } + + if (rfd == null) { + PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, + Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, + "No thanks, unknown port in forwarded-tcpip request", ""); + /* Always try to be polite. */ + tm.sendAsynchronousMessage(pcof.getPayload()); + log.debug("Unexpected forwarded-tcpip request, denying it!"); + return; + } + + Channel c = new Channel(this); + + synchronized (c) { + c.remoteID = remoteID; + c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */ + c.remoteMaxPacketSize = remoteMaxPacketSize; + c.localID = addChannel(c); + } + + /* + * The open confirmation message will be sent from another thread. + */ + RemoteAcceptThread rat = new RemoteAcceptThread(c, remoteConnectedAddress, remoteConnectedPort, + remoteOriginatorAddress, remoteOriginatorPort, rfd.targetAddress, rfd.targetPort); + rat.setDaemon(true); + rat.start(); + return; + } + + if ((server_state != null) && ("session".equals(channelType))) { + ServerConnectionCallback cb; + + synchronized (server_state) { + cb = server_state.cb_conn; + } + + if (cb == null) { + tm.sendAsynchronousMessage(new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, + "Sessions are currently not enabled", "en").getPayload()); + return; + } + + final Channel c = new Channel(this); + + synchronized (c) { + c.remoteID = remoteID; + c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */ + c.remoteMaxPacketSize = remoteMaxPacketSize; + c.localID = addChannel(c); + c.state = Channel.STATE_OPEN; + c.ss = new ServerSessionImpl(c); + } + + PacketChannelOpenConfirmation pcoc = new PacketChannelOpenConfirmation(c.remoteID, c.localID, + c.localWindow, c.localMaxPacketSize); + tm.sendAsynchronousMessage(pcoc.getPayload()); + c.ss.sscb = cb.acceptSession(c.ss); + return; + } + + /* Tell the server that we have no idea what it is talking about */ + PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_UNKNOWN_CHANNEL_TYPE, + "Unknown channel type", ""); + tm.sendAsynchronousMessage(pcof.getPayload()); + log.warning("The peer tried to open an unsupported channel type (" + channelType + ")"); + } + + /* Starts the given runnable in a foreground (non-daemon) thread */ + private void runAsync(Runnable r) { + Thread t = new Thread(r); + t.start(); + } + + public void msgChannelRequest(byte[] msg) throws IOException { + TypesReader tr = new TypesReader(msg); + tr.readByte(); // skip packet type + int id = tr.readUINT32(); + Channel c = getChannel(id); + + if (c == null) { + throw new IOException("Unexpected SSH_MSG_CHANNEL_REQUEST message for non-existent channel " + id); + } + + ServerSessionImpl server_session = null; + + if (server_state != null) { + synchronized (c) { + server_session = c.ss; + } + } + + String type = tr.readString("US-ASCII"); + boolean wantReply = tr.readBoolean(); + log.debug("Got SSH_MSG_CHANNEL_REQUEST (channel " + id + ", '" + type + "')"); + + if (type.equals("exit-status")) { + if (wantReply) { + throw new IOException( + "Badly formatted SSH_MSG_CHANNEL_REQUEST exit-status message, 'want reply' is true"); + } + + int exit_status = tr.readUINT32(); + + if (tr.remain() != 0) { + throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); + } + + synchronized (c) { + c.exit_status = exit_status; + c.notifyAll(); + } + + log.debug("Got EXIT STATUS (channel " + id + ", status " + exit_status + ")"); + return; + } + + if ((server_state == null) && (type.equals("exit-signal"))) { + if (wantReply) { + throw new IOException( + "Badly formatted SSH_MSG_CHANNEL_REQUEST exit-signal message, 'want reply' is true"); + } + + String signame = tr.readString("US-ASCII"); + tr.readBoolean(); + tr.readString(); + tr.readString(); + + if (tr.remain() != 0) { + throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); + } + + synchronized (c) { + c.exit_signal = signame; + c.notifyAll(); + } + + log.debug("Got EXIT SIGNAL (channel " + id + ", signal " + signame + ")"); + return; + } + + if ((server_session != null) && (type.equals("pty-req"))) { + PtySettings pty = new PtySettings(); + pty.term = tr.readString(); + pty.term_width_characters = tr.readUINT32(); + pty.term_height_characters = tr.readUINT32(); + pty.term_width_pixels = tr.readUINT32(); + pty.term_height_pixels = tr.readUINT32(); + pty.terminal_modes = tr.readByteString(); + + if (tr.remain() != 0) { + throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); + } + + Runnable run_after_sending_success = null; + ServerSessionCallback sscb = server_session.getServerSessionCallback(); + + if (sscb != null) { + run_after_sending_success = sscb.requestPtyReq(server_session, pty); + } + + if (wantReply) { + if (run_after_sending_success != null) { + tm.sendAsynchronousMessage(new PacketChannelSuccess(c.remoteID).getPayload()); + } + else { + tm.sendAsynchronousMessage(new PacketChannelFailure(c.remoteID).getPayload()); + } + } + + if (run_after_sending_success != null) { + runAsync(run_after_sending_success); + } + + return; + } + + if ((server_session != null) && (type.equals("shell"))) { + if (tr.remain() != 0) { + throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); + } + + Runnable run_after_sending_success = null; + ServerSessionCallback sscb = server_session.getServerSessionCallback(); + + if (sscb != null) { + run_after_sending_success = sscb.requestShell(server_session); + } + + if (wantReply) { + if (run_after_sending_success != null) { + tm.sendAsynchronousMessage(new PacketChannelSuccess(c.remoteID).getPayload()); + } + else { + tm.sendAsynchronousMessage(new PacketChannelFailure(c.remoteID).getPayload()); + } + } + + if (run_after_sending_success != null) { + runAsync(run_after_sending_success); + } + + return; + } + + if ((server_session != null) && (type.equals("exec"))) { + String command = tr.readString(); + + if (tr.remain() != 0) { + throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); + } + + Runnable run_after_sending_success = null; + ServerSessionCallback sscb = server_session.getServerSessionCallback(); + + if (sscb != null) { + run_after_sending_success = sscb.requestExec(server_session, command); + } + + if (wantReply) { + if (run_after_sending_success != null) { + tm.sendAsynchronousMessage(new PacketChannelSuccess(c.remoteID).getPayload()); + } + else { + tm.sendAsynchronousMessage(new PacketChannelFailure(c.remoteID).getPayload()); + } + } + + if (run_after_sending_success != null) { + runAsync(run_after_sending_success); + } + + return; + } + + /* We simply ignore unknown channel requests, however, if the server wants a reply, + * then we signal that we have no idea what it is about. + */ + + if (wantReply) { + tm.sendAsynchronousMessage(new PacketChannelFailure(c.remoteID).getPayload()); + } + + log.debug("Channel request '" + type + "' is not known, ignoring it"); + } + + public void msgChannelEOF(byte[] msg) throws IOException { + if (msg.length != 5) { + throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_EOF message has wrong size (%d)", msg.length)); + } + + int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); + Channel c = getChannel(id); + + if (c == null) { + throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_EOF message for non-existent channel " + id); + } + + synchronized (c) { + c.EOF = true; + c.notifyAll(); + } + + log.debug("Got SSH_MSG_CHANNEL_EOF (channel " + id + ")"); + } + + public void msgChannelClose(byte[] msg) throws IOException { + if (msg.length != 5) { + throw new PacketFormatException("SSH_MSG_CHANNEL_CLOSE message has wrong size (" + msg.length + ")"); + } + + int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); + Channel c = getChannel(id); + + if (c == null) { + throw new IOException("Unexpected SSH_MSG_CHANNEL_CLOSE message for non-existent channel " + id); + } + + synchronized (c) { + c.EOF = true; + c.state = Channel.STATE_CLOSED; + c.setReasonClosed(new ChannelClosedException("Close requested by remote")); + c.closeMessageRecv = true; + removeChannel(c.localID); + c.notifyAll(); + } + + log.debug("Got SSH_MSG_CHANNEL_CLOSE (channel " + id + ")"); + } + + public void msgChannelSuccess(byte[] msg) throws IOException { + if (msg.length != 5) { + throw new PacketFormatException("SSH_MSG_CHANNEL_SUCCESS message has wrong size (" + msg.length + ")"); + } + + int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); + Channel c = getChannel(id); + + if (c == null) { + throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_SUCCESS message for non-existent channel " + id); + } + + synchronized (c) { + c.successCounter++; + c.notifyAll(); + } + + log.debug("Got SSH_MSG_CHANNEL_SUCCESS (channel " + id + ")"); + } + + public void msgChannelFailure(byte[] msg) throws IOException { + if (msg.length != 5) { + throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_FAILURE message has wrong size (%d)", msg.length)); + } + + int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); + Channel c = getChannel(id); + + if (c == null) { + throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_FAILURE message for non-existent channel " + id); + } + + synchronized (c) { + c.failedCounter++; + c.notifyAll(); + } + + log.debug("Got SSH_MSG_CHANNEL_FAILURE (channel " + id + ")"); + } + + public void msgChannelOpenConfirmation(byte[] msg) throws IOException { + PacketChannelOpenConfirmation sm = new PacketChannelOpenConfirmation(msg); + Channel c = getChannel(sm.getRecipientChannelID()); + + if (c == null) { + throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for non-existent channel " + + sm.getRecipientChannelID()); + } + + synchronized (c) { + if (c.state != Channel.STATE_OPENING) { + throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for channel " + + sm.getRecipientChannelID()); + } + + c.remoteID = sm.getSenderChannelID(); + c.remoteWindow = sm.getInitialWindowSize() & 0xFFFFffffL; /* convert UINT32 to long */ + c.remoteMaxPacketSize = sm.getMaxPacketSize(); + c.state = Channel.STATE_OPEN; + c.notifyAll(); + } + + log.debug("Got SSH_MSG_CHANNEL_OPEN_CONFIRMATION (channel " + sm.getRecipientChannelID() + " / remote: " + + sm.getSenderChannelID() + ")"); + } + + public void msgChannelOpenFailure(byte[] msg) throws IOException { + if (msg.length < 5) { + throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_OPEN_FAILURE message has wrong size (%d)", msg.length)); + } + + TypesReader tr = new TypesReader(msg); + tr.readByte(); // skip packet type + int id = tr.readUINT32(); /* sender channel */ + Channel c = getChannel(id); + + if (c == null) { + throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE message for non-existent channel " + id); + } + + int reasonCode = tr.readUINT32(); + String description = tr.readString("UTF-8"); + String reasonCodeSymbolicName; + + switch (reasonCode) { + case 1: + reasonCodeSymbolicName = "SSH_OPEN_ADMINISTRATIVELY_PROHIBITED"; + break; + + case 2: + reasonCodeSymbolicName = "SSH_OPEN_CONNECT_FAILED"; + break; + + case 3: + reasonCodeSymbolicName = "SSH_OPEN_UNKNOWN_CHANNEL_TYPE"; + break; + + case 4: + reasonCodeSymbolicName = "SSH_OPEN_RESOURCE_SHORTAGE"; + break; + + default: + reasonCodeSymbolicName = "UNKNOWN REASON CODE (" + reasonCode + ")"; + } + + StringBuilder descriptionBuffer = new StringBuilder(); + descriptionBuffer.append(description); + + for (int i = 0; i < descriptionBuffer.length(); i++) { + char cc = descriptionBuffer.charAt(i); + + if ((cc >= 32) && (cc <= 126)) { + continue; + } + + descriptionBuffer.setCharAt(i, '\uFFFD'); + } + + synchronized (c) { + c.EOF = true; + c.state = Channel.STATE_CLOSED; + c.setReasonClosed(new ChannelClosedException(String.format("The server refused to open the channel (%s, '%s')", + reasonCodeSymbolicName, descriptionBuffer.toString()))); + c.notifyAll(); + } + + log.debug("Got SSH_MSG_CHANNEL_OPEN_FAILURE (channel " + id + ")"); + } + + public void msgGlobalRequest(byte[] msg) throws IOException { + /* Currently we do not support any kind of global request */ + TypesReader tr = new TypesReader(msg); + tr.readByte(); // skip packet type + String requestName = tr.readString(); + boolean wantReply = tr.readBoolean(); + + if (wantReply) { + byte[] reply_failure = new byte[1]; + reply_failure[0] = Packets.SSH_MSG_REQUEST_FAILURE; + tm.sendAsynchronousMessage(reply_failure); + } + + /* We do not clean up the requestName String - that is OK for debug */ + log.debug("Got SSH_MSG_GLOBAL_REQUEST (" + requestName + ")"); + } + + public void msgGlobalSuccess() throws IOException { + synchronized (channels) { + globalSuccessCounter++; + channels.notifyAll(); + } + + log.debug("Got SSH_MSG_REQUEST_SUCCESS"); + } + + public void msgGlobalFailure() throws IOException { + synchronized (channels) { + globalFailedCounter++; + channels.notifyAll(); + } + + log.debug("Got SSH_MSG_REQUEST_FAILURE"); + } + + public void handleFailure(final IOException failure) { + log.debug("HandleMessage: got shutdown"); + + synchronized (listenerThreads) { + for (IChannelWorkerThread lat : listenerThreads) { + lat.stopWorking(); + } + + listenerThreadsAllowed = false; + } + + synchronized (channels) { + shutdown = true; + + for (Channel c : channels) { + synchronized (c) { + c.EOF = true; + c.state = Channel.STATE_CLOSED; + c.setReasonClosed(failure); + c.closeMessageRecv = true; + c.notifyAll(); + } + } + + channels.clear(); + channels.notifyAll(); /* Notify global response waiters */ + } + } + + public void handleMessage(byte[] msg) throws IOException { + switch (msg[0]) { + case Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: + msgChannelOpenConfirmation(msg); + break; + + case Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST: + msgChannelWindowAdjust(msg); + break; + + case Packets.SSH_MSG_CHANNEL_DATA: + msgChannelData(msg); + break; + + case Packets.SSH_MSG_CHANNEL_EXTENDED_DATA: + msgChannelExtendedData(msg); + break; + + case Packets.SSH_MSG_CHANNEL_REQUEST: + msgChannelRequest(msg); + break; + + case Packets.SSH_MSG_CHANNEL_EOF: + msgChannelEOF(msg); + break; + + case Packets.SSH_MSG_CHANNEL_OPEN: + msgChannelOpen(msg); + break; + + case Packets.SSH_MSG_CHANNEL_CLOSE: + msgChannelClose(msg); + break; + + case Packets.SSH_MSG_CHANNEL_SUCCESS: + msgChannelSuccess(msg); + break; + + case Packets.SSH_MSG_CHANNEL_FAILURE: + msgChannelFailure(msg); + break; + + case Packets.SSH_MSG_CHANNEL_OPEN_FAILURE: + msgChannelOpenFailure(msg); + break; + + case Packets.SSH_MSG_GLOBAL_REQUEST: + msgGlobalRequest(msg); + break; + + case Packets.SSH_MSG_REQUEST_SUCCESS: + msgGlobalSuccess(); + break; + + case Packets.SSH_MSG_REQUEST_FAILURE: + msgGlobalFailure(); + break; + + default: + throw new PacketTypeException(msg[0]); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/ChannelOutputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * ChannelOutputStream. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class ChannelOutputStream extends OutputStream { + Channel c; + + boolean isClosed = false; + + ChannelOutputStream(Channel c) { + this.c = c; + } + + @Override + public void write(int b) throws IOException { + byte[] buff = new byte[1]; + buff[0] = (byte) b; + write(buff, 0, 1); + } + + @Override + public void close() throws IOException { + if (isClosed == false) { + isClosed = true; + c.cm.sendEOF(c); + } + } + + @Override + public void flush() throws IOException { + if (isClosed) + throw new IOException("This OutputStream is closed."); + + /* This is a no-op, since this stream is unbuffered */ + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + if (isClosed) + throw new IOException("This OutputStream is closed."); + + if (b == null) + throw new NullPointerException(); + + if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) + throw new IndexOutOfBoundsException(); + + if (len == 0) + return; + + c.cm.sendData(c, b, off, len); + } + + @Override + public void write(byte[] b) throws IOException { + write(b, 0, b.length); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/DynamicAcceptThread.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,295 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; +import java.io.OutputStream; +import java.io.PushbackInputStream; +import java.net.ConnectException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NoRouteToHostException; +import java.net.ServerSocket; +import java.net.Socket; + +import net.sourceforge.jsocks.CProxy; +import net.sourceforge.jsocks.ProxyMessage; +import net.sourceforge.jsocks.Socks4Message; +import net.sourceforge.jsocks.Socks5Message; +import net.sourceforge.jsocks.SocksException; +import net.sourceforge.jsocks.server.ServerAuthenticator; +import net.sourceforge.jsocks.server.ServerAuthenticatorNone; + +/** + * DynamicAcceptThread. + * + * @author Kenny Root + * @version $Id$ + */ +public class DynamicAcceptThread extends Thread implements IChannelWorkerThread { + private ChannelManager cm; + private ServerSocket ss; + + class DynamicAcceptRunnable implements Runnable { + private static final int idleTimeout = 180000; //3 minutes + + private ServerAuthenticator auth; + private Socket sock; + private InputStream in; + private OutputStream out; + private ProxyMessage msg; + + public DynamicAcceptRunnable(ServerAuthenticator auth, Socket sock) { + this.auth = auth; + this.sock = sock; + setName("DynamicAcceptRunnable"); + } + + public void run() { + try { + startSession(); + } + catch (IOException ioe) { + int error_code = CProxy.SOCKS_FAILURE; + + if (ioe instanceof SocksException) + error_code = ((SocksException) ioe).errCode; + else if (ioe instanceof NoRouteToHostException) + error_code = CProxy.SOCKS_HOST_UNREACHABLE; + else if (ioe instanceof ConnectException) + error_code = CProxy.SOCKS_CONNECTION_REFUSED; + else if (ioe instanceof InterruptedIOException) + error_code = CProxy.SOCKS_TTL_EXPIRE; + + if (error_code > CProxy.SOCKS_ADDR_NOT_SUPPORTED + || error_code < 0) { + error_code = CProxy.SOCKS_FAILURE; + } + + sendErrorMessage(error_code); + } + finally { + if (auth != null) + auth.endSession(); + } + } + + private ProxyMessage readMsg(InputStream in) throws IOException { + PushbackInputStream push_in; + + if (in instanceof PushbackInputStream) + push_in = (PushbackInputStream) in; + else + push_in = new PushbackInputStream(in); + + int version = push_in.read(); + push_in.unread(version); + ProxyMessage msg; + + if (version == 5) { + msg = new Socks5Message(push_in, false); + } + else if (version == 4) { + msg = new Socks4Message(push_in, false); + } + else { + throw new SocksException(CProxy.SOCKS_FAILURE); + } + + return msg; + } + + private void sendErrorMessage(int error_code) { + ProxyMessage err_msg; + + if (msg instanceof Socks4Message) + err_msg = new Socks4Message(Socks4Message.REPLY_REJECTED); + else + err_msg = new Socks5Message(error_code); + + try { + err_msg.write(out); + } + catch (IOException ioe) { + } + } + + private void handleRequest(ProxyMessage msg) throws IOException { + if (!auth.checkRequest(msg)) + throw new SocksException(CProxy.SOCKS_FAILURE); + + switch (msg.command) { + case CProxy.SOCKS_CMD_CONNECT: + onConnect(msg); + break; + + default: + throw new SocksException(CProxy.SOCKS_CMD_NOT_SUPPORTED); + } + } + + private void startSession() throws IOException { + sock.setSoTimeout(idleTimeout); + + try { + auth = auth.startSession(sock); + } + catch (IOException ioe) { + System.out.println("Could not start SOCKS session"); + ioe.printStackTrace(); + auth = null; + return; + } + + if (auth == null) { // Authentication failed + System.out.println("SOCKS auth failed"); + return; + } + + in = auth.getInputStream(); + out = auth.getOutputStream(); + msg = readMsg(in); + handleRequest(msg); + } + + private void onConnect(ProxyMessage msg) throws IOException { + ProxyMessage response = null; + Channel cn = null; + StreamForwarder r2l = null; + StreamForwarder l2r = null; + + if (msg instanceof Socks5Message) { + response = new Socks5Message(CProxy.SOCKS_SUCCESS, (InetAddress)null, 0); + } + else { + response = new Socks4Message(Socks4Message.REPLY_OK, (InetAddress)null, 0); + } + + response.write(out); + String destHost = msg.host; + + if (msg.ip != null) + destHost = msg.ip.getHostAddress(); + + try { + /* + * This may fail, e.g., if the remote port is closed (in + * optimistic terms: not open yet) + */ + cn = cm.openDirectTCPIPChannel(destHost, msg.port, + "127.0.0.1", 0); + } + catch (IOException e) { + /* + * Simply close the local socket and wait for the next incoming + * connection + */ + try { + sock.close(); + } + catch (IOException ignore) { + } + + return; + } + + try { + r2l = new StreamForwarder(cn, null, sock, cn.stdoutStream, out, "RemoteToLocal"); + l2r = new StreamForwarder(cn, r2l, sock, in, cn.stdinStream, "LocalToRemote"); + } + catch (IOException e) { + try { + /* + * This message is only visible during debugging, since we + * discard the channel immediatelly + */ + cn.cm.closeChannel(cn, + "Weird error during creation of StreamForwarder (" + + e.getMessage() + ")", true); + } + catch (IOException ignore) { + } + + return; + } + + r2l.setDaemon(true); + l2r.setDaemon(true); + r2l.start(); + l2r.start(); + } + } + + public DynamicAcceptThread(ChannelManager cm, int local_port) + throws IOException { + this.cm = cm; + setName("DynamicAcceptThread"); + ss = new ServerSocket(local_port); + } + + public DynamicAcceptThread(ChannelManager cm, InetSocketAddress localAddress) + throws IOException { + this.cm = cm; + ss = new ServerSocket(); + ss.bind(localAddress); + } + + @Override + public void run() { + try { + cm.registerThread(this); + } + catch (IOException e) { + stopWorking(); + return; + } + + while (true) { + Socket sock = null; + + try { + sock = ss.accept(); + } + catch (IOException e) { + stopWorking(); + return; + } + + DynamicAcceptRunnable dar = new DynamicAcceptRunnable(new ServerAuthenticatorNone(), sock); + Thread t = new Thread(dar); + t.setDaemon(true); + t.start(); + } + } + + /* + * (non-Javadoc) + * + * @see ch.ethz.ssh2.channel.IChannelWorkerThread#stopWorking() + */ + public void stopWorking() { + try { + /* This will lead to an IOException in the ss.accept() call */ + ss.close(); + } + catch (IOException e) { + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/IChannelWorkerThread.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +/** + * IChannelWorkerThread. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +interface IChannelWorkerThread { + public void stopWorking(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/LocalAcceptThread.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * LocalAcceptThread. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class LocalAcceptThread extends Thread implements IChannelWorkerThread { + ChannelManager cm; + String host_to_connect; + int port_to_connect; + + final ServerSocket ss; + + public LocalAcceptThread(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) + throws IOException { + this.cm = cm; + this.host_to_connect = host_to_connect; + this.port_to_connect = port_to_connect; + ss = new ServerSocket(local_port); + } + + public LocalAcceptThread(ChannelManager cm, InetSocketAddress localAddress, String host_to_connect, + int port_to_connect) throws IOException { + this.cm = cm; + this.host_to_connect = host_to_connect; + this.port_to_connect = port_to_connect; + ss = new ServerSocket(); + ss.bind(localAddress); + } + + public ServerSocket getServerSocket() { + return ss; + } + + @Override + public void run() { + try { + cm.registerThread(this); + } + catch (IOException e) { + stopWorking(); + return; + } + + while (true) { + Socket s = null; + + try { + s = ss.accept(); + } + catch (IOException e) { + stopWorking(); + return; + } + + Channel cn = null; + StreamForwarder r2l = null; + StreamForwarder l2r = null; + + try { + /* This may fail, e.g., if the remote port is closed (in optimistic terms: not open yet) */ + cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, s.getInetAddress().getHostAddress(), s + .getPort()); + } + catch (IOException e) { + /* Simply close the local socket and wait for the next incoming connection */ + try { + s.close(); + } + catch (IOException ignore) { + } + + continue; + } + + try { + r2l = new StreamForwarder(cn, null, null, cn.stdoutStream, s.getOutputStream(), "RemoteToLocal"); + l2r = new StreamForwarder(cn, r2l, s, s.getInputStream(), cn.stdinStream, "LocalToRemote"); + } + catch (IOException e) { + try { + /* This message is only visible during debugging, since we discard the channel immediatelly */ + cn.cm.closeChannel(cn, e, true); + } + catch (IOException ignore) { + } + + continue; + } + + r2l.setDaemon(true); + l2r.setDaemon(true); + r2l.start(); + l2r.start(); + } + } + + public void stopWorking() { + try { + /* This will lead to an IOException in the ss.accept() call */ + ss.close(); + } + catch (IOException ignored) { + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/RemoteAcceptThread.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.net.Socket; + +import ch.ethz.ssh2.log.Logger; + +/** + * RemoteAcceptThread. + * + * @author Christian Plattner + * @version $Id: RemoteAcceptThread.java 119 2014-04-12 20:30:58Z dkocher@sudo.ch $ + */ +public class RemoteAcceptThread extends Thread { + private static final Logger log = Logger.getLogger(RemoteAcceptThread.class); + + Channel c; + + String remoteConnectedAddress; + int remoteConnectedPort; + String remoteOriginatorAddress; + int remoteOriginatorPort; + String targetAddress; + int targetPort; + + Socket s; + + public RemoteAcceptThread(Channel c, String remoteConnectedAddress, int remoteConnectedPort, + String remoteOriginatorAddress, int remoteOriginatorPort, String targetAddress, int targetPort) { + this.c = c; + this.remoteConnectedAddress = remoteConnectedAddress; + this.remoteConnectedPort = remoteConnectedPort; + this.remoteOriginatorAddress = remoteOriginatorAddress; + this.remoteOriginatorPort = remoteOriginatorPort; + this.targetAddress = targetAddress; + this.targetPort = targetPort; + log.debug("RemoteAcceptThread: " + remoteConnectedAddress + "/" + remoteConnectedPort + ", R: " + + remoteOriginatorAddress + "/" + remoteOriginatorPort); + } + + @Override + public void run() { + try { + c.cm.sendOpenConfirmation(c); + s = new Socket(targetAddress, targetPort); + StreamForwarder r2l = new StreamForwarder(c, null, null, c.getStdoutStream(), s.getOutputStream(), + "RemoteToLocal"); + StreamForwarder l2r = new StreamForwarder(c, null, null, s.getInputStream(), c.getStdinStream(), + "LocalToRemote"); + /* No need to start two threads, one can be executed in the current thread */ + r2l.setDaemon(true); + r2l.start(); + l2r.run(); + + while (r2l.isAlive()) { + try { + r2l.join(); + } + catch (InterruptedException ignored) { + } + } + + /* If the channel is already closed, then this is a no-op */ + c.cm.closeChannel(c, "EOF on both streams reached.", true); + s.close(); + } + catch (IOException e) { + log.warning("IOException in proxy code: " + e.getMessage()); + + try { + c.cm.closeChannel(c, e, true); + } + catch (IOException ignored) { + } + + try { + if (s != null) + s.close(); + } + catch (IOException ignored) { + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/RemoteForwardingData.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +/** + * RemoteForwardingData. Data about a requested remote forwarding. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class RemoteForwardingData { + public String bindAddress; + public int bindPort; + + String targetAddress; + int targetPort; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/RemoteX11AcceptThread.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.util.StringEncoder; + +/** + * RemoteX11AcceptThread. + * + * @author Christian Plattner + * @version $Id: RemoteX11AcceptThread.java 119 2014-04-12 20:30:58Z dkocher@sudo.ch $ + */ +public class RemoteX11AcceptThread extends Thread { + private static final Logger log = Logger.getLogger(RemoteX11AcceptThread.class); + + Channel c; + + String remoteOriginatorAddress; + int remoteOriginatorPort; + + Socket s; + + public RemoteX11AcceptThread(Channel c, String remoteOriginatorAddress, int remoteOriginatorPort) { + this.c = c; + this.remoteOriginatorAddress = remoteOriginatorAddress; + this.remoteOriginatorPort = remoteOriginatorPort; + } + + @Override + public void run() { + try { + /* Send Open Confirmation */ + c.cm.sendOpenConfirmation(c); + /* Read startup packet from client */ + OutputStream remote_os = c.getStdinStream(); + InputStream remote_is = c.getStdoutStream(); + /* The following code is based on the protocol description given in: + * Scheifler/Gettys, + * X Windows System: Core and Extension Protocols: + * X Version 11, Releases 6 and 6.1 ISBN 1-55558-148-X + * (from the ETH library - after being here for almost ten + * years one of the few books I borrowed... sad but true =) + */ + /* + * Client startup: + * + * 1 0X42 MSB first/0x6c lSB first - byteorder + * 1 - unused + * 2 card16 - protocol-major-version + * 2 card16 - protocol-minor-version + * 2 n - lenght of authorization-protocol-name + * 2 d - lenght of authorization-protocol-data + * 2 - unused + * string8 - authorization-protocol-name + * p - unused, p=pad(n) + * string8 - authorization-protocol-data + * q - unused, q=pad(d) + * + * pad(X) = (4 - (X mod 4)) mod 4 + * + * Server response: + * + * 1 (0 failed, 2 authenticate, 1 success) + * ... + * + */ + /* Later on we will simply forward the first 6 header bytes to the "real" X11 server */ + byte[] header = new byte[6]; + + if (remote_is.read(header) != 6) + throw new IOException("Unexpected EOF on X11 startup!"); + + if ((header[0] != 0x42) && (header[0] != 0x6c)) // 0x42 MSB first, 0x6C LSB first + throw new IOException("Unknown endian format in X11 message!"); + + /* Yes, I came up with this myself - shall I file an application for a patent? =) */ + int idxMSB = (header[0] == 0x42) ? 0 : 1; + /* Read authorization data header */ + byte[] auth_buff = new byte[6]; + + if (remote_is.read(auth_buff) != 6) + throw new IOException("Unexpected EOF on X11 startup!"); + + int authProtocolNameLength = ((auth_buff[idxMSB] & 0xff) << 8) | (auth_buff[1 - idxMSB] & 0xff); + int authProtocolDataLength = ((auth_buff[2 + idxMSB] & 0xff) << 8) | (auth_buff[3 - idxMSB] & 0xff); + + if ((authProtocolNameLength > 256) || (authProtocolDataLength > 256)) + throw new IOException("Buggy X11 authorization data"); + + int authProtocolNamePadding = ((4 - (authProtocolNameLength % 4)) % 4); + int authProtocolDataPadding = ((4 - (authProtocolDataLength % 4)) % 4); + byte[] authProtocolName = new byte[authProtocolNameLength]; + byte[] authProtocolData = new byte[authProtocolDataLength]; + byte[] paddingBuffer = new byte[4]; + + if (remote_is.read(authProtocolName) != authProtocolNameLength) + throw new IOException("Unexpected EOF on X11 startup! (authProtocolName)"); + + if (remote_is.read(paddingBuffer, 0, authProtocolNamePadding) != authProtocolNamePadding) + throw new IOException("Unexpected EOF on X11 startup! (authProtocolNamePadding)"); + + if (remote_is.read(authProtocolData) != authProtocolDataLength) + throw new IOException("Unexpected EOF on X11 startup! (authProtocolData)"); + + if (remote_is.read(paddingBuffer, 0, authProtocolDataPadding) != authProtocolDataPadding) + throw new IOException("Unexpected EOF on X11 startup! (authProtocolDataPadding)"); + + if ("MIT-MAGIC-COOKIE-1".equals(StringEncoder.GetString(authProtocolName)) == false) + throw new IOException("Unknown X11 authorization protocol!"); + + if (authProtocolDataLength != 16) + throw new IOException("Wrong data length for X11 authorization data!"); + + StringBuilder tmp = new StringBuilder(32); + + for (int i = 0; i < authProtocolData.length; i++) { + String digit2 = Integer.toHexString(authProtocolData[i] & 0xff); + tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2); + } + + String hexEncodedFakeCookie = tmp.toString(); + + /* Order is very important here - it may be that a certain x11 forwarding + * gets disabled right in the moment when we check and register our connection + * */ + + synchronized (c) { + /* Please read the comment in Channel.java */ + c.hexX11FakeCookie = hexEncodedFakeCookie; + } + + /* Now check our fake cookie directory to see if we produced this cookie */ + X11ServerData sd = c.cm.checkX11Cookie(hexEncodedFakeCookie); + + if (sd == null) + throw new IOException("Invalid X11 cookie received."); + + /* If the session which corresponds to this cookie is closed then we will + * detect this: the session's close code will close all channels + * with the session's assigned x11 fake cookie. + */ + s = new Socket(sd.hostname, sd.port); + OutputStream x11_os = s.getOutputStream(); + InputStream x11_is = s.getInputStream(); + /* Now we are sending the startup packet to the real X11 server */ + x11_os.write(header); + + if (sd.x11_magic_cookie == null) { + byte[] emptyAuthData = new byte[6]; + /* empty auth data, hopefully you are connecting to localhost =) */ + x11_os.write(emptyAuthData); + } + else { + if (sd.x11_magic_cookie.length != 16) + throw new IOException("The real X11 cookie has an invalid length!"); + + /* send X11 cookie specified by client */ + x11_os.write(auth_buff); + x11_os.write(authProtocolName); /* re-use */ + x11_os.write(paddingBuffer, 0, authProtocolNamePadding); + x11_os.write(sd.x11_magic_cookie); + x11_os.write(paddingBuffer, 0, authProtocolDataPadding); + } + + x11_os.flush(); + /* Start forwarding traffic */ + StreamForwarder r2l = new StreamForwarder(c, null, null, remote_is, x11_os, "RemoteToX11"); + StreamForwarder l2r = new StreamForwarder(c, null, null, x11_is, remote_os, "X11ToRemote"); + /* No need to start two threads, one can be executed in the current thread */ + r2l.setDaemon(true); + r2l.start(); + l2r.run(); + + while (r2l.isAlive()) { + try { + r2l.join(); + } + catch (InterruptedException ignored) { + } + } + + /* If the channel is already closed, then this is a no-op */ + c.cm.closeChannel(c, "EOF on both X11 streams reached.", true); + s.close(); + } + catch (IOException e) { + log.warning("IOException in X11 proxy code: " + e.getMessage()); + + try { + c.cm.closeChannel(c, e, true); + } + catch (IOException ignored) { + } + + try { + if (s != null) + s.close(); + } + catch (IOException ignored) { + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/ServerSessionImpl.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,50 @@ + +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import ch.ethz.ssh2.ServerSession; +import ch.ethz.ssh2.ServerSessionCallback; + +public class ServerSessionImpl implements ServerSession { + Channel c; + public ServerSessionCallback sscb; + + public ServerSessionImpl(Channel c) { + this.c = c; + } + + public int getState() { + return c.getState(); + } + + public InputStream getStdout() { + return c.getStdoutStream(); + } + + public InputStream getStderr() { + return c.getStderrStream(); + } + + public OutputStream getStdin() { + return c.getStdinStream(); + } + + public void close() { + try { + c.cm.closeChannel(c, "Closed due to server request", true); + } + catch (IOException ignored) { + } + } + + public synchronized ServerSessionCallback getServerSessionCallback() { + return sscb; + } + + public synchronized void setServerSessionCallback(ServerSessionCallback sscb) { + this.sscb = sscb; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/StreamForwarder.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +/** + * A StreamForwarder forwards data between two given streams. + * If two StreamForwarder threads are used (one for each direction) + * then one can be configured to shutdown the underlying channel/socket + * if both threads have finished forwarding (EOF). + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class StreamForwarder extends Thread { + OutputStream os; + InputStream is; + byte[] buffer = new byte[Channel.CHANNEL_BUFFER_SIZE]; + Channel c; + StreamForwarder sibling; + Socket s; + String mode; + + StreamForwarder(Channel c, StreamForwarder sibling, Socket s, InputStream is, OutputStream os, String mode) + throws IOException { + this.is = is; + this.os = os; + this.mode = mode; + this.c = c; + this.sibling = sibling; + this.s = s; + } + + @Override + public void run() { + try { + while (true) { + int len = is.read(buffer); + + if (len <= 0) + break; + + os.write(buffer, 0, len); + os.flush(); + } + } + catch (IOException e) { + try { + c.cm.closeChannel(c, e, true); + } + catch (IOException ignored) { + } + } + finally { + try { + os.close(); + } + catch (IOException ignored) { + } + + try { + is.close(); + } + catch (IOException ignored) { + } + + if (sibling != null) { + while (sibling.isAlive()) { + try { + sibling.join(); + } + catch (InterruptedException ignored) { + } + } + + try { + c.cm.closeChannel(c, "StreamForwarder (" + mode + ") is cleaning up the connection", true); + } + catch (IOException ignored) { + } + + try { + if (s != null) + s.close(); + } + catch (IOException ignored) { + } + } + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/channel/X11ServerData.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.channel; + +/** + * X11ServerData. Data regarding an x11 forwarding target. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + * + */ +public class X11ServerData { + public String hostname; + public int port; + public byte[] x11_magic_cookie; /* not the remote (fake) one, the local (real) one */ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/compression/CompressionFactory.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,88 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.ethz.ssh2.compression; + +import java.util.Vector; + +/** + * @author Kenny Root + * + */ +public class CompressionFactory { + static class CompressorEntry { + String type; + String compressorClass; + + public CompressorEntry(String type, String compressorClass) { + this.type = type; + this.compressorClass = compressorClass; + } + } + + static Vector<CompressorEntry> compressors = new Vector<CompressorEntry>(); + + static { + /* Higher Priority First */ + compressors.addElement(new CompressorEntry("zlib", "ch.ethz.ssh2.compression.Zlib")); + compressors.addElement(new CompressorEntry("zlib@openssh.com", "ch.ethz.ssh2.compression.ZlibOpenSSH")); + compressors.addElement(new CompressorEntry("none", "")); + } + + public static String[] getDefaultCompressorList() { + String list[] = new String[compressors.size()]; + + for (int i = 0; i < compressors.size(); i++) { + CompressorEntry ce = compressors.elementAt(i); + list[i] = new String(ce.type); + } + + return list; + } + + public static void checkCompressorList(String[] compressorCandidates) { + for (int i = 0; i < compressorCandidates.length; i++) + getEntry(compressorCandidates[i]); + } + + public static Compressor createCompressor(String type) { + try { + CompressorEntry ce = getEntry(type); + + if ("".equals(ce.compressorClass)) + return null; + + Class<?> cc = Class.forName(ce.compressorClass); + Compressor cmp = (Compressor) cc.newInstance(); + return cmp; + } + catch (Exception e) { + throw new IllegalArgumentException("Cannot instantiate " + type); + } + } + + private static CompressorEntry getEntry(String type) { + for (int i = 0; i < compressors.size(); i++) { + CompressorEntry ce = compressors.elementAt(i); + + if (ce.type.equals(type)) + return ce; + } + + throw new IllegalArgumentException("Unkown algorithm " + type); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/compression/Compressor.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,32 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.ethz.ssh2.compression; + +/** + * @author Kenny Root + * + */ +public interface Compressor { + int getBufferSize(); + + int compress(byte[] buf, int start, int len, byte[] output); + + byte[] uncompress(byte[] buf, int start, int[] len); + + boolean canCompressPreauth(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/compression/Zlib.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,131 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.ethz.ssh2.compression; + +import com.jcraft.jzlib.JZlib; +import com.jcraft.jzlib.ZStream; + +/** + * @author Kenny Root + * + */ +public class Zlib implements Compressor { + static private final int DEFAULT_BUF_SIZE = 4096; + static private final int LEVEL = 5; + + private ZStream deflate; + private byte[] deflate_tmpbuf; + + private ZStream inflate; + private byte[] inflate_tmpbuf; + private byte[] inflated_buf; + + public Zlib() { + deflate = new ZStream(); + inflate = new ZStream(); + deflate.deflateInit(LEVEL); + inflate.inflateInit(); + deflate_tmpbuf = new byte[DEFAULT_BUF_SIZE]; + inflate_tmpbuf = new byte[DEFAULT_BUF_SIZE]; + inflated_buf = new byte[DEFAULT_BUF_SIZE]; + } + + public boolean canCompressPreauth() { + return true; + } + + public int getBufferSize() { + return DEFAULT_BUF_SIZE; + } + + public int compress(byte[] buf, int start, int len, byte[] output) { + deflate.next_in = buf; + deflate.next_in_index = start; + deflate.avail_in = len - start; + + if ((buf.length + 1024) > deflate_tmpbuf.length) { + deflate_tmpbuf = new byte[buf.length + 1024]; + } + + deflate.next_out = deflate_tmpbuf; + deflate.next_out_index = 0; + deflate.avail_out = output.length; + + if (deflate.deflate(JZlib.Z_PARTIAL_FLUSH) != JZlib.Z_OK) { + System.err.println("compress: compression failure"); + } + + if (deflate.avail_in > 0) { + System.err.println("compress: deflated data too large"); + } + + int outputlen = output.length - deflate.avail_out; + System.arraycopy(deflate_tmpbuf, 0, output, 0, outputlen); + return outputlen; + } + + public byte[] uncompress(byte[] buffer, int start, int[] length) { + int inflated_end = 0; + inflate.next_in = buffer; + inflate.next_in_index = start; + inflate.avail_in = length[0]; + + while (true) { + inflate.next_out = inflate_tmpbuf; + inflate.next_out_index = 0; + inflate.avail_out = DEFAULT_BUF_SIZE; + int status = inflate.inflate(JZlib.Z_PARTIAL_FLUSH); + + switch (status) { + case JZlib.Z_OK: + if (inflated_buf.length < inflated_end + DEFAULT_BUF_SIZE + - inflate.avail_out) { + byte[] foo = new byte[inflated_end + DEFAULT_BUF_SIZE + - inflate.avail_out]; + System.arraycopy(inflated_buf, 0, foo, 0, inflated_end); + inflated_buf = foo; + } + + System.arraycopy(inflate_tmpbuf, 0, inflated_buf, inflated_end, + DEFAULT_BUF_SIZE - inflate.avail_out); + inflated_end += (DEFAULT_BUF_SIZE - inflate.avail_out); + length[0] = inflated_end; + break; + + case JZlib.Z_BUF_ERROR: + if (inflated_end > buffer.length - start) { + byte[] foo = new byte[inflated_end + start]; + System.arraycopy(buffer, 0, foo, 0, start); + System.arraycopy(inflated_buf, 0, foo, start, inflated_end); + buffer = foo; + } + else { + System.arraycopy(inflated_buf, 0, buffer, start, + inflated_end); + } + + length[0] = inflated_end; + return buffer; + + default: + System.err.println("uncompress: inflate returnd " + status); + return null; + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/compression/ZlibOpenSSH.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,35 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.ethz.ssh2.compression; + +/** + * Defines how zlib@openssh.org compression works. + * See + * http://www.openssh.org/txt/draft-miller-secsh-compression-delayed-00.txt + * compression is disabled until userauth has occurred. + * + * @author Matt Johnston + * + */ +public class ZlibOpenSSH extends Zlib { + + public boolean canCompressPreauth() { + return false; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/Base64.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto; + +import java.io.CharArrayWriter; +import java.io.IOException; + +/** + * Basic Base64 Support. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class Base64 { + static final char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); + + public static char[] encode(byte[] content) { + CharArrayWriter cw = new CharArrayWriter((4 * content.length) / 3); + int idx = 0; + int x = 0; + + for (int i = 0; i < content.length; i++) { + if (idx == 0) + x = (content[i] & 0xff) << 16; + else if (idx == 1) + x = x | ((content[i] & 0xff) << 8); + else + x = x | (content[i] & 0xff); + + idx++; + + if (idx == 3) { + cw.write(alphabet[x >> 18]); + cw.write(alphabet[(x >> 12) & 0x3f]); + cw.write(alphabet[(x >> 6) & 0x3f]); + cw.write(alphabet[x & 0x3f]); + idx = 0; + } + } + + if (idx == 1) { + cw.write(alphabet[x >> 18]); + cw.write(alphabet[(x >> 12) & 0x3f]); + cw.write('='); + cw.write('='); + } + + if (idx == 2) { + cw.write(alphabet[x >> 18]); + cw.write(alphabet[(x >> 12) & 0x3f]); + cw.write(alphabet[(x >> 6) & 0x3f]); + cw.write('='); + } + + return cw.toCharArray(); + } + + public static byte[] decode(char[] message) throws IOException { + byte buff[] = new byte[4]; + byte dest[] = new byte[message.length]; + int bpos = 0; + int destpos = 0; + + for (int i = 0; i < message.length; i++) { + int c = message[i]; + + if ((c == '\n') || (c == '\r') || (c == ' ') || (c == '\t')) + continue; + + if ((c >= 'A') && (c <= 'Z')) { + buff[bpos++] = (byte)(c - 'A'); + } + else if ((c >= 'a') && (c <= 'z')) { + buff[bpos++] = (byte)((c - 'a') + 26); + } + else if ((c >= '0') && (c <= '9')) { + buff[bpos++] = (byte)((c - '0') + 52); + } + else if (c == '+') { + buff[bpos++] = 62; + } + else if (c == '/') { + buff[bpos++] = 63; + } + else if (c == '=') { + buff[bpos++] = 64; + } + else { + throw new IOException("Illegal char in base64 code."); + } + + if (bpos == 4) { + bpos = 0; + + if (buff[0] == 64) + break; + + if (buff[1] == 64) + throw new IOException("Unexpected '=' in base64 code."); + + if (buff[2] == 64) { + int v = (((buff[0] & 0x3f) << 6) | ((buff[1] & 0x3f))); + dest[destpos++] = (byte)(v >> 4); + break; + } + else if (buff[3] == 64) { + int v = (((buff[0] & 0x3f) << 12) | ((buff[1] & 0x3f) << 6) | ((buff[2] & 0x3f))); + dest[destpos++] = (byte)(v >> 10); + dest[destpos++] = (byte)(v >> 2); + break; + } + else { + int v = (((buff[0] & 0x3f) << 18) | ((buff[1] & 0x3f) << 12) | ((buff[2] & 0x3f) << 6) | ((buff[3] & 0x3f))); + dest[destpos++] = (byte)(v >> 16); + dest[destpos++] = (byte)(v >> 8); + dest[destpos++] = (byte)(v); + } + } + } + + byte[] res = new byte[destpos]; + System.arraycopy(dest, 0, res, 0, destpos); + return res; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/CryptoWishList.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto; + +import ch.ethz.ssh2.compression.CompressionFactory; +import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; +import ch.ethz.ssh2.crypto.digest.MAC; +import ch.ethz.ssh2.transport.KexManager; + +/** + * CryptoWishList. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class CryptoWishList { + public String[] kexAlgorithms = KexManager.getDefaultClientKexAlgorithmList(); + public String[] serverHostKeyAlgorithms = KexManager.getDefaultServerHostkeyAlgorithmList(); + public String[] c2s_enc_algos = BlockCipherFactory.getDefaultCipherList(); + public String[] s2c_enc_algos = BlockCipherFactory.getDefaultCipherList(); + public String[] c2s_mac_algos = MAC.getMacList(); + public String[] s2c_mac_algos = MAC.getMacList(); + public String[] c2s_comp_algos = CompressionFactory.getDefaultCompressorList(); + public String[] s2c_comp_algos = CompressionFactory.getDefaultCompressorList(); + + public static CryptoWishList forServer() { + CryptoWishList cwl = new CryptoWishList(); + cwl.kexAlgorithms = KexManager.getDefaultServerKexAlgorithmList(); + return cwl; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/KeyMaterial.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto; + +import java.io.IOException; +import java.math.BigInteger; + +import ch.ethz.ssh2.crypto.digest.HashForSSH2Types; + +/** + * Establishes key material for iv/key/mac (both directions). + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class KeyMaterial { + public byte[] initial_iv_client_to_server; + public byte[] initial_iv_server_to_client; + public byte[] enc_key_client_to_server; + public byte[] enc_key_server_to_client; + public byte[] integrity_key_client_to_server; + public byte[] integrity_key_server_to_client; + + private static byte[] calculateKey(HashForSSH2Types sh, BigInteger K, byte[] H, byte type, byte[] SessionID, + int keyLength) throws IOException { + byte[] res = new byte[keyLength]; + int dglen = sh.getDigestLength(); + int numRounds = (keyLength + dglen - 1) / dglen; + byte[][] tmp = new byte[numRounds][]; + sh.reset(); + sh.updateBigInt(K); + sh.updateBytes(H); + sh.updateByte(type); + sh.updateBytes(SessionID); + tmp[0] = sh.getDigest(); + int off = 0; + int produced = Math.min(dglen, keyLength); + System.arraycopy(tmp[0], 0, res, off, produced); + keyLength -= produced; + off += produced; + + for (int i = 1; i < numRounds; i++) { + sh.updateBigInt(K); + sh.updateBytes(H); + + for (int j = 0; j < i; j++) { + sh.updateBytes(tmp[j]); + } + + tmp[i] = sh.getDigest(); + produced = Math.min(dglen, keyLength); + System.arraycopy(tmp[i], 0, res, off, produced); + keyLength -= produced; + off += produced; + } + + return res; + } + + public static KeyMaterial create(String hashType, byte[] H, BigInteger K, byte[] SessionID, int keyLengthCS, + int blockSizeCS, int macLengthCS, int keyLengthSC, int blockSizeSC, int macLengthSC) + throws IOException { + KeyMaterial km = new KeyMaterial(); + HashForSSH2Types sh = new HashForSSH2Types(hashType); + km.initial_iv_client_to_server = calculateKey(sh, K, H, (byte) 'A', SessionID, blockSizeCS); + km.initial_iv_server_to_client = calculateKey(sh, K, H, (byte) 'B', SessionID, blockSizeSC); + km.enc_key_client_to_server = calculateKey(sh, K, H, (byte) 'C', SessionID, keyLengthCS); + km.enc_key_server_to_client = calculateKey(sh, K, H, (byte) 'D', SessionID, keyLengthSC); + km.integrity_key_client_to_server = calculateKey(sh, K, H, (byte) 'E', SessionID, macLengthCS); + km.integrity_key_server_to_client = calculateKey(sh, K, H, (byte) 'F', SessionID, macLengthSC); + return km; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/PEMDecoder.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,444 @@ + +package ch.ethz.ssh2.crypto; + +import java.io.BufferedReader; +import java.io.CharArrayReader; +import java.io.IOException; +import java.math.BigInteger; +import java.security.DigestException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.DSAPrivateKeySpec; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.RSAPrivateCrtKeySpec; +import java.security.spec.RSAPrivateKeySpec; +import java.security.spec.RSAPublicKeySpec; + +import ch.ethz.ssh2.crypto.cipher.AES; +import ch.ethz.ssh2.crypto.cipher.BlockCipher; +import ch.ethz.ssh2.crypto.cipher.CBCMode; +import ch.ethz.ssh2.crypto.cipher.DES; +import ch.ethz.ssh2.crypto.cipher.DESede; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; + +/** + * PEM Support. + * + * @author Christian Plattner, plattner@trilead.com + * @version $Id: PEMDecoder.java,v 1.2 2008/04/01 12:38:09 cplattne Exp $ + */ +public class PEMDecoder { + public static final int PEM_RSA_PRIVATE_KEY = 1; + public static final int PEM_DSA_PRIVATE_KEY = 2; + public static final int PEM_EC_PRIVATE_KEY = 3; + + private static final int hexToInt(char c) { + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a') + 10; + } + + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A') + 10; + } + + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + + throw new IllegalArgumentException("Need hex char"); + } + + private static byte[] hexToByteArray(String hex) { + if (hex == null) + throw new IllegalArgumentException("null argument"); + + if ((hex.length() % 2) != 0) + throw new IllegalArgumentException("Uneven string length in hex encoding."); + + byte decoded[] = new byte[hex.length() / 2]; + + for (int i = 0; i < decoded.length; i++) { + int hi = hexToInt(hex.charAt(i * 2)); + int lo = hexToInt(hex.charAt((i * 2) + 1)); + decoded[i] = (byte)(hi * 16 + lo); + } + + return decoded; + } + + private static byte[] generateKeyFromPasswordSaltWithMD5(byte[] password, byte[] salt, int keyLen) + throws IOException { + if (salt.length < 8) + throw new IllegalArgumentException("Salt needs to be at least 8 bytes for key generation."); + + MessageDigest md5; + + try { + md5 = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("VM does not support MD5", e); + } + + byte[] key = new byte[keyLen]; + byte[] tmp = new byte[md5.getDigestLength()]; + + while (true) { + md5.update(password, 0, password.length); + md5.update(salt, 0, 8); // ARGH we only use the first 8 bytes of the + // salt in this step. + // This took me two hours until I got AES-xxx running. + int copy = (keyLen < tmp.length) ? keyLen : tmp.length; + + try { + md5.digest(tmp, 0, tmp.length); + } + catch (DigestException e) { + IOException ex = new IOException("could not digest password"); + ex.initCause(e); + throw ex; + } + + System.arraycopy(tmp, 0, key, key.length - keyLen, copy); + keyLen -= copy; + + if (keyLen == 0) + return key; + + md5.update(tmp, 0, tmp.length); + } + } + + private static byte[] removePadding(byte[] buff, int blockSize) throws IOException { + /* Removes RFC 1423/PKCS #7 padding */ + int rfc_1423_padding = buff[buff.length - 1] & 0xff; + + if ((rfc_1423_padding < 1) || (rfc_1423_padding > blockSize)) + throw new IOException("Decrypted PEM has wrong padding, did you specify the correct password?"); + + for (int i = 2; i <= rfc_1423_padding; i++) { + if (buff[buff.length - i] != rfc_1423_padding) + throw new IOException("Decrypted PEM has wrong padding, did you specify the correct password?"); + } + + byte[] tmp = new byte[buff.length - rfc_1423_padding]; + System.arraycopy(buff, 0, tmp, 0, buff.length - rfc_1423_padding); + return tmp; + } + + public static final PEMStructure parsePEM(char[] pem) throws IOException { + PEMStructure ps = new PEMStructure(); + String line = null; + BufferedReader br = new BufferedReader(new CharArrayReader(pem)); + String endLine = null; + + while (true) { + line = br.readLine(); + + if (line == null) + throw new IOException("Invalid PEM structure, '-----BEGIN...' missing"); + + line = line.trim(); + + if (line.startsWith("-----BEGIN DSA PRIVATE KEY-----")) { + endLine = "-----END DSA PRIVATE KEY-----"; + ps.pemType = PEM_DSA_PRIVATE_KEY; + break; + } + + if (line.startsWith("-----BEGIN RSA PRIVATE KEY-----")) { + endLine = "-----END RSA PRIVATE KEY-----"; + ps.pemType = PEM_RSA_PRIVATE_KEY; + break; + } + + if (line.startsWith("-----BEGIN EC PRIVATE KEY-----")) { + endLine = "-----END EC PRIVATE KEY-----"; + ps.pemType = PEM_EC_PRIVATE_KEY; + break; + } + } + + while (true) { + line = br.readLine(); + + if (line == null) + throw new IOException("Invalid PEM structure, " + endLine + " missing"); + + line = line.trim(); + int sem_idx = line.indexOf(':'); + + if (sem_idx == -1) + break; + + String name = line.substring(0, sem_idx + 1); + String value = line.substring(sem_idx + 1); + String values[] = value.split(","); + + for (int i = 0; i < values.length; i++) + values[i] = values[i].trim(); + + // Proc-Type: 4,ENCRYPTED + // DEK-Info: DES-EDE3-CBC,579B6BE3E5C60483 + + if ("Proc-Type:".equals(name)) { + ps.procType = values; + continue; + } + + if ("DEK-Info:".equals(name)) { + ps.dekInfo = values; + continue; + } + + /* Ignore line */ + } + + StringBuffer keyData = new StringBuffer(); + + while (true) { + if (line == null) + throw new IOException("Invalid PEM structure, " + endLine + " missing"); + + line = line.trim(); + + if (line.startsWith(endLine)) + break; + + keyData.append(line); + line = br.readLine(); + } + + char[] pem_chars = new char[keyData.length()]; + keyData.getChars(0, pem_chars.length, pem_chars, 0); + ps.data = Base64.decode(pem_chars); + + if (ps.data.length == 0) + throw new IOException("Invalid PEM structure, no data available"); + + return ps; + } + + private static final void decryptPEM(PEMStructure ps, byte[] pw) throws IOException { + if (ps.dekInfo == null) + throw new IOException("Broken PEM, no mode and salt given, but encryption enabled"); + + if (ps.dekInfo.length != 2) + throw new IOException("Broken PEM, DEK-Info is incomplete!"); + + String algo = ps.dekInfo[0]; + byte[] salt = hexToByteArray(ps.dekInfo[1]); + BlockCipher bc = null; + + if (algo.equals("DES-EDE3-CBC")) { + DESede des3 = new DESede(); + des3.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 24)); + bc = new CBCMode(des3, salt, false); + } + else if (algo.equals("DES-CBC")) { + DES des = new DES(); + des.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 8)); + bc = new CBCMode(des, salt, false); + } + else if (algo.equals("AES-128-CBC")) { + AES aes = new AES(); + aes.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 16)); + bc = new CBCMode(aes, salt, false); + } + else if (algo.equals("AES-192-CBC")) { + AES aes = new AES(); + aes.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 24)); + bc = new CBCMode(aes, salt, false); + } + else if (algo.equals("AES-256-CBC")) { + AES aes = new AES(); + aes.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 32)); + bc = new CBCMode(aes, salt, false); + } + else { + throw new IOException("Cannot decrypt PEM structure, unknown cipher " + algo); + } + + if ((ps.data.length % bc.getBlockSize()) != 0) + throw new IOException("Invalid PEM structure, size of encrypted block is not a multiple of " + + bc.getBlockSize()); + + /* Now decrypt the content */ + byte[] dz = new byte[ps.data.length]; + + for (int i = 0; i < ps.data.length / bc.getBlockSize(); i++) { + bc.transformBlock(ps.data, i * bc.getBlockSize(), dz, i * bc.getBlockSize()); + } + + /* Now check and remove RFC 1423/PKCS #7 padding */ + dz = removePadding(dz, bc.getBlockSize()); + ps.data = dz; + ps.dekInfo = null; + ps.procType = null; + } + + public static final boolean isPEMEncrypted(PEMStructure ps) throws IOException { + if (ps.procType == null) + return false; + + if (ps.procType.length != 2) + throw new IOException("Unknown Proc-Type field."); + + if ("4".equals(ps.procType[0]) == false) + throw new IOException("Unknown Proc-Type field (" + ps.procType[0] + ")"); + + if ("ENCRYPTED".equals(ps.procType[1])) + return true; + + return false; + } + + public static KeyPair decode(char[] pem, String password) throws IOException { + PEMStructure ps = parsePEM(pem); + return decode(ps, password); + } + + public static KeyPair decode(PEMStructure ps, String password) throws IOException { + if (isPEMEncrypted(ps)) { + if (password == null) + throw new IOException("PEM is encrypted, but no password was specified"); + + decryptPEM(ps, password.getBytes("ISO-8859-1")); + } + + if (ps.pemType == PEM_DSA_PRIVATE_KEY) { + SimpleDERReader dr = new SimpleDERReader(ps.data); + byte[] seq = dr.readSequenceAsByteArray(); + + if (dr.available() != 0) + throw new IOException("Padding in DSA PRIVATE KEY DER stream."); + + dr.resetInput(seq); + BigInteger version = dr.readInt(); + + if (version.compareTo(BigInteger.ZERO) != 0) + throw new IOException("Wrong version (" + version + ") in DSA PRIVATE KEY DER stream."); + + BigInteger p = dr.readInt(); + BigInteger q = dr.readInt(); + BigInteger g = dr.readInt(); + BigInteger y = dr.readInt(); + BigInteger x = dr.readInt(); + + if (dr.available() != 0) + throw new IOException("Padding in DSA PRIVATE KEY DER stream."); + + DSAPrivateKeySpec privSpec = new DSAPrivateKeySpec(x, p, q, g); + DSAPublicKeySpec pubSpec = new DSAPublicKeySpec(y, p, q, g); + return generateKeyPair("DSA", privSpec, pubSpec); + } + + if (ps.pemType == PEM_RSA_PRIVATE_KEY) { + SimpleDERReader dr = new SimpleDERReader(ps.data); + byte[] seq = dr.readSequenceAsByteArray(); + + if (dr.available() != 0) + throw new IOException("Padding in RSA PRIVATE KEY DER stream."); + + dr.resetInput(seq); + BigInteger version = dr.readInt(); + + if ((version.compareTo(BigInteger.ZERO) != 0) && (version.compareTo(BigInteger.ONE) != 0)) + throw new IOException("Wrong version (" + version + ") in RSA PRIVATE KEY DER stream."); + + BigInteger n = dr.readInt(); + BigInteger e = dr.readInt(); + BigInteger d = dr.readInt(); + // TODO: is this right? + BigInteger primeP = dr.readInt(); + BigInteger primeQ = dr.readInt(); + BigInteger expP = dr.readInt(); + BigInteger expQ = dr.readInt(); + BigInteger coeff = dr.readInt(); + RSAPrivateKeySpec privSpec = new RSAPrivateCrtKeySpec(n, e, d, primeP, primeQ, expP, expQ, coeff); + RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(n, e); + return generateKeyPair("RSA", privSpec, pubSpec); + } + + if (ps.pemType == PEM_EC_PRIVATE_KEY) { + SimpleDERReader dr = new SimpleDERReader(ps.data); + byte[] seq = dr.readSequenceAsByteArray(); + + if (dr.available() != 0) + throw new IOException("Padding in EC PRIVATE KEY DER stream."); + + dr.resetInput(seq); + BigInteger version = dr.readInt(); + + if ((version.compareTo(BigInteger.ONE) != 0)) + throw new IOException("Wrong version (" + version + ") in EC PRIVATE KEY DER stream."); + + byte[] privateBytes = dr.readOctetString(); + String curveOid = null; + byte[] publicBytes = null; + + while (dr.available() > 0) { + int type = dr.readConstructedType(); + SimpleDERReader cr = dr.readConstructed(); + + switch (type) { + case 0: + curveOid = cr.readOid(); + break; + + case 1: + publicBytes = cr.readOctetString(); + break; + } + } + + ECParameterSpec params = ECDSASHA2Verify.getCurveForOID(curveOid); + + if (params == null) + throw new IOException("invalid OID"); + + BigInteger s = new BigInteger(privateBytes); + byte[] publicBytesSlice = new byte[publicBytes.length - 1]; + System.arraycopy(publicBytes, 1, publicBytesSlice, 0, publicBytesSlice.length); + ECPoint w = ECDSASHA2Verify.decodeECPoint(publicBytesSlice, params.getCurve()); + ECPrivateKeySpec privSpec = new ECPrivateKeySpec(s, params); + ECPublicKeySpec pubSpec = new ECPublicKeySpec(w, params); + return generateKeyPair("EC", privSpec, pubSpec); + } + + throw new IOException("PEM problem: it is of unknown type"); + } + + /** + * Generate a {@code KeyPair} given an {@code algorithm} and {@code KeySpec}. + */ + private static KeyPair generateKeyPair(String algorithm, KeySpec privSpec, KeySpec pubSpec) + throws IOException { + try { + final KeyFactory kf = KeyFactory.getInstance(algorithm); + final PublicKey pubKey = kf.generatePublic(pubSpec); + final PrivateKey privKey = kf.generatePrivate(privSpec); + return new KeyPair(pubKey, privKey); + } + catch (NoSuchAlgorithmException ex) { + IOException ioex = new IOException(); + ioex.initCause(ex); + throw ioex; + } + catch (InvalidKeySpecException ex) { + IOException ioex = new IOException("invalid keyspec"); + ioex.initCause(ex); + throw ioex; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/PEMDecryptException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2006-2014 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto; + +import java.io.IOException; + +/** + * @version $Id: PEMDecryptException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class PEMDecryptException extends IOException { + /** + * + */ + private static final long serialVersionUID = 1L; + + public PEMDecryptException(String message) { + super(message); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/PEMStructure.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto; + +/** + * Parsed PEM structure. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ + +public class PEMStructure { + public int pemType; + String dekInfo[]; + String procType[]; + byte[] data; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/SecureRandomFix.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,82 @@ +// +// Copyright (C) 2014 by 510 Software Group +// licensed under the GPLv3 or later + +package ch.ethz.ssh2.crypto; + +import android.os.Build; +import android.os.Process; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.SecureRandom; + + +public class SecureRandomFix extends SecureRandom { + + // http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html + + private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18; + private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL = + getBuildFingerprintAndDeviceSerial(); + + private static byte[] generateReasonableSeed() { + try { + ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream(); + DataOutputStream seedBufferOut = + new DataOutputStream(seedBuffer); + seedBufferOut.writeLong(System.currentTimeMillis()); + seedBufferOut.writeLong(System.nanoTime()); + seedBufferOut.writeInt(Process.myPid()); + seedBufferOut.writeInt(Process.myUid()); + seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL); + seedBufferOut.close(); + return seedBuffer.toByteArray(); + } catch (IOException e) { + throw new SecurityException("Failed to generate seed", e); + } + } + + /** + * Gets the hardware serial number of this device. + * + * @return serial number or {@code null} if not available. + */ + private static String getDeviceSerialNumber() { + // We're using the Reflection API because Build.SERIAL is only available + // since API Level 9 (Gingerbread, Android 2.3). + try { + return (String) Build.class.getField("SERIAL").get(null); + } catch (Exception ignored) { + return null; + } + } + + private static byte[] getBuildFingerprintAndDeviceSerial() { + StringBuilder result = new StringBuilder(); + String fingerprint = Build.FINGERPRINT; + if (fingerprint != null) { + result.append(fingerprint); + } + String serial = getDeviceSerialNumber(); + if (serial != null) { + result.append(serial); + } + try { + return result.toString().getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8 encoding not supported"); + } + } + + public SecureRandomFix() { + super(); + if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) { + // No need to apply the fix + return; + } + setSeed(generateReasonableSeed()); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/SimpleDERReader.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,205 @@ +package ch.ethz.ssh2.crypto; + +import java.io.IOException; + +import java.math.BigInteger; + +/** + * SimpleDERReader. + * + * @author Christian Plattner, plattner@trilead.com + * @version $Id: SimpleDERReader.java,v 1.1 2007/10/15 12:49:56 cplattne Exp $ + */ +public class SimpleDERReader { + private static final int CONSTRUCTED = 0x20; + + byte[] buffer; + int pos; + int count; + + public SimpleDERReader(byte[] b) { + resetInput(b); + } + + public SimpleDERReader(byte[] b, int off, int len) { + resetInput(b, off, len); + } + + public void resetInput(byte[] b) { + resetInput(b, 0, b.length); + } + + public void resetInput(byte[] b, int off, int len) { + buffer = b; + pos = off; + count = len; + } + + private byte readByte() throws IOException { + if (count <= 0) + throw new IOException("DER byte array: out of data"); + + count--; + return buffer[pos++]; + } + + private byte[] readBytes(int len) throws IOException { + if (len > count) + throw new IOException("DER byte array: out of data"); + + byte[] b = new byte[len]; + System.arraycopy(buffer, pos, b, 0, len); + pos += len; + count -= len; + return b; + } + + public int available() { + return count; + } + + private int readLength() throws IOException { + int len = readByte() & 0xff; + + if ((len & 0x80) == 0) + return len; + + int remain = len & 0x7F; + + if (remain == 0) + return -1; + + len = 0; + + while (remain > 0) { + len = len << 8; + len = len | (readByte() & 0xff); + remain--; + } + + return len; + } + + public int ignoreNextObject() throws IOException { + int type = readByte() & 0xff; + int len = readLength(); + + if ((len < 0) || len > available()) + throw new IOException("Illegal len in DER object (" + len + ")"); + + readBytes(len); + return type; + } + + public BigInteger readInt() throws IOException { + int type = readByte() & 0xff; + + if (type != 0x02) + throw new IOException("Expected DER Integer, but found type " + type); + + int len = readLength(); + + if ((len < 0) || len > available()) + throw new IOException("Illegal len in DER object (" + len + ")"); + + byte[] b = readBytes(len); + BigInteger bi = new BigInteger(b); + return bi; + } + + public int readConstructedType() throws IOException { + int type = readByte() & 0xff; + + if ((type & CONSTRUCTED) != CONSTRUCTED) + throw new IOException("Expected constructed type, but was " + type); + + return type & 0x1f; + } + + public SimpleDERReader readConstructed() throws IOException { + int len = readLength(); + + if ((len < 0) || len > available()) + throw new IOException("Illegal len in DER object (" + len + ")"); + + SimpleDERReader cr = new SimpleDERReader(buffer, pos, len); + pos += len; + count -= len; + return cr; + } + + public byte[] readSequenceAsByteArray() throws IOException { + int type = readByte() & 0xff; + + if (type != 0x30) + throw new IOException("Expected DER Sequence, but found type " + type); + + int len = readLength(); + + if ((len < 0) || len > available()) + throw new IOException("Illegal len in DER object (" + len + ")"); + + byte[] b = readBytes(len); + return b; + } + + public String readOid() throws IOException { + int type = readByte() & 0xff; + + if (type != 0x06) + throw new IOException("Expected DER OID, but found type " + type); + + int len = readLength(); + + if ((len < 1) || len > available()) + throw new IOException("Illegal len in DER object (" + len + ")"); + + byte[] b = readBytes(len); + long value = 0; + StringBuilder sb = new StringBuilder(64); + + switch (b[0] / 40) { + case 0: + sb.append('0'); + break; + + case 1: + sb.append('1'); + b[0] -= 40; + break; + + default: + sb.append('2'); + b[0] -= 80; + break; + } + + for (int i = 0; i < len; i++) { + value = (value << 7) + (b[i] & 0x7F); + + if ((b[i] & 0x80) == 0) { + sb.append('.'); + sb.append(value); + value = 0; + } + } + + return sb.toString(); + } + + public byte[] readOctetString() throws IOException { + int type = readByte() & 0xff; + + if (type != 0x04 && type != 0x03) + throw new IOException("Expected DER Octetstring, but found type " + type); + + int len = readLength(); + + if ((len < 0) || len > available()) + throw new IOException("Illegal len in DER object (" + len + ")"); + + byte[] b = readBytes(len); + return b; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/AES.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,661 @@ +package ch.ethz.ssh2.crypto.cipher; + +/* + This file was shamelessly taken from the Bouncy Castle Crypto package. + Their licence file states the following: + + Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle + (http://www.bouncycastle.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +/** + * An implementation of the AES (Rijndael), from FIPS-197. + * <p> + * For further details see: <a + * href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/ + * </a>. + * + * This implementation is based on optimizations from Dr. Brian Gladman's paper + * and C code at <a + * href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/ + * </a> + * + * There are three levels of tradeoff of speed vs memory Because java has no + * preprocessor, they are written as three separate classes from which to choose + * + * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 + * 256 word tables for encryption and 4 for decryption. + * + * The middle performance version uses only one 256 word table for each, for a + * total of 2Kbytes, adding 12 rotate operations per round to compute the values + * contained in the other tables from the contents of the first + * + * The slowest version uses no static tables at all and computes the values in + * each round + * <p> + * This file contains the fast version with 8Kbytes of static tables for round + * precomputation + * + * @author See comments in the source file + * @version 2.50, 03/15/10 + */ +public class AES implements BlockCipher { + // The S box + private static final byte[] S = { (byte) 99, (byte) 124, (byte) 119, (byte) 123, (byte) 242, (byte) 107, + (byte) 111, (byte) 197, (byte) 48, (byte) 1, (byte) 103, (byte) 43, (byte) 254, (byte) 215, (byte) 171, + (byte) 118, (byte) 202, (byte) 130, (byte) 201, (byte) 125, (byte) 250, (byte) 89, (byte) 71, (byte) 240, + (byte) 173, (byte) 212, (byte) 162, (byte) 175, (byte) 156, (byte) 164, (byte) 114, (byte) 192, (byte) 183, + (byte) 253, (byte) 147, (byte) 38, (byte) 54, (byte) 63, (byte) 247, (byte) 204, (byte) 52, (byte) 165, + (byte) 229, (byte) 241, (byte) 113, (byte) 216, (byte) 49, (byte) 21, (byte) 4, (byte) 199, (byte) 35, + (byte) 195, (byte) 24, (byte) 150, (byte) 5, (byte) 154, (byte) 7, (byte) 18, (byte) 128, (byte) 226, + (byte) 235, (byte) 39, (byte) 178, (byte) 117, (byte) 9, (byte) 131, (byte) 44, (byte) 26, (byte) 27, + (byte) 110, (byte) 90, (byte) 160, (byte) 82, (byte) 59, (byte) 214, (byte) 179, (byte) 41, (byte) 227, + (byte) 47, (byte) 132, (byte) 83, (byte) 209, (byte) 0, (byte) 237, (byte) 32, (byte) 252, (byte) 177, + (byte) 91, (byte) 106, (byte) 203, (byte) 190, (byte) 57, (byte) 74, (byte) 76, (byte) 88, (byte) 207, + (byte) 208, (byte) 239, (byte) 170, (byte) 251, (byte) 67, (byte) 77, (byte) 51, (byte) 133, (byte) 69, + (byte) 249, (byte) 2, (byte) 127, (byte) 80, (byte) 60, (byte) 159, (byte) 168, (byte) 81, (byte) 163, + (byte) 64, (byte) 143, (byte) 146, (byte) 157, (byte) 56, (byte) 245, (byte) 188, (byte) 182, (byte) 218, + (byte) 33, (byte) 16, (byte) 255, (byte) 243, (byte) 210, (byte) 205, (byte) 12, (byte) 19, (byte) 236, + (byte) 95, (byte) 151, (byte) 68, (byte) 23, (byte) 196, (byte) 167, (byte) 126, (byte) 61, (byte) 100, + (byte) 93, (byte) 25, (byte) 115, (byte) 96, (byte) 129, (byte) 79, (byte) 220, (byte) 34, (byte) 42, + (byte) 144, (byte) 136, (byte) 70, (byte) 238, (byte) 184, (byte) 20, (byte) 222, (byte) 94, (byte) 11, + (byte) 219, (byte) 224, (byte) 50, (byte) 58, (byte) 10, (byte) 73, (byte) 6, (byte) 36, (byte) 92, + (byte) 194, (byte) 211, (byte) 172, (byte) 98, (byte) 145, (byte) 149, (byte) 228, (byte) 121, (byte) 231, + (byte) 200, (byte) 55, (byte) 109, (byte) 141, (byte) 213, (byte) 78, (byte) 169, (byte) 108, (byte) 86, + (byte) 244, (byte) 234, (byte) 101, (byte) 122, (byte) 174, (byte) 8, (byte) 186, (byte) 120, (byte) 37, + (byte) 46, (byte) 28, (byte) 166, (byte) 180, (byte) 198, (byte) 232, (byte) 221, (byte) 116, (byte) 31, + (byte) 75, (byte) 189, (byte) 139, (byte) 138, (byte) 112, (byte) 62, (byte) 181, (byte) 102, (byte) 72, + (byte) 3, (byte) 246, (byte) 14, (byte) 97, (byte) 53, (byte) 87, (byte) 185, (byte) 134, (byte) 193, + (byte) 29, (byte) 158, (byte) 225, (byte) 248, (byte) 152, (byte) 17, (byte) 105, (byte) 217, (byte) 142, + (byte) 148, (byte) 155, (byte) 30, (byte) 135, (byte) 233, (byte) 206, (byte) 85, (byte) 40, (byte) 223, + (byte) 140, (byte) 161, (byte) 137, (byte) 13, (byte) 191, (byte) 230, (byte) 66, (byte) 104, (byte) 65, + (byte) 153, (byte) 45, (byte) 15, (byte) 176, (byte) 84, (byte) 187, (byte) 22, + }; + + // The inverse S-box + private static final byte[] Si = { (byte) 82, (byte) 9, (byte) 106, (byte) 213, (byte) 48, (byte) 54, (byte) 165, + (byte) 56, (byte) 191, (byte) 64, (byte) 163, (byte) 158, (byte) 129, (byte) 243, (byte) 215, (byte) 251, + (byte) 124, (byte) 227, (byte) 57, (byte) 130, (byte) 155, (byte) 47, (byte) 255, (byte) 135, (byte) 52, + (byte) 142, (byte) 67, (byte) 68, (byte) 196, (byte) 222, (byte) 233, (byte) 203, (byte) 84, (byte) 123, + (byte) 148, (byte) 50, (byte) 166, (byte) 194, (byte) 35, (byte) 61, (byte) 238, (byte) 76, (byte) 149, + (byte) 11, (byte) 66, (byte) 250, (byte) 195, (byte) 78, (byte) 8, (byte) 46, (byte) 161, (byte) 102, + (byte) 40, (byte) 217, (byte) 36, (byte) 178, (byte) 118, (byte) 91, (byte) 162, (byte) 73, (byte) 109, + (byte) 139, (byte) 209, (byte) 37, (byte) 114, (byte) 248, (byte) 246, (byte) 100, (byte) 134, (byte) 104, + (byte) 152, (byte) 22, (byte) 212, (byte) 164, (byte) 92, (byte) 204, (byte) 93, (byte) 101, (byte) 182, + (byte) 146, (byte) 108, (byte) 112, (byte) 72, (byte) 80, (byte) 253, (byte) 237, (byte) 185, (byte) 218, + (byte) 94, (byte) 21, (byte) 70, (byte) 87, (byte) 167, (byte) 141, (byte) 157, (byte) 132, (byte) 144, + (byte) 216, (byte) 171, (byte) 0, (byte) 140, (byte) 188, (byte) 211, (byte) 10, (byte) 247, (byte) 228, + (byte) 88, (byte) 5, (byte) 184, (byte) 179, (byte) 69, (byte) 6, (byte) 208, (byte) 44, (byte) 30, + (byte) 143, (byte) 202, (byte) 63, (byte) 15, (byte) 2, (byte) 193, (byte) 175, (byte) 189, (byte) 3, + (byte) 1, (byte) 19, (byte) 138, (byte) 107, (byte) 58, (byte) 145, (byte) 17, (byte) 65, (byte) 79, + (byte) 103, (byte) 220, (byte) 234, (byte) 151, (byte) 242, (byte) 207, (byte) 206, (byte) 240, (byte) 180, + (byte) 230, (byte) 115, (byte) 150, (byte) 172, (byte) 116, (byte) 34, (byte) 231, (byte) 173, (byte) 53, + (byte) 133, (byte) 226, (byte) 249, (byte) 55, (byte) 232, (byte) 28, (byte) 117, (byte) 223, (byte) 110, + (byte) 71, (byte) 241, (byte) 26, (byte) 113, (byte) 29, (byte) 41, (byte) 197, (byte) 137, (byte) 111, + (byte) 183, (byte) 98, (byte) 14, (byte) 170, (byte) 24, (byte) 190, (byte) 27, (byte) 252, (byte) 86, + (byte) 62, (byte) 75, (byte) 198, (byte) 210, (byte) 121, (byte) 32, (byte) 154, (byte) 219, (byte) 192, + (byte) 254, (byte) 120, (byte) 205, (byte) 90, (byte) 244, (byte) 31, (byte) 221, (byte) 168, (byte) 51, + (byte) 136, (byte) 7, (byte) 199, (byte) 49, (byte) 177, (byte) 18, (byte) 16, (byte) 89, (byte) 39, + (byte) 128, (byte) 236, (byte) 95, (byte) 96, (byte) 81, (byte) 127, (byte) 169, (byte) 25, (byte) 181, + (byte) 74, (byte) 13, (byte) 45, (byte) 229, (byte) 122, (byte) 159, (byte) 147, (byte) 201, (byte) 156, + (byte) 239, (byte) 160, (byte) 224, (byte) 59, (byte) 77, (byte) 174, (byte) 42, (byte) 245, (byte) 176, + (byte) 200, (byte) 235, (byte) 187, (byte) 60, (byte) 131, (byte) 83, (byte) 153, (byte) 97, (byte) 23, + (byte) 43, (byte) 4, (byte) 126, (byte) 186, (byte) 119, (byte) 214, (byte) 38, (byte) 225, (byte) 105, + (byte) 20, (byte) 99, (byte) 85, (byte) 33, (byte) 12, (byte) 125, + }; + + // vector used in calculating key schedule (powers of x in GF(256)) + private static final int[] rcon = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, + 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 + }; + + // precomputation tables of calculations for rounds + private static final int[] T0 = { 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, + 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, + 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, 0xc2b7b775, + 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551, + 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795, 0x65232346, + 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, + 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, + 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, + 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, + 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a, + 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, + 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, + 0x63212142, 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, + 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, + 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, + 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, + 0x76dbdbad, 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, + 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac, + 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a, + 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, + 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, + 0x05030306, 0x01f6f6f7, 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, + 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, + 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, + 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c + }; + + private static final int[] T1 = { 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, + 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, + 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, + 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, 0xb7b775c2, + 0xfdfde11c, 0x93933dae, 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, 0x3434685c, 0xa5a551f4, + 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552, 0x23234665, + 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, + 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, + 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, + 0x2f2f5e71, 0x84841397, 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060, 0xfcfce31f, 0xb1b179c8, + 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, + 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf, + 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, + 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, + 0x21214263, 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f, + 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, + 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e, + 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, + 0xdbdbad76, 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4, + 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, 0xe7e7d532, + 0xc8c88b43, 0x37376e59, 0x6d6ddab7, 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, 0x5656acfa, + 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f, + 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, + 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, 0x484890d8, + 0x03030605, 0xf6f6f701, 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958, + 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, + 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, + 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, + 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a + }; + + private static final int[] T2 = { 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, + 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, + 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, + 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, 0xb775c2b7, + 0xfde11cfd, 0x933dae93, 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, 0x34685c34, 0xa551f4a5, + 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7, 0x23466523, + 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, + 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, + 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, + 0x2f5e712f, 0x84139784, 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020, 0xfce31ffc, 0xb179c8b1, + 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, + 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45, + 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, + 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, + 0x21426321, 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec, + 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, 0x64c8ac64, + 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a, + 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, + 0xdbad76db, 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c, + 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, 0xe7d532e7, + 0xc88b43c8, 0x376e5937, 0x6ddab76d, 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, 0x56acfa56, + 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25, + 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, + 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, 0x4890d848, + 0x03060503, 0xf6f701f6, 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1, + 0x1d3a271d, 0x9e27b99e, 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9, 0x8e07898e, + 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, + 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, + 0x9929b099, 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16 + }; + + private static final int[] T3 = { 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, + 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, + 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, + 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, + 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, 0x685c3434, 0x51f4a5a5, + 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7, 0x46652323, + 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, + 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, + 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, + 0x5e712f2f, 0x13978484, 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020, 0xe31ffcfc, 0x79c8b1b1, + 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, + 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545, + 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, + 0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, + 0x42632121, 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, + 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, + 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a, + 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, + 0xad76dbdb, 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c, + 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, 0xd532e7e7, + 0x8b43c8c8, 0x6e593737, 0xdab76d6d, 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, 0xacfa5656, + 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525, + 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, + 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, 0x90d84848, + 0x06050303, 0xf701f6f6, 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1, + 0x3a271d1d, 0x27b99e9e, 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9, 0x07898e8e, + 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, + 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, + 0x29b09999, 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616 + }; + + private static final int[] Tinv0 = { 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, + 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, + 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, + 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, 0x6a89c275, + 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5, + 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f, 0x876cde94, + 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3, + 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, + 0xd5be0506, 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, + 0x069f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x055dc471, 0x6fd40604, + 0xff155060, 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, + 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd, + 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, + 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, + 0x1d171b12, 0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, + 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, + 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, + 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, + 0xef903322, 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, + 0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, 0xbe805d9f, + 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd, 0xf418596e, + 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea, + 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, + 0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, + 0x1b886a4c, 0xb81f2cc1, 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, + 0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, + 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, + 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, + 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0 + }; + + private static final int[] Tinv1 = { 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb, 0x459d1ff1, + 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680, + 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1, 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, + 0x5f8f03e7, 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3, 0x69e04929, 0xc8c98e44, 0x89c2756a, + 0x798ef478, 0x3e58996b, 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4, 0x4adf6318, 0x311ae582, + 0x33519760, 0x7f536245, 0x7764b1e0, 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19, 0x6cde9487, + 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357, 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5, + 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b, 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, + 0xbe0506d5, 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532, 0xebf6a475, 0xec830b39, 0xef6040aa, + 0x9f715e06, 0x106ebd51, 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5, 0x5dc47105, 0xd406046f, + 0x155060ff, 0xfb981924, 0xe9bdd697, 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738, 0xeec879db, + 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000, 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb, + 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821, 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, + 0x96eeb4d2, 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16, 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, + 0x171b121d, 0x0d090e0b, 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c, 0xdd99eebb, 0x607fa3fd, + 0x2601f79f, 0xf5725cbc, 0x3b6644c5, 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863, 0xdc31d7ca, + 0x85634210, 0x22971340, 0x11c68420, 0x244a857d, 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3, + 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa, 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, + 0x903322ef, 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf, 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, + 0x9d3a2ce4, 0x9278500d, 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e, 0xafc382f5, 0x805d9fbe, + 0x93d0697c, 0x2dd56fa9, 0x1225cfb3, 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09, 0x18596ef4, + 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e, 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4, + 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0, 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, + 0x9804f14a, 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d, 0x4daacc54, 0x0496e4df, 0xb5d19ee3, + 0x886a4c1b, 0x1f2cc1b8, 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e, 0x1d67b35a, 0xd2db9252, + 0x5610e933, 0x47d66d13, 0x61d79a8c, 0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735, 0xe51ce1ed, + 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879, 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886, + 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, + 0xb30c08de, 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042 + }; + + private static final int[] Tinv2 = { 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b, 0x9d1ff145, + 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d, 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044, + 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0, 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, + 0x8f03e75f, 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321, 0xe0492969, 0xc98e44c8, 0xc2756a89, + 0x8ef47879, 0x58996b3e, 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a, 0xdf63184a, 0x1ae58231, + 0x51976033, 0x5362457f, 0x64b1e077, 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd, 0xde94876c, + 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f, 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508, + 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c, 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, + 0x0506d5be, 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1, 0xf6a475eb, 0x830b39ec, 0x6040aaef, + 0x715e069f, 0x6ebd5110, 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d, 0xc471055d, 0x06046fd4, + 0x5060ff15, 0x981924fb, 0xbdd697e9, 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b, 0xc879dbee, + 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000, 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff, + 0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6, 0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, + 0xeeb4d296, 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a, 0x93e20aba, 0xa0c0e52a, 0x223c43e0, + 0x1b121d17, 0x090e0b0d, 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07, 0x99eebbdd, 0x7fa3fd60, + 0x01f79f26, 0x725cbcf5, 0x6644c53b, 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1, 0x31d7cadc, + 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24, 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330, + 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48, 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, + 0x3322ef90, 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81, 0x7aa528de, 0xb7da268e, 0xad3fa4bf, + 0x3a2ce49d, 0x78500d92, 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7, 0xc382f5af, 0x5d9fbe80, + 0xd0697c93, 0xd56fa92d, 0x25cfb312, 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978, 0x596ef418, + 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6, 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409, + 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066, 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, + 0x04f14a98, 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0, 0xaacc544d, 0x96e4df04, 0xd19ee3b5, + 0x6a4c1b88, 0x2cc1b81f, 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41, 0x67b35a1d, 0xdb9252d2, + 0x10e93356, 0xd66d1347, 0xd79a8c61, 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9, 0x1ce1ede5, + 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce, 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db, + 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, + 0x0c08deb3, 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257 + }; + + private static final int[] Tinv3 = { 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab, 0x1ff1459d, + 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, + 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe, 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, + 0x03e75f8f, 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174, 0x492969e0, 0x8e44c8c9, 0x756a89c2, + 0xf478798e, 0x996b3e58, 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace, 0x63184adf, 0xe582311a, + 0x97603351, 0x62457f53, 0xb1e07764, 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45, 0x94876cde, + 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f, 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837, + 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf, 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, + 0x06d5be05, 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a, 0xa475ebf6, 0x0b39ec83, 0x40aaef60, + 0x5e069f71, 0xbd51106e, 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54, 0x71055dc4, 0x046fd406, + 0x60ff1550, 0x1924fb98, 0xd697e9bd, 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19, 0x79dbeec8, + 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000, 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e, + 0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c, 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, + 0xb4d296ee, 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12, 0xe20aba93, 0xc0e52aa0, 0x3c43e022, + 0x121d171b, 0x0e0b0d09, 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775, 0xeebbdd99, 0xa3fd607f, + 0xf79f2601, 0x5cbcf572, 0x44c53b66, 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4, 0xd7cadc31, + 0x42108563, 0x13402297, 0x842011c6, 0x857d244a, 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2, + 0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894, 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, + 0x22ef9033, 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5, 0xa528de7a, 0xda268eb7, 0x3fa4bfad, + 0x2ce49d3a, 0x500d9278, 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739, 0x82f5afc3, 0x9fbe805d, + 0x697c93d0, 0x6fa92dd5, 0xcfb31225, 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826, 0x6ef41859, + 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff, 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f, + 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2, 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, + 0xf14a9804, 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef, 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, + 0x4c1b886a, 0xc1b81f2c, 0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b, 0xb35a1d67, 0x9252d2db, + 0xe9335610, 0x6d1347d6, 0x9a8c61d7, 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961, 0xe1ede51c, + 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14, 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44, + 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d, 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, + 0x08deb30c, 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8 + }; + + private int shift(int r, int shift) { + return (((r >>> shift) | (r << (32 - shift)))); + } + + /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + + private static final int m1 = 0x80808080; + private static final int m2 = 0x7f7f7f7f; + private static final int m3 = 0x0000001b; + + private int FFmulX(int x) { + return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3)); + } + + /* + * The following defines provide alternative definitions of FFmulX that + * might give improved performance if a fast 32-bit multiply is not + * available. + * + * private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & + * m2) < < 1) ^ ((u >>> 3) | (u >>> 6)); } private static final int m4 = + * 0x1b1b1b1b; private int FFmulX(int x) { int u = x & m1; return ((x & m2) < < + * 1) ^ ((u - (u >>> 7)) & m4); } + * + */ + + private int inv_mcol(int x) { + int f2 = FFmulX(x); + int f4 = FFmulX(f2); + int f8 = FFmulX(f4); + int f9 = x ^ f8; + return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24); + } + + private int subWord(int x) { + return (S[x & 255] & 255 | ((S[(x >> 8) & 255] & 255) << 8) | ((S[(x >> 16) & 255] & 255) << 16) | S[(x >> 24) & 255] << 24); + } + + /** + * Calculate the necessary round keys The number of calculations depends on + * key size and block size AES specified a fixed block size of 128 bits and + * key sizes 128/192/256 bits This code is written assuming those are the + * only possible values + */ + private int[][] generateWorkingKey(byte[] key, boolean forEncryption) { + int KC = key.length / 4; // key length in words + int t; + + if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length)) { + throw new IllegalArgumentException("Key length not 128/192/256 bits."); + } + + ROUNDS = KC + 6; // This is not always true for the generalized + // Rijndael that allows larger block sizes + int[][] W = new int[ROUNDS + 1][4]; // 4 words in a block + // + // copy the key into the round key array + // + t = 0; + + for (int i = 0; i < key.length; t++) { + W[t >> 2][t & 3] = (key[i] & 0xff) | ((key[i + 1] & 0xff) << 8) | ((key[i + 2] & 0xff) << 16) + | (key[i + 3] << 24); + i += 4; + } + + // + // while not enough round key material calculated + // calculate new values + // + int k = (ROUNDS + 1) << 2; + + for (int i = KC; (i < k); i++) { + int temp = W[(i - 1) >> 2][(i - 1) & 3]; + + if ((i % KC) == 0) { + temp = subWord(shift(temp, 8)) ^ rcon[(i / KC) - 1]; + } + else if ((KC > 6) && ((i % KC) == 4)) { + temp = subWord(temp); + } + + W[i >> 2][i & 3] = W[(i - KC) >> 2][(i - KC) & 3] ^ temp; + } + + if (!forEncryption) { + for (int j = 1; j < ROUNDS; j++) { + for (int i = 0; i < 4; i++) { + W[j][i] = inv_mcol(W[j][i]); + } + } + } + + return W; + } + + private int ROUNDS; + private int[][] WorkingKey = null; + private int C0, C1, C2, C3; + private boolean doEncrypt; + + private static final int BLOCK_SIZE = 16; + + /** + * default constructor - 128 bit block size. + */ + public AES() { + } + + /** + * initialise an AES cipher. + * + * @param forEncryption + * whether or not we are for encryption. + * @param key + * the key required to set up the cipher. + * @exception IllegalArgumentException + * if the params argument is inappropriate. + */ + + public final void init(boolean forEncryption, byte[] key) { + WorkingKey = generateWorkingKey(key, forEncryption); + this.doEncrypt = forEncryption; + } + + public final String getAlgorithmName() { + return "AES"; + } + + public final int getBlockSize() { + return BLOCK_SIZE; + } + + public final int processBlock(byte[] in, int inOff, byte[] out, int outOff) { + if (WorkingKey == null) { + throw new IllegalStateException("AES engine not initialised"); + } + + if ((inOff + (32 / 2)) > in.length) { + throw new IllegalArgumentException("input buffer too short"); + } + + if ((outOff + (32 / 2)) > out.length) { + throw new IllegalArgumentException("output buffer too short"); + } + + if (doEncrypt) { + unpackBlock(in, inOff); + encryptBlock(WorkingKey); + packBlock(out, outOff); + } + else { + unpackBlock(in, inOff); + decryptBlock(WorkingKey); + packBlock(out, outOff); + } + + return BLOCK_SIZE; + } + + public final void reset() { + } + + private void unpackBlock(byte[] bytes, int off) { + int index = off; + C0 = (bytes[index++] & 0xff); + C0 |= (bytes[index++] & 0xff) << 8; + C0 |= (bytes[index++] & 0xff) << 16; + C0 |= bytes[index++] << 24; + C1 = (bytes[index++] & 0xff); + C1 |= (bytes[index++] & 0xff) << 8; + C1 |= (bytes[index++] & 0xff) << 16; + C1 |= bytes[index++] << 24; + C2 = (bytes[index++] & 0xff); + C2 |= (bytes[index++] & 0xff) << 8; + C2 |= (bytes[index++] & 0xff) << 16; + C2 |= bytes[index++] << 24; + C3 = (bytes[index++] & 0xff); + C3 |= (bytes[index++] & 0xff) << 8; + C3 |= (bytes[index++] & 0xff) << 16; + C3 |= bytes[index++] << 24; + } + + private void packBlock(byte[] bytes, int off) { + int index = off; + bytes[index++] = (byte) C0; + bytes[index++] = (byte)(C0 >> 8); + bytes[index++] = (byte)(C0 >> 16); + bytes[index++] = (byte)(C0 >> 24); + bytes[index++] = (byte) C1; + bytes[index++] = (byte)(C1 >> 8); + bytes[index++] = (byte)(C1 >> 16); + bytes[index++] = (byte)(C1 >> 24); + bytes[index++] = (byte) C2; + bytes[index++] = (byte)(C2 >> 8); + bytes[index++] = (byte)(C2 >> 16); + bytes[index++] = (byte)(C2 >> 24); + bytes[index++] = (byte) C3; + bytes[index++] = (byte)(C3 >> 8); + bytes[index++] = (byte)(C3 >> 16); + bytes[index++] = (byte)(C3 >> 24); + } + + private void encryptBlock(int[][] KW) { + int r, r0, r1, r2, r3; + C0 ^= KW[0][0]; + C1 ^= KW[0][1]; + C2 ^= KW[0][2]; + C3 ^= KW[0][3]; + + for (r = 1; r < ROUNDS - 1;) { + r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[(C3 >> 24) & 255] ^ KW[r][0]; + r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[(C0 >> 24) & 255] ^ KW[r][1]; + r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[(C1 >> 24) & 255] ^ KW[r][2]; + r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[(C2 >> 24) & 255] ^ KW[r++][3]; + C0 = T0[r0 & 255] ^ T1[(r1 >> 8) & 255] ^ T2[(r2 >> 16) & 255] ^ T3[(r3 >> 24) & 255] ^ KW[r][0]; + C1 = T0[r1 & 255] ^ T1[(r2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[(r0 >> 24) & 255] ^ KW[r][1]; + C2 = T0[r2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(r0 >> 16) & 255] ^ T3[(r1 >> 24) & 255] ^ KW[r][2]; + C3 = T0[r3 & 255] ^ T1[(r0 >> 8) & 255] ^ T2[(r1 >> 16) & 255] ^ T3[(r2 >> 24) & 255] ^ KW[r++][3]; + } + + r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[(C3 >> 24) & 255] ^ KW[r][0]; + r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[(C0 >> 24) & 255] ^ KW[r][1]; + r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[(C1 >> 24) & 255] ^ KW[r][2]; + r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[(C2 >> 24) & 255] ^ KW[r++][3]; + // the final round's table is a simple function of S so we don't use a + // whole other four tables for it + C0 = (S[r0 & 255] & 255) ^ ((S[(r1 >> 8) & 255] & 255) << 8) ^ ((S[(r2 >> 16) & 255] & 255) << 16) + ^ (S[(r3 >> 24) & 255] << 24) ^ KW[r][0]; + C1 = (S[r1 & 255] & 255) ^ ((S[(r2 >> 8) & 255] & 255) << 8) ^ ((S[(r3 >> 16) & 255] & 255) << 16) + ^ (S[(r0 >> 24) & 255] << 24) ^ KW[r][1]; + C2 = (S[r2 & 255] & 255) ^ ((S[(r3 >> 8) & 255] & 255) << 8) ^ ((S[(r0 >> 16) & 255] & 255) << 16) + ^ (S[(r1 >> 24) & 255] << 24) ^ KW[r][2]; + C3 = (S[r3 & 255] & 255) ^ ((S[(r0 >> 8) & 255] & 255) << 8) ^ ((S[(r1 >> 16) & 255] & 255) << 16) + ^ (S[(r2 >> 24) & 255] << 24) ^ KW[r][3]; + } + + private void decryptBlock(int[][] KW) { + int r, r0, r1, r2, r3; + C0 ^= KW[ROUNDS][0]; + C1 ^= KW[ROUNDS][1]; + C2 ^= KW[ROUNDS][2]; + C3 ^= KW[ROUNDS][3]; + + for (r = ROUNDS - 1; r > 1;) { + r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[(C1 >> 24) & 255] + ^ KW[r][0]; + r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[(C2 >> 24) & 255] + ^ KW[r][1]; + r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[(C3 >> 24) & 255] + ^ KW[r][2]; + r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[(C0 >> 24) & 255] + ^ KW[r--][3]; + C0 = Tinv0[r0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(r2 >> 16) & 255] ^ Tinv3[(r1 >> 24) & 255] + ^ KW[r][0]; + C1 = Tinv0[r1 & 255] ^ Tinv1[(r0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[(r2 >> 24) & 255] + ^ KW[r][1]; + C2 = Tinv0[r2 & 255] ^ Tinv1[(r1 >> 8) & 255] ^ Tinv2[(r0 >> 16) & 255] ^ Tinv3[(r3 >> 24) & 255] + ^ KW[r][2]; + C3 = Tinv0[r3 & 255] ^ Tinv1[(r2 >> 8) & 255] ^ Tinv2[(r1 >> 16) & 255] ^ Tinv3[(r0 >> 24) & 255] + ^ KW[r--][3]; + } + + r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[(C1 >> 24) & 255] ^ KW[r][0]; + r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[(C2 >> 24) & 255] ^ KW[r][1]; + r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[(C3 >> 24) & 255] ^ KW[r][2]; + r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[(C0 >> 24) & 255] ^ KW[r--][3]; + // the final round's table is a simple function of Si so we don't use a + // whole other four tables for it + C0 = (Si[r0 & 255] & 255) ^ ((Si[(r3 >> 8) & 255] & 255) << 8) ^ ((Si[(r2 >> 16) & 255] & 255) << 16) + ^ (Si[(r1 >> 24) & 255] << 24) ^ KW[0][0]; + C1 = (Si[r1 & 255] & 255) ^ ((Si[(r0 >> 8) & 255] & 255) << 8) ^ ((Si[(r3 >> 16) & 255] & 255) << 16) + ^ (Si[(r2 >> 24) & 255] << 24) ^ KW[0][1]; + C2 = (Si[r2 & 255] & 255) ^ ((Si[(r1 >> 8) & 255] & 255) << 8) ^ ((Si[(r0 >> 16) & 255] & 255) << 16) + ^ (Si[(r3 >> 24) & 255] << 24) ^ KW[0][2]; + C3 = (Si[r3 & 255] & 255) ^ ((Si[(r2 >> 8) & 255] & 255) << 8) ^ ((Si[(r1 >> 16) & 255] & 255) << 16) + ^ (Si[(r0 >> 24) & 255] << 24) ^ KW[0][3]; + } + + public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + processBlock(src, srcoff, dst, dstoff); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/BlockCipher.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.cipher; + +/** + * BlockCipher. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public interface BlockCipher { + public void init(boolean forEncryption, byte[] key); + + public int getBlockSize(); + + public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/BlockCipherFactory.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.cipher; + +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; + +/** + * BlockCipherFactory. + * + * @author Christian Plattner + * @version $Id: BlockCipherFactory.java 86 2014-04-07 14:15:18Z dkocher@sudo.ch $ + */ +public class BlockCipherFactory { + private static final class CipherEntry { + String type; + int blocksize; + int keysize; + String cipherClass; + + public CipherEntry(String type, int blockSize, int keySize, String cipherClass) { + this.type = type; + this.blocksize = blockSize; + this.keysize = keySize; + this.cipherClass = cipherClass; + } + } + + private static final List<CipherEntry> ciphers = new ArrayList<CipherEntry>(); + + static { + // Higher priority (stronger) first + ciphers.add(new CipherEntry("aes256-ctr", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("aes192-ctr", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("aes128-ctr", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("blowfish-ctr", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); + ciphers.add(new CipherEntry("aes256-cbc", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("aes192-cbc", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("aes128-cbc", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("blowfish-cbc", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); + ciphers.add(new CipherEntry("3des-ctr", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); + ciphers.add(new CipherEntry("3des-cbc", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); + } + + public static String[] getDefaultCipherList() { + List<String> list = new ArrayList<String>(ciphers.size()); + + for (CipherEntry ce : ciphers) { + list.add(ce.type); + } + + return list.toArray(new String[ciphers.size()]); + } + + public static void checkCipherList(String[] cipherCandidates) { + for (String cipherCandidate : cipherCandidates) { + getEntry(cipherCandidate); + } + } + + // @SuppressWarnings("rawtypes") + public static BlockCipher createCipher(String type, boolean encrypt, byte[] key, byte[] iv) { + try { + CipherEntry ce = getEntry(type); + Class<?> cc = Class.forName(ce.cipherClass); + BlockCipher bc = (BlockCipher) cc.newInstance(); + + if (type.endsWith("-cbc")) { + bc.init(encrypt, key); + return new CBCMode(bc, iv, encrypt); + } + else if (type.endsWith("-ctr")) { + bc.init(true, key); + return new CTRMode(bc, iv, encrypt); + } + + throw new IllegalArgumentException("Cannot instantiate " + type); + } + catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Cannot instantiate " + type, e); + } + catch (InstantiationException e) { + throw new IllegalArgumentException("Cannot instantiate " + type, e); + } + catch (IllegalAccessException e) { + throw new IllegalArgumentException("Cannot instantiate " + type, e); + } + } + + private static CipherEntry getEntry(String type) { + for (CipherEntry ce : ciphers) { + if (ce.type.equals(type)) { + return ce; + } + } + + throw new IllegalArgumentException("Unkown algorithm " + type); + } + + public static int getBlockSize(String type) { + CipherEntry ce = getEntry(type); + return ce.blocksize; + } + + public static int getKeySize(String type) { + CipherEntry ce = getEntry(type); + return ce.keysize; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/BlowFish.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,376 @@ +package ch.ethz.ssh2.crypto.cipher; + +/* + This file was shamelessly taken from the Bouncy Castle Crypto package. + Their licence file states the following: + + Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle + (http://www.bouncycastle.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +/** + * A class that provides Blowfish key encryption operations, such as encoding + * data and generating keys. All the algorithms herein are from Applied + * Cryptography and implement a simplified cryptography interface. + * + * @author See comments in the source file + * @version 2.50, 03/15/10 + */ +public class BlowFish implements BlockCipher { + + private final static int[] KP = { 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, + 0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, + 0xB5470917, 0x9216D5D9, 0x8979FB1B + }, + + KS0 = { 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, 0x24A19947, + 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658, + 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918, + 0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, + 0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C, + 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60, + 0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, 0x6A51A0D2, + 0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176, + 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, 0x401A449F, + 0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6, + 0x409F60C4, 0x5E5C9EC2, 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C, + 0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, 0x45C8740F, 0xD20B5F39, + 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, 0x9E5C57BB, + 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, 0xBBCA58C8, + 0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, 0x9A53E479, 0xB6F84565, 0xD28E49BC, + 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB, + 0xF2122B64, 0x8888B812, 0x900DF01C, 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777, + 0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, + 0xD2ADA8D9, 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, 0x2464369B, + 0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9, + 0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, + 0x81E67400, 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A + }, + + KS1 = { 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, + 0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65, + 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6, + 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A, + 0x3CB574B2, 0x25837A58, 0xDC0921BD, 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC, + 0xC8B57634, 0x9AF3DDA7, 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, + 0x183EB331, 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, 0x7A584718, + 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908, + 0xDD433B37, 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55, 0x81AC77D6, + 0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6, + 0x5266C825, 0x2E4CC978, 0x9C10B36A, 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D, + 0x1939260F, 0x19C27960, 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883, 0xB17F37D1, + 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90, + 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA, + 0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099, 0x95F7997E, + 0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF, + 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA, + 0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A, + 0x3D816250, 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, 0x3372F092, + 0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E, + 0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484, 0xFDD56705, + 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 + }, + + KS2 = { 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, 0xD4082471, + 0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF, + 0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6, + 0xABCA0A9A, 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, 0x20FE9E35, + 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332, + 0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7, + 0xD096954B, 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, 0x07F9C9EE, + 0x41041F0F, 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60, + 0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, 0x3B240B62, + 0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60, + 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3, + 0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, 0x7B9479BF, + 0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659, + 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, 0xF0F7C086, + 0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, 0xB0804187, + 0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E, + 0x20B45770, 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, 0xE0A9DC09, + 0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, + 0x2868F169, 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, 0x11E69ED7, + 0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, 0x4B7C0188, + 0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, 0xD83D7CD3, + 0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 + }, + + KS3 = { 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, 0xD5118E9D, + 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79, + 0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, + 0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, 0xC72FEFD3, + 0xF752F7DA, 0x3F046F69, 0x77FA0A59, 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797, + 0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, + 0x5A88F54C, 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, 0xC3EB9E15, + 0x3C9057A2, 0x97271AEC, 0xA93A072A, 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5, + 0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, 0x4DE81751, 0x3830DC8E, 0x379D5862, + 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, + 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB, + 0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, 0x740E0D8D, 0xE75B1357, 0xF8721671, + 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1, + 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A, + 0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, + 0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532, + 0xE0D392DF, 0xD3A0342B, 0x8971F21E, 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E, + 0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5, + 0xF6FB2299, 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, 0xC9AA53FD, + 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3, + 0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, + 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 + }; + + // ==================================== + // Useful constants + // ==================================== + + private static final int ROUNDS = 16; + private static final int BLOCK_SIZE = 8; // bytes = 64 bits + private static final int SBOX_SK = 256; + private static final int P_SZ = ROUNDS + 2; + + private final int[] S0, S1, S2, S3; // the s-boxes + private final int[] P; // the p-array + + private boolean doEncrypt = false; + + private byte[] workingKey = null; + + public BlowFish() { + S0 = new int[SBOX_SK]; + S1 = new int[SBOX_SK]; + S2 = new int[SBOX_SK]; + S3 = new int[SBOX_SK]; + P = new int[P_SZ]; + } + + /** + * initialise a Blowfish cipher. + * + * @param encrypting + * whether or not we are for encryption. + * @param key + * the key required to set up the cipher. + * @exception IllegalArgumentException + * if the params argument is inappropriate. + */ + public void init(boolean encrypting, byte[] key) { + this.doEncrypt = encrypting; + this.workingKey = key; + setKey(this.workingKey); + } + + public String getAlgorithmName() { + return "Blowfish"; + } + + public final void transformBlock(byte[] in, int inOff, byte[] out, int outOff) { + if (workingKey == null) { + throw new IllegalStateException("Blowfish not initialised"); + } + + if (doEncrypt) { + encryptBlock(in, inOff, out, outOff); + } + else { + decryptBlock(in, inOff, out, outOff); + } + } + + public void reset() { + } + + public int getBlockSize() { + return BLOCK_SIZE; + } + + // ================================== + // Private Implementation + // ================================== + + private int F(int x) { + return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff]) ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]); + } + + /** + * apply the encryption cycle to each value pair in the table. + */ + private void processTable(int xl, int xr, int[] table) { + int size = table.length; + + for (int s = 0; s < size; s += 2) { + xl ^= P[0]; + + for (int i = 1; i < ROUNDS; i += 2) { + xr ^= F(xl) ^ P[i]; + xl ^= F(xr) ^ P[i + 1]; + } + + xr ^= P[ROUNDS + 1]; + table[s] = xr; + table[s + 1] = xl; + xr = xl; // end of cycle swap + xl = table[s]; + } + } + + private void setKey(byte[] key) { + /* + * - comments are from _Applied Crypto_, Schneier, p338 please be + * careful comparing the two, AC numbers the arrays from 1, the enclosed + * code from 0. + * + * (1) Initialise the S-boxes and the P-array, with a fixed string This + * string contains the hexadecimal digits of pi (3.141...) + */ + System.arraycopy(KS0, 0, S0, 0, SBOX_SK); + System.arraycopy(KS1, 0, S1, 0, SBOX_SK); + System.arraycopy(KS2, 0, S2, 0, SBOX_SK); + System.arraycopy(KS3, 0, S3, 0, SBOX_SK); + System.arraycopy(KP, 0, P, 0, P_SZ); + /* + * (2) Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with + * the second 32-bits of the key, and so on for all bits of the key (up + * to P[17]). Repeatedly cycle through the key bits until the entire + * P-array has been XOR-ed with the key bits + */ + int keyLength = key.length; + int keyIndex = 0; + + for (int i = 0; i < P_SZ; i++) { + // get the 32 bits of the key, in 4 * 8 bit chunks + int data = 0x0000000; + + for (int j = 0; j < 4; j++) { + // create a 32 bit block + data = (data << 8) | (key[keyIndex++] & 0xff); + + // wrap when we get to the end of the key + if (keyIndex >= keyLength) { + keyIndex = 0; + } + } + + // XOR the newly created 32 bit chunk onto the P-array + P[i] ^= data; + } + + /* + * (3) Encrypt the all-zero string with the Blowfish algorithm, using + * the subkeys described in (1) and (2) + * + * (4) Replace P1 and P2 with the output of step (3) + * + * (5) Encrypt the output of step(3) using the Blowfish algorithm, with + * the modified subkeys. + * + * (6) Replace P3 and P4 with the output of step (5) + * + * (7) Continue the process, replacing all elements of the P-array and + * then all four S-boxes in order, with the output of the continuously + * changing Blowfish algorithm + */ + processTable(0, 0, P); + processTable(P[P_SZ - 2], P[P_SZ - 1], S0); + processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1); + processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2); + processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3); + } + + /** + * Encrypt the given input starting at the given offset and place the result + * in the provided buffer starting at the given offset. The input will be an + * exact multiple of our blocksize. + */ + private void encryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) { + int xl = BytesTo32bits(src, srcIndex); + int xr = BytesTo32bits(src, srcIndex + 4); + xl ^= P[0]; + + for (int i = 1; i < ROUNDS; i += 2) { + xr ^= F(xl) ^ P[i]; + xl ^= F(xr) ^ P[i + 1]; + } + + xr ^= P[ROUNDS + 1]; + Bits32ToBytes(xr, dst, dstIndex); + Bits32ToBytes(xl, dst, dstIndex + 4); + } + + /** + * Decrypt the given input starting at the given offset and place the result + * in the provided buffer starting at the given offset. The input will be an + * exact multiple of our blocksize. + */ + private void decryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) { + int xl = BytesTo32bits(src, srcIndex); + int xr = BytesTo32bits(src, srcIndex + 4); + xl ^= P[ROUNDS + 1]; + + for (int i = ROUNDS; i > 0; i -= 2) { + xr ^= F(xl) ^ P[i]; + xl ^= F(xr) ^ P[i - 1]; + } + + xr ^= P[0]; + Bits32ToBytes(xr, dst, dstIndex); + Bits32ToBytes(xl, dst, dstIndex + 4); + } + + private int BytesTo32bits(byte[] b, int i) { + return ((b[i] & 0xff) << 24) | ((b[i + 1] & 0xff) << 16) | ((b[i + 2] & 0xff) << 8) | ((b[i + 3] & 0xff)); + } + + private void Bits32ToBytes(int in, byte[] b, int offset) { + b[offset + 3] = (byte) in; + b[offset + 2] = (byte)(in >> 8); + b[offset + 1] = (byte)(in >> 16); + b[offset] = (byte)(in >> 24); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/CBCMode.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.cipher; + +/** + * CBCMode. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class CBCMode implements BlockCipher { + BlockCipher tc; + int blockSize; + boolean doEncrypt; + + byte[] cbc_vector; + byte[] tmp_vector; + + public void init(boolean forEncryption, byte[] key) { + } + + public CBCMode(BlockCipher tc, byte[] iv, boolean doEncrypt) + throws IllegalArgumentException { + this.tc = tc; + this.blockSize = tc.getBlockSize(); + this.doEncrypt = doEncrypt; + + if (this.blockSize != iv.length) + throw new IllegalArgumentException("IV must be " + blockSize + + " bytes long! (currently " + iv.length + ")"); + + this.cbc_vector = new byte[blockSize]; + this.tmp_vector = new byte[blockSize]; + System.arraycopy(iv, 0, cbc_vector, 0, blockSize); + } + + public int getBlockSize() { + return blockSize; + } + + private void encryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + for (int i = 0; i < blockSize; i++) + cbc_vector[i] ^= src[srcoff + i]; + + tc.transformBlock(cbc_vector, 0, dst, dstoff); + System.arraycopy(dst, dstoff, cbc_vector, 0, blockSize); + } + + private void decryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + /* Assume the worst, src and dst are overlapping... */ + System.arraycopy(src, srcoff, tmp_vector, 0, blockSize); + tc.transformBlock(src, srcoff, dst, dstoff); + + for (int i = 0; i < blockSize; i++) + dst[dstoff + i] ^= cbc_vector[i]; + + /* ...that is why we need a tmp buffer. */ + byte[] swap = cbc_vector; + cbc_vector = tmp_vector; + tmp_vector = swap; + } + + public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + if (doEncrypt) + encryptBlock(src, srcoff, dst, dstoff); + else + decryptBlock(src, srcoff, dst, dstoff); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/CTRMode.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.cipher; + +/** + * This is CTR mode as described in draft-ietf-secsh-newmodes-XY.txt + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class CTRMode implements BlockCipher { + byte[] X; + byte[] Xenc; + + BlockCipher bc; + int blockSize; + boolean doEncrypt; + + int count = 0; + + public void init(boolean forEncryption, byte[] key) { + } + + public CTRMode(BlockCipher tc, byte[] iv, boolean doEnc) throws IllegalArgumentException { + bc = tc; + blockSize = bc.getBlockSize(); + doEncrypt = doEnc; + + if (blockSize != iv.length) + throw new IllegalArgumentException("IV must be " + blockSize + " bytes long! (currently " + iv.length + ")"); + + X = new byte[blockSize]; + Xenc = new byte[blockSize]; + System.arraycopy(iv, 0, X, 0, blockSize); + } + + public final int getBlockSize() { + return blockSize; + } + + public final void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + bc.transformBlock(X, 0, Xenc, 0); + + for (int i = 0; i < blockSize; i++) { + dst[dstoff + i] = (byte)(src[srcoff + i] ^ Xenc[i]); + } + + for (int i = (blockSize - 1); i >= 0; i--) { + X[i]++; + + if (X[i] != 0) + break; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.cipher; + +import java.io.IOException; +import java.io.InputStream; + +/** + * CipherInputStream. + * + * @author Christian Plattner + * @version $Id: CipherInputStream.java 11 2011-05-27 14:14:06Z dkocher@sudo.ch $ + */ +public class CipherInputStream { + BlockCipher currentCipher; + InputStream bi; + byte[] buffer; + byte[] enc; + int blockSize; + int pos; + + /* + * We cannot use java.io.BufferedInputStream, since that is not available in + * J2ME. Everything could be improved alot here. + */ + + private static final int BUFF_SIZE = 8192; + byte[] input_buffer = new byte[BUFF_SIZE]; + int input_buffer_pos = 0; + int input_buffer_size = 0; + + public CipherInputStream(BlockCipher tc, InputStream bi) { + this.bi = bi; + changeCipher(tc); + } + + private int fill_buffer() throws IOException { + input_buffer_pos = 0; + input_buffer_size = 0; + input_buffer_size = bi.read(input_buffer, 0, BUFF_SIZE); + return input_buffer_size; + } + + private int internal_read(byte[] b, int off, int len) throws IOException { + if (input_buffer_size < 0) { + return -1; + } + + if (input_buffer_pos >= input_buffer_size) { + if (fill_buffer() <= 0) { + return -1; + } + } + + int avail = input_buffer_size - input_buffer_pos; + int thiscopy = (len > avail) ? avail : len; + System.arraycopy(input_buffer, input_buffer_pos, b, off, thiscopy); + input_buffer_pos += thiscopy; + return thiscopy; + } + + public void changeCipher(BlockCipher bc) { + this.currentCipher = bc; + blockSize = bc.getBlockSize(); + buffer = new byte[blockSize]; + enc = new byte[blockSize]; + pos = blockSize; + } + + private void getBlock() throws IOException { + int n = 0; + + while (n < blockSize) { + int len = internal_read(enc, n, blockSize - n); + + if (len < 0) { + throw new IOException("Cannot read full block, EOF reached."); + } + + n += len; + } + + try { + currentCipher.transformBlock(enc, 0, buffer, 0); + } + catch (Exception e) { + throw new IOException("Error while decrypting block."); + } + + pos = 0; + } + + public int read(byte[] dst) throws IOException { + return read(dst, 0, dst.length); + } + + public int read(byte[] dst, int off, int len) throws IOException { + int count = 0; + + while (len > 0) { + if (pos >= blockSize) { + getBlock(); + } + + int avail = blockSize - pos; + int copy = Math.min(avail, len); + System.arraycopy(buffer, pos, dst, off, copy); + pos += copy; + off += copy; + len -= copy; + count += copy; + } + + return count; + } + + public int read() throws IOException { + if (pos >= blockSize) { + getBlock(); + } + + return buffer[pos++] & 0xff; + } + + public int readPlain(byte[] b, int off, int len) throws IOException { + if (pos != blockSize) { + throw new IOException("Cannot read plain since crypto buffer is not aligned."); + } + + int n = 0; + + while (n < len) { + int cnt = internal_read(b, off + n, len - n); + + if (cnt < 0) { + throw new IOException("Cannot fill buffer, EOF reached."); + } + + n += cnt; + } + + return n; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/CipherOutputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.cipher; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * CipherOutputStream. + * + * @author Christian Plattner + * @version $Id: CipherOutputStream.java 85 2014-04-07 14:05:09Z dkocher@sudo.ch $ + */ +public class CipherOutputStream { + BlockCipher currentCipher; + OutputStream bo; + byte[] buffer; + byte[] enc; + int blockSize; + int pos; + + /* + * We cannot use java.io.BufferedOutputStream, since that is not available + * in J2ME. Everything could be improved here alot. + */ + + private static final int BUFF_SIZE = 8192; + byte[] out_buffer = new byte[BUFF_SIZE]; + int out_buffer_pos = 0; + + public CipherOutputStream(BlockCipher tc, OutputStream bo) { + this.bo = bo; + changeCipher(tc); + } + + private void internal_write(byte[] src, int off, int len) throws IOException { + while (len > 0) { + int space = BUFF_SIZE - out_buffer_pos; + int copy = (len > space) ? space : len; + System.arraycopy(src, off, out_buffer, out_buffer_pos, copy); + off += copy; + out_buffer_pos += copy; + len -= copy; + + if (out_buffer_pos >= BUFF_SIZE) { + bo.write(out_buffer, 0, BUFF_SIZE); + out_buffer_pos = 0; + } + } + } + + private void internal_write(int b) throws IOException { + out_buffer[out_buffer_pos++] = (byte) b; + + if (out_buffer_pos >= BUFF_SIZE) { + bo.write(out_buffer, 0, BUFF_SIZE); + out_buffer_pos = 0; + } + } + + public void flush() throws IOException { + if (pos != 0) { + throw new IOException("FATAL: cannot flush since crypto buffer is not aligned."); + } + + if (out_buffer_pos > 0) { + bo.write(out_buffer, 0, out_buffer_pos); + out_buffer_pos = 0; + } + + bo.flush(); + } + + public void changeCipher(BlockCipher bc) { + this.currentCipher = bc; + blockSize = bc.getBlockSize(); + buffer = new byte[blockSize]; + enc = new byte[blockSize]; + pos = 0; + } + + private void writeBlock() throws IOException { + try { + currentCipher.transformBlock(buffer, 0, enc, 0); + } + catch (Exception e) { + throw new IOException("Error while decrypting block.", e); + } + + internal_write(enc, 0, blockSize); + pos = 0; + } + + public void write(byte[] src, int off, int len) throws IOException { + while (len > 0) { + int avail = blockSize - pos; + int copy = Math.min(avail, len); + System.arraycopy(src, off, buffer, pos, copy); + pos += copy; + off += copy; + len -= copy; + + if (pos >= blockSize) { + writeBlock(); + } + } + } + + public void write(int b) throws IOException { + buffer[pos++] = (byte) b; + + if (pos >= blockSize) { + writeBlock(); + } + } + + public void writePlain(int b) throws IOException { + if (pos != 0) { + throw new IOException("Cannot write plain since crypto buffer is not aligned."); + } + + internal_write(b); + } + + public void writePlain(byte[] b, int off, int len) throws IOException { + if (pos != 0) { + throw new IOException("Cannot write plain since crypto buffer is not aligned."); + } + + internal_write(b, off, len); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/DES.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,352 @@ +package ch.ethz.ssh2.crypto.cipher; + +/* + This file is based on the 3DES implementation from the Bouncy Castle Crypto package. + Their licence file states the following: + + Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle + (http://www.bouncycastle.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +/** + * DES. + * + * @author See comments in the source file + * @version 2.50, 03/15/10 + * + */ +public class DES implements BlockCipher { + private int[] workingKey = null; + + /** + * standard constructor. + */ + public DES() { + } + + /** + * initialise a DES cipher. + * + * @param encrypting + * whether or not we are for encryption. + * @param key + * the parameters required to set up the cipher. + * @exception IllegalArgumentException + * if the params argument is inappropriate. + */ + public void init(boolean encrypting, byte[] key) { + this.workingKey = generateWorkingKey(encrypting, key, 0); + } + + public String getAlgorithmName() { + return "DES"; + } + + public int getBlockSize() { + return 8; + } + + public void transformBlock(byte[] in, int inOff, byte[] out, int outOff) { + if (workingKey == null) { + throw new IllegalStateException("DES engine not initialised!"); + } + + desFunc(workingKey, in, inOff, out, outOff); + } + + public void reset() { + } + + /** + * what follows is mainly taken from "Applied Cryptography", by Bruce + * Schneier, however it also bears great resemblance to Richard + * Outerbridge's D3DES... + */ + + static short[] Df_Key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, + 0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 + }; + + static short[] bytebit = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; + + static int[] bigbyte = { 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000, + 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 + }; + + /* + * Use the key schedule specified in the Standard (ANSI X3.92-1981). + */ + + static byte[] pc1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, + 4, 27, 19, 11, 3 + }; + + static byte[] totrot = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 }; + + static byte[] pc2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, + 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 + }; + + static int[] SP1 = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, + 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, + 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, + 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, + 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, + 0x00010400, 0x00000000, 0x01010004 + }; + + static int[] SP2 = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, + 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, + 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, + 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, + 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, + 0x80100020, 0x80108020, 0x00108000 + }; + + static int[] SP3 = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, + 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, + 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, + 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, + 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, + 0x00000008, 0x08020008, 0x00020200 + }; + + static int[] SP4 = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, + 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, + 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, + 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, + 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, + 0x00800000, 0x00002000, 0x00802080 + }; + + static int[] SP5 = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, + 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, + 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, + 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, + 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, + 0x40080000, 0x02080100, 0x40000100 + }; + + static int[] SP6 = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, + 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, + 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, + 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, + 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, + 0x20000000, 0x00400010, 0x20004010 + }; + + static int[] SP7 = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, + 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, + 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, + 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, + 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, + 0x04000800, 0x00000800, 0x00200002 + }; + + static int[] SP8 = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, + 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, + 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, + 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, + 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, + 0x00040040, 0x10000000, 0x10041000 + }; + + /** + * generate an integer based working key based on our secret key and what we + * processing we are planning to do. + * + * Acknowledgements for this routine go to James Gillogly & Phil Karn. + * (whoever, and wherever they are!). + */ + protected int[] generateWorkingKey(boolean encrypting, byte[] key, int off) { + int[] newKey = new int[32]; + boolean[] pc1m = new boolean[56], pcr = new boolean[56]; + + for (int j = 0; j < 56; j++) { + int l = pc1[j]; + pc1m[j] = ((key[off + (l >>> 3)] & bytebit[l & 07]) != 0); + } + + for (int i = 0; i < 16; i++) { + int l, m, n; + + if (encrypting) { + m = i << 1; + } + else { + m = (15 - i) << 1; + } + + n = m + 1; + newKey[m] = newKey[n] = 0; + + for (int j = 0; j < 28; j++) { + l = j + totrot[i]; + + if (l < 28) { + pcr[j] = pc1m[l]; + } + else { + pcr[j] = pc1m[l - 28]; + } + } + + for (int j = 28; j < 56; j++) { + l = j + totrot[i]; + + if (l < 56) { + pcr[j] = pc1m[l]; + } + else { + pcr[j] = pc1m[l - 28]; + } + } + + for (int j = 0; j < 24; j++) { + if (pcr[pc2[j]]) { + newKey[m] |= bigbyte[j]; + } + + if (pcr[pc2[j + 24]]) { + newKey[n] |= bigbyte[j]; + } + } + } + + // + // store the processed key + // + for (int i = 0; i != 32; i += 2) { + int i1, i2; + i1 = newKey[i]; + i2 = newKey[i + 1]; + newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10) | ((i2 & 0x00fc0000) >>> 10) + | ((i2 & 0x00000fc0) >>> 6); + newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16) | ((i2 & 0x0003f000) >>> 4) + | (i2 & 0x0000003f); + } + + return newKey; + } + + /** + * the DES engine. + */ + protected void desFunc(int[] wKey, byte[] in, int inOff, byte[] out, int outOff) { + int work, right, left; + left = (in[inOff + 0] & 0xff) << 24; + left |= (in[inOff + 1] & 0xff) << 16; + left |= (in[inOff + 2] & 0xff) << 8; + left |= (in[inOff + 3] & 0xff); + right = (in[inOff + 4] & 0xff) << 24; + right |= (in[inOff + 5] & 0xff) << 16; + right |= (in[inOff + 6] & 0xff) << 8; + right |= (in[inOff + 7] & 0xff); + work = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= (work << 4); + work = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= work; + left ^= (work << 16); + work = ((right >>> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= work; + right ^= (work << 8); + right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff; + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff; + + for (int round = 0; round < 8; round++) { + int fval; + work = (right << 28) | (right >>> 4); + work ^= wKey[round * 4 + 0]; + fval = SP7[work & 0x3f]; + fval |= SP5[(work >>> 8) & 0x3f]; + fval |= SP3[(work >>> 16) & 0x3f]; + fval |= SP1[(work >>> 24) & 0x3f]; + work = right ^ wKey[round * 4 + 1]; + fval |= SP8[work & 0x3f]; + fval |= SP6[(work >>> 8) & 0x3f]; + fval |= SP4[(work >>> 16) & 0x3f]; + fval |= SP2[(work >>> 24) & 0x3f]; + left ^= fval; + work = (left << 28) | (left >>> 4); + work ^= wKey[round * 4 + 2]; + fval = SP7[work & 0x3f]; + fval |= SP5[(work >>> 8) & 0x3f]; + fval |= SP3[(work >>> 16) & 0x3f]; + fval |= SP1[(work >>> 24) & 0x3f]; + work = left ^ wKey[round * 4 + 3]; + fval |= SP8[work & 0x3f]; + fval |= SP6[(work >>> 8) & 0x3f]; + fval |= SP4[(work >>> 16) & 0x3f]; + fval |= SP2[(work >>> 24) & 0x3f]; + right ^= fval; + } + + right = (right << 31) | (right >>> 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left << 31) | (left >>> 1); + work = ((left >>> 8) ^ right) & 0x00ff00ff; + right ^= work; + left ^= (work << 8); + work = ((left >>> 2) ^ right) & 0x33333333; + right ^= work; + left ^= (work << 2); + work = ((right >>> 16) ^ left) & 0x0000ffff; + left ^= work; + right ^= (work << 16); + work = ((right >>> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= (work << 4); + out[outOff + 0] = (byte)((right >>> 24) & 0xff); + out[outOff + 1] = (byte)((right >>> 16) & 0xff); + out[outOff + 2] = (byte)((right >>> 8) & 0xff); + out[outOff + 3] = (byte)(right & 0xff); + out[outOff + 4] = (byte)((left >>> 24) & 0xff); + out[outOff + 5] = (byte)((left >>> 16) & 0xff); + out[outOff + 6] = (byte)((left >>> 8) & 0xff); + out[outOff + 7] = (byte)(left & 0xff); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/DESede.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,98 @@ +package ch.ethz.ssh2.crypto.cipher; + +/* + This file was shamelessly taken (and modified) from the Bouncy Castle Crypto package. + Their licence file states the following: + + Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle + (http://www.bouncycastle.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +/** + * DESede. + * + * @author See comments in the source file + * @version 2.50, 03/15/10 + * + */ +public class DESede extends DES { + private int[] key1 = null; + private int[] key2 = null; + private int[] key3 = null; + + private boolean encrypt; + + /** + * standard constructor. + */ + public DESede() { + } + + /** + * initialise a DES cipher. + * + * @param encrypting + * whether or not we are for encryption. + * @param key + * the parameters required to set up the cipher. + * @exception IllegalArgumentException + * if the params argument is inappropriate. + */ + @Override + public void init(boolean encrypting, byte[] key) { + key1 = generateWorkingKey(encrypting, key, 0); + key2 = generateWorkingKey(!encrypting, key, 8); + key3 = generateWorkingKey(encrypting, key, 16); + encrypt = encrypting; + } + + @Override + public String getAlgorithmName() { + return "DESede"; + } + + @Override + public int getBlockSize() { + return 8; + } + + @Override + public void transformBlock(byte[] in, int inOff, byte[] out, int outOff) { + if (key1 == null) { + throw new IllegalStateException("DESede engine not initialised!"); + } + + if (encrypt) { + desFunc(key1, in, inOff, out, outOff); + desFunc(key2, out, outOff, out, outOff); + desFunc(key3, out, outOff, out, outOff); + } + else { + desFunc(key3, in, inOff, out, outOff); + desFunc(key2, out, outOff, out, outOff); + desFunc(key1, out, outOff, out, outOff); + } + } + + @Override + public void reset() { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/NullCipher.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.cipher; + +/** + * NullCipher. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class NullCipher implements BlockCipher { + private int blockSize = 8; + + public NullCipher() { + } + + public NullCipher(int blockSize) { + this.blockSize = blockSize; + } + + public void init(boolean forEncryption, byte[] key) { + } + + public int getBlockSize() { + return blockSize; + } + + public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + System.arraycopy(src, srcoff, dst, dstoff, blockSize); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/dh/DhExchange.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,147 @@ +/** + * + */ +package ch.ethz.ssh2.crypto.dh; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; + +import javax.crypto.KeyAgreement; +import javax.crypto.interfaces.DHPrivateKey; +import javax.crypto.interfaces.DHPublicKey; +import javax.crypto.spec.DHParameterSpec; +import javax.crypto.spec.DHPublicKeySpec; + +/** + * @author kenny + * + */ +public class DhExchange extends GenericDhExchange { + + /* Given by the standard */ + + private static final BigInteger P1 = new BigInteger( + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" + + "FFFFFFFFFFFFFFFF", 16); + + private static final BigInteger P14 = new BigInteger( + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16); + + private static final BigInteger G = BigInteger.valueOf(2); + + /* Client public and private */ + + private DHPrivateKey clientPrivate; + private DHPublicKey clientPublic; + + /* Server public */ + + private DHPublicKey serverPublic; + private byte[] f; + + @Override + public void init(String name) throws IOException { + final DHParameterSpec spec; + + if ("diffie-hellman-group1-sha1".equals(name)) { + spec = new DHParameterSpec(P1, G); + } + else if ("diffie-hellman-group14-sha1".equals(name)) { + spec = new DHParameterSpec(P14, G); + } + else { + throw new IllegalArgumentException("Unknown DH group " + name); + } + + try { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH"); + kpg.initialize(spec); + KeyPair pair = kpg.generateKeyPair(); + clientPrivate = (DHPrivateKey) pair.getPrivate(); + clientPublic = (DHPublicKey) pair.getPublic(); + } + catch (NoSuchAlgorithmException e) { + throw(IOException) new IOException("No DH keypair generator").initCause(e); + } + catch (InvalidAlgorithmParameterException e) { + throw(IOException) new IOException("Invalid DH parameters").initCause(e); + } + } + + @Override + public byte[] getE() { + if (clientPublic == null) + throw new IllegalStateException("DhExchange not initialized!"); + + return clientPublic.getY().toByteArray(); + } + + @Override + protected byte[] getServerE() { + if (serverPublic == null) + throw new IllegalStateException("DhExchange not initialized!"); + + return serverPublic.getY().toByteArray(); + } + + @Override + public byte[] getF() { + return f; + } + + @Override + public void setF(byte[] f) throws IOException { + if (clientPublic == null) + throw new IllegalStateException("DhExchange not initialized!"); + + final KeyAgreement ka; + + try { + KeyFactory kf = KeyFactory.getInstance("DH"); + DHParameterSpec params = clientPublic.getParams(); + this.f = f; + this.serverPublic = (DHPublicKey) kf.generatePublic(new DHPublicKeySpec( + new BigInteger(f), params.getP(), params.getG())); + ka = KeyAgreement.getInstance("DH"); + ka.init(clientPrivate); + ka.doPhase(serverPublic, true); + } + catch (NoSuchAlgorithmException e) { + throw(IOException) new IOException("No DH key agreement method").initCause(e); + } + catch (InvalidKeyException e) { + throw(IOException) new IOException("Invalid DH key").initCause(e); + } + catch (InvalidKeySpecException e) { + throw(IOException) new IOException("Invalid DH key").initCause(e); + } + + sharedSecret = new BigInteger(ka.generateSecret()); + } + + @Override + public String getHashAlgo() { + return "SHA1"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/dh/DhGroupExchange.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,108 @@ + +package ch.ethz.ssh2.crypto.dh; + +import java.math.BigInteger; +import java.security.SecureRandom; +import java.io.IOException; + +import ch.ethz.ssh2.DHGexParameters; +import ch.ethz.ssh2.crypto.digest.HashForSSH2Types; + + +/** + * DhGroupExchange. + * + * @author Christian Plattner, plattner@trilead.com + * @version $Id: DhGroupExchange.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $ + */ +public class DhGroupExchange { + /* Given by the standard */ + + private BigInteger p; + private BigInteger g; + + /* Client public and private */ + + private BigInteger e; + private BigInteger x; + + /* Server public */ + + private BigInteger f; + + /* Shared secret */ + + private BigInteger k; + + public DhGroupExchange(BigInteger p, BigInteger g) { + this.p = p; + this.g = g; + } + + public void init(SecureRandom rnd) { + k = null; + x = new BigInteger(p.bitLength() - 1, rnd); + e = g.modPow(x, p); + } + + /** + * @return Returns the e. + */ + public BigInteger getE() { + if (e == null) + throw new IllegalStateException("Not initialized!"); + + return e; + } + + /** + * @return Returns the shared secret k. + */ + public BigInteger getK() { + if (k == null) + throw new IllegalStateException("Shared secret not yet known, need f first!"); + + return k; + } + + /** + * Sets f and calculates the shared secret. + */ + public void setF(BigInteger f) { + if (e == null) + throw new IllegalStateException("Not initialized!"); + + BigInteger zero = BigInteger.valueOf(0); + + if (zero.compareTo(f) >= 0 || p.compareTo(f) <= 0) + throw new IllegalArgumentException("Invalid f specified!"); + + this.f = f; + this.k = f.modPow(x, p); + } + + public byte[] calculateH(String hashAlgo, byte[] clientversion, byte[] serverversion, + byte[] clientKexPayload, byte[] serverKexPayload, byte[] hostKey, DHGexParameters para) throws IOException { + HashForSSH2Types hash = new HashForSSH2Types(hashAlgo); + hash.updateByteString(clientversion); + hash.updateByteString(serverversion); + hash.updateByteString(clientKexPayload); + hash.updateByteString(serverKexPayload); + hash.updateByteString(hostKey); + + if (para.getMin_group_len() > 0) + hash.updateUINT32(para.getMin_group_len()); + + hash.updateUINT32(para.getPref_group_len()); + + if (para.getMax_group_len() > 0) + hash.updateUINT32(para.getMax_group_len()); + + hash.updateBigInt(p); + hash.updateBigInt(g); + hash.updateBigInt(e); + hash.updateBigInt(f); + hash.updateBigInt(k); + return hash.getDigest(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/dh/EcDhExchange.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,127 @@ +/** + * + */ +package ch.ethz.ssh2.crypto.dh; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; + +import javax.crypto.KeyAgreement; + +import ch.ethz.ssh2.signature.ECDSASHA2Verify; + +/** + * @author kenny + * + */ +public class EcDhExchange extends GenericDhExchange { + + /* Client public and private */ + + private ECPrivateKey clientPrivate; + private ECPublicKey clientPublic; + + /* Server public */ + + private ECPublicKey serverPublic; + private byte[] f; + + @Override + public void init(String name) throws IOException { + final ECParameterSpec spec; + + if ("ecdh-sha2-nistp256".equals(name)) { + spec = ECDSASHA2Verify.EllipticCurves.nistp256; + } + else if ("ecdh-sha2-nistp384".equals(name)) { + spec = ECDSASHA2Verify.EllipticCurves.nistp384; + } + else if ("ecdh-sha2-nistp521".equals(name)) { + spec = ECDSASHA2Verify.EllipticCurves.nistp521; + } + else { + throw new IllegalArgumentException("Unknown EC curve " + name); + } + + KeyPairGenerator kpg; + + try { + kpg = KeyPairGenerator.getInstance("EC"); + kpg.initialize(spec); + KeyPair pair = kpg.generateKeyPair(); + clientPrivate = (ECPrivateKey) pair.getPrivate(); + clientPublic = (ECPublicKey) pair.getPublic(); + } + catch (NoSuchAlgorithmException e) { + throw(IOException) new IOException("No DH keypair generator").initCause(e); + } + catch (InvalidAlgorithmParameterException e) { + throw(IOException) new IOException("Invalid DH parameters").initCause(e); + } + } + + @Override + public byte[] getE() { + return ECDSASHA2Verify.encodeECPoint(clientPublic.getW(), clientPublic.getParams() + .getCurve()); + } + + @Override + protected byte[] getServerE() { + return ECDSASHA2Verify.encodeECPoint(serverPublic.getW(), serverPublic.getParams() + .getCurve()); + } + + @Override + public byte[] getF() { + return f; + } + + @Override + public void setF(byte[] f) throws IOException { + if (clientPublic == null) + throw new IllegalStateException("DhDsaExchange not initialized!"); + + final KeyAgreement ka; + + try { + KeyFactory kf = KeyFactory.getInstance("EC"); + ECParameterSpec params = clientPublic.getParams(); + ECPoint serverPoint = ECDSASHA2Verify.decodeECPoint(f, params.getCurve()); + this.f = f; + this.serverPublic = (ECPublicKey) kf.generatePublic(new ECPublicKeySpec(serverPoint, + params)); + ka = KeyAgreement.getInstance("ECDH"); + ka.init(clientPrivate); + ka.doPhase(serverPublic, true); + } + catch (NoSuchAlgorithmException e) { + throw(IOException) new IOException("No ECDH key agreement method").initCause(e); + } + catch (InvalidKeyException e) { + throw(IOException) new IOException("Invalid ECDH key").initCause(e); + } + catch (InvalidKeySpecException e) { + throw(IOException) new IOException("Invalid ECDH key").initCause(e); + } + + sharedSecret = new BigInteger(ka.generateSecret()); + } + + @Override + public String getHashAlgo() { + return ECDSASHA2Verify.getDigestAlgorithmForParams(clientPublic.getParams()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/dh/GenericDhExchange.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,94 @@ + +package ch.ethz.ssh2.crypto.dh; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; + +import ch.ethz.ssh2.crypto.digest.HashForSSH2Types; +import ch.ethz.ssh2.log.Logger; + + +/** + * DhExchange. + * + * @author Christian Plattner, plattner@trilead.com + * @version $Id: DhExchange.java,v 1.2 2008/04/01 12:38:09 cplattne Exp $ + */ +public abstract class GenericDhExchange { + private static final Logger log = Logger.getLogger(GenericDhExchange.class); + + /* Shared secret */ + + BigInteger sharedSecret; + + protected GenericDhExchange() { + } + + public static GenericDhExchange getInstance(String algo) { + if (algo.startsWith("ecdh-sha2-")) { + return new EcDhExchange(); + } + else { + return new DhExchange(); + } + } + + public abstract void init(String name) throws IOException; + + /** + * @return Returns the e (public value) + * @throws IllegalStateException + */ + public abstract byte[] getE(); + + public void setE(BigInteger e) throws IOException { + throw new IOException(); + } + + /** + * @return Returns the server's e (public value) + * @throws IllegalStateException + */ + protected abstract byte[] getServerE(); + + /** + * @return Returns the shared secret k. + * @throws IllegalStateException + */ + public BigInteger getK() { + if (sharedSecret == null) + throw new IllegalStateException("Shared secret not yet known, need f first!"); + + return sharedSecret; + } + + /** + * @param f + */ + public void setF(BigInteger f) throws IOException { + setF(f.toByteArray()); + } + + public abstract byte[] getF(); + + public abstract void setF(byte[] f) throws IOException; + + public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload, + byte[] serverKexPayload, byte[] hostKey) throws UnsupportedEncodingException, IOException { + HashForSSH2Types hash = new HashForSSH2Types(getHashAlgo()); + log.debug("Client: '" + new String(clientversion, "ISO-8859-1") + "'"); + log.debug("Server: '" + new String(serverversion, "ISO-8859-1") + "'"); + hash.updateByteString(clientversion); + hash.updateByteString(serverversion); + hash.updateByteString(clientKexPayload); + hash.updateByteString(serverKexPayload); + hash.updateByteString(hostKey); + hash.updateByteString(getE()); + hash.updateByteString(getServerE()); + hash.updateBigInt(sharedSecret); + return hash.getDigest(); + } + + public abstract String getHashAlgo(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/digest/Digest.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.digest; + +import java.security.DigestException; + +/** + * Digest. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public interface Digest { + public int getDigestLength(); + + public void update(byte b); + + public void update(byte[] b); + + public void update(byte b[], int off, int len); + + public void reset(); + + public void digest(byte[] out) throws DigestException; + + public void digest(byte[] out, int off) throws DigestException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/digest/HMAC.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.digest; + +import java.security.DigestException; + +/** + * HMAC. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class HMAC implements Digest { + Digest md; + byte[] k_xor_ipad; + byte[] k_xor_opad; + + byte[] tmp; + + int size; + + public HMAC(Digest md, byte[] key, int size) throws DigestException { + this.md = md; + this.size = size; + tmp = new byte[md.getDigestLength()]; + final int BLOCKSIZE = 64; + k_xor_ipad = new byte[BLOCKSIZE]; + k_xor_opad = new byte[BLOCKSIZE]; + + if (key.length > BLOCKSIZE) { + md.reset(); + md.update(key); + md.digest(tmp); + key = tmp; + } + + System.arraycopy(key, 0, k_xor_ipad, 0, key.length); + System.arraycopy(key, 0, k_xor_opad, 0, key.length); + + for (int i = 0; i < BLOCKSIZE; i++) { + k_xor_ipad[i] ^= 0x36; + k_xor_opad[i] ^= 0x5C; + } + + md.update(k_xor_ipad); + } + + public final int getDigestLength() { + return size; + } + + public final void update(byte b) { + md.update(b); + } + + public final void update(byte[] b) { + md.update(b); + } + + public final void update(byte[] b, int off, int len) { + md.update(b, off, len); + } + + public final void reset() { + md.reset(); + md.update(k_xor_ipad); + } + + public final void digest(byte[] out) throws DigestException { + digest(out, 0); + } + + public final void digest(byte[] out, int off) throws DigestException { + md.digest(tmp); + md.update(k_xor_opad); + md.update(tmp); + md.digest(tmp); + System.arraycopy(tmp, 0, out, off, size); + md.update(k_xor_ipad); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/digest/HashForSSH2Types.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.digest; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.DigestException; + +/** + * HashForSSH2Types. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class HashForSSH2Types { + Digest md; + + public HashForSSH2Types(Digest md) { + this.md = md; + } + + public HashForSSH2Types(String type) { + if (type.equals("SHA1")) { + md = new SHA1(); + } + else if (type.equals("SHA2")) { + md = new SHA256(); + } + else if (type.equals("MD5")) { + md = new MD5(); + } + else { + throw new IllegalArgumentException(String.format("Unknown algorithm %s", type)); + } + } + + public void updateByte(byte b) { + md.update(b); + } + + public void updateBytes(byte[] b) { + md.update(b); + } + + public void updateUINT32(int v) { + md.update((byte)(v >> 24)); + md.update((byte)(v >> 16)); + md.update((byte)(v >> 8)); + md.update((byte)(v)); + } + + public void updateByteString(byte[] b) { + updateUINT32(b.length); + updateBytes(b); + } + + public void updateBigInt(BigInteger b) { + updateByteString(b.toByteArray()); + } + + public void reset() { + md.reset(); + } + + public int getDigestLength() { + return md.getDigestLength(); + } + + public byte[] getDigest() throws IOException { + byte[] tmp = new byte[md.getDigestLength()]; + getDigest(tmp); + return tmp; + } + + public void getDigest(byte[] out) throws IOException { + try { + getDigest(out, 0); + } + catch (DigestException e) { + throw new IOException(e); + } + } + + public void getDigest(byte[] out, int off) throws DigestException { + md.digest(out, off); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/digest/MAC.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.digest; + +import java.io.IOException; +import java.security.DigestException; + +/** + * MAC. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class MAC { + private Digest mac; + private int size; + + public static String[] getMacList() { + // Higher priority (stronger) first. Added SHA-2 algorithms as in RFC 6668 + return new String[] { + // "hmac-sha2-512", // fails interop w/ centos6 + "hmac-sha2-256", + "hmac-sha1", + "hmac-sha1-96", + "hmac-md5", + "hmac-md5-96" + }; + } + + public static void checkMacList(final String[] macs) { + for (String m : macs) { + getKeyLen(m); + } + } + + public static int getKeyLen(final String type) { + if (type.equals("hmac-sha1")) { + return 20; + } + + if (type.equals("hmac-sha1-96")) { + return 20; + } + + if (type.equals("hmac-md5")) { + return 16; + } + + if (type.equals("hmac-md5-96")) { + return 16; + } + + if (type.equals("hmac-sha2-256")) { + return 32; + } + + if (type.equals("hmac-sha2-512")) { + return 64; + } + + throw new IllegalArgumentException(String.format("Unknown algorithm %s", type)); + } + + public MAC(final String type, final byte[] key) throws DigestException { + if (type.equals("hmac-sha1")) { + mac = new HMAC(new SHA1(), key, 20); + } + else if (type.equals("hmac-sha1-96")) { + mac = new HMAC(new SHA1(), key, 12); + } + else if (type.equals("hmac-md5")) { + mac = new HMAC(new MD5(), key, 16); + } + else if (type.equals("hmac-md5-96")) { + mac = new HMAC(new MD5(), key, 12); + } + else if (type.equals("hmac-sha2-256")) { + mac = new HMAC(new SHA256(), key, 32); + } + else if (type.equals("hmac-sha2-512")) { + mac = new HMAC(new SHA512(), key, 64); + } + else { + throw new IllegalArgumentException(String.format("Unknown algorithm %s", type)); + } + + size = mac.getDigestLength(); + } + + public final void initMac(final int seq) { + mac.reset(); + mac.update((byte)(seq >> 24)); + mac.update((byte)(seq >> 16)); + mac.update((byte)(seq >> 8)); + mac.update((byte)(seq)); + } + + public final void update(byte[] packetdata, int off, int len) { + mac.update(packetdata, off, len); + } + + public final void getMac(byte[] out, int off) throws IOException { + try { + mac.digest(out, off); + } + catch (DigestException e) { + throw new IOException(e); + } + } + + public final int size() { + return size; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/digest/MD5.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.digest; + +import java.security.DigestException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * @version $Id: MD5.java 154 2014-04-28 11:45:02Z dkocher@sudo.ch $ + */ +public final class MD5 implements Digest { + + private MessageDigest md; + + public MD5() { + try { + md = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e); + } + } + + public final int getDigestLength() { + return md.getDigestLength(); + } + + public final void reset() { + md.reset(); + } + + public final void update(byte b[]) { + this.update(b, 0, b.length); + } + + public final void update(byte b[], int off, int len) { + md.update(b, off, len); + } + + public final void update(byte b) { + md.update(b); + } + + public final void digest(byte[] out) throws DigestException { + this.digest(out, 0); + } + + public final void digest(byte[] out, int off) throws DigestException { + md.digest(out, off, out.length); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/digest/SHA1.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.digest; + +import java.security.DigestException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * @version $Id: SHA1.java 154 2014-04-28 11:45:02Z dkocher@sudo.ch $ + */ +public final class SHA1 implements Digest { + + private MessageDigest md; + + public SHA1() { + try { + md = MessageDigest.getInstance("SHA-1"); + } + catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e); + } + } + + public final int getDigestLength() { + return md.getDigestLength(); + } + + public final void reset() { + md.reset(); + } + + public final void update(byte b[]) { + this.update(b, 0, b.length); + } + + public final void update(byte b[], int off, int len) { + md.update(b, off, len); + } + + public final void update(byte b) { + md.update(b); + } + + public final void digest(byte[] out) throws DigestException { + this.digest(out, 0); + } + + public final void digest(byte[] out, int off) throws DigestException { + md.digest(out, off, out.length); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/digest/SHA256.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.digest; + +import java.security.DigestException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * @version $Id: SHA256.java 152 2014-04-28 11:02:23Z dkocher@sudo.ch $ + */ +public final class SHA256 implements Digest { + + private MessageDigest md; + + public SHA256() { + try { + md = MessageDigest.getInstance("SHA-256"); + } + catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e); + } + } + + public final int getDigestLength() { + return md.getDigestLength(); + } + + public final void reset() { + md.reset(); + } + + public final void update(byte b[]) { + this.update(b, 0, b.length); + } + + public final void update(byte b[], int off, int len) { + md.update(b, off, len); + } + + public final void update(byte b) { + md.update(b); + } + + public final void digest(byte[] out) throws DigestException { + this.digest(out, 0); + } + + public final void digest(byte[] out, int off) throws DigestException { + md.digest(out, off, out.length); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/digest/SHA512.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.crypto.digest; + +import java.security.DigestException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * @version $Id: SHA512.java 152 2014-04-28 11:02:23Z dkocher@sudo.ch $ + */ +public final class SHA512 implements Digest { + + private MessageDigest md; + + public SHA512() { + try { + md = MessageDigest.getInstance("SHA-512"); + } + catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e); + } + } + + public final int getDigestLength() { + return md.getDigestLength(); + } + + public final void reset() { + md.reset(); + } + + public final void update(byte b[]) { + md.update(b); + } + + public final void update(byte b[], int off, int len) { + md.update(b, off, len); + } + + public final void update(byte b) { + md.update(b); + } + + public final void digest(byte[] out) { + md.digest(out); + } + + public final void digest(byte[] out, int off) throws DigestException { + md.digest(out, off, out.length); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/log/Logger.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2.log; + +import android.util.Log; + +public class Logger { + private static final String TAG = "ConnectBot.ssh"; + public static boolean enabled = false; + + public static Logger getLogger(Class<?> x) { + return new Logger(); + } + + public Logger() { + } + + public final boolean isEnabled() { + return enabled; + } + + public boolean isDebugEnabled() { + return enabled; + } + + public void debug(String message) { + if (enabled) Log.d(TAG, message); + } + + public boolean isInfoEnabled() { + return enabled; + } + + public void info(String message) { + if (enabled) Log.i(TAG, message); + } + + public boolean isWarningEnabled() { + return enabled; + } + + public void warning(String message) { + if (enabled) Log.w(TAG, message); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketChannelAuthAgentReq.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,30 @@ +package ch.ethz.ssh2.packets; + +/** + * PacketGlobalAuthAgent. + * + * @author Kenny Root, kenny@the-b.org + * @version $Id$ + */ +public class PacketChannelAuthAgentReq { + byte[] payload; + + public int recipientChannelID; + + public PacketChannelAuthAgentReq(int recipientChannelID) { + this.recipientChannelID = recipientChannelID; + } + + public byte[] getPayload() { + if (payload == null) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); + tw.writeUINT32(recipientChannelID); + tw.writeString("auth-agent-req@openssh.com"); + tw.writeBoolean(true); // want reply + payload = tw.getBytes(); + } + + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketChannelFailure.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketChannelFailure.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketChannelFailure { + private final byte[] payload; + + public PacketChannelFailure(int recipientChannelID) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_FAILURE); + tw.writeUINT32(recipientChannelID); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketChannelOpenConfirmation.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketChannelOpenConfirmation.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketChannelOpenConfirmation { + + private final byte[] payload; + + private final int recipientChannelID; + private final int senderChannelID; + private final int initialWindowSize; + private final int maxPacketSize; + + public PacketChannelOpenConfirmation(int recipientChannelID, int senderChannelID, int initialWindowSize, + int maxPacketSize) { + this.recipientChannelID = recipientChannelID; + this.senderChannelID = senderChannelID; + this.initialWindowSize = initialWindowSize; + this.maxPacketSize = maxPacketSize; + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION); + tw.writeUINT32(recipientChannelID); + tw.writeUINT32(senderChannelID); + tw.writeUINT32(initialWindowSize); + tw.writeUINT32(maxPacketSize); + payload = tw.getBytes(); + } + + public PacketChannelOpenConfirmation(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) { + throw new PacketTypeException(packet_type); + } + + recipientChannelID = tr.readUINT32(); + senderChannelID = tr.readUINT32(); + initialWindowSize = tr.readUINT32(); + maxPacketSize = tr.readUINT32(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public int getRecipientChannelID() { + return recipientChannelID; + } + + public int getSenderChannelID() { + return senderChannelID; + } + + public int getInitialWindowSize() { + return initialWindowSize; + } + + public int getMaxPacketSize() { + return maxPacketSize; + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketChannelOpenFailure.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; + +/** + * @author Christian Plattner + * @version $Id: PacketChannelOpenFailure.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketChannelOpenFailure { + + private final byte[] payload; + + public PacketChannelOpenFailure(int recipientChannelID, int reasonCode, String description, + String languageTag) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN_FAILURE); + tw.writeUINT32(recipientChannelID); + tw.writeUINT32(reasonCode); + tw.writeString(description); + tw.writeString(languageTag); + payload = tw.getBytes(); + } + + public PacketChannelOpenFailure(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN_FAILURE) { + throw new IOException( + "This is not a SSH_MSG_CHANNEL_OPEN_FAILURE! (" + + packet_type + ")" + ); + } + + int recipientChannelID = tr.readUINT32(); + int reasonCode = tr.readUINT32(); + String description = tr.readString(); + String languageTag = tr.readString(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketChannelSuccess.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketChannelSuccess.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketChannelSuccess { + + private final byte[] payload; + + public PacketChannelSuccess(int recipientChannelID) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_SUCCESS); + tw.writeUINT32(recipientChannelID); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketChannelWindowAdjust.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; + +/** + * @author Christian Plattner + * @version $Id: PacketChannelWindowAdjust.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketChannelWindowAdjust { + + private final byte[] payload; + + public PacketChannelWindowAdjust(int recipientChannelID, int windowChange) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST); + tw.writeUINT32(recipientChannelID); + tw.writeUINT32(windowChange); + payload = tw.getBytes(); + } + + public PacketChannelWindowAdjust(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST) { + throw new IOException( + "This is not a SSH_MSG_CHANNEL_WINDOW_ADJUST! (" + + packet_type + ")" + ); + } + + int recipientChannelID = tr.readUINT32(); + int windowChange = tr.readUINT32(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketDisconnect.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketDisconnect.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketDisconnect { + + public enum Reason { + SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT, + SSH_DISCONNECT_PROTOCOL_ERROR, + SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + SSH_DISCONNECT_RESERVED, + SSH_DISCONNECT_MAC_ERROR, + SSH_DISCONNECT_COMPRESSION_ERROR, + SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, + SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED, + SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE, + SSH_DISCONNECT_CONNECTION_LOST, + SSH_DISCONNECT_BY_APPLICATION, + SSH_DISCONNECT_TOO_MANY_CONNECTIONS, + SSH_DISCONNECT_AUTH_CANCELLED_BY_USER, + SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, + SSH_DISCONNECT_ILLEGAL_USER_NAME + } + + private final byte[] payload; + + private final Reason reason; + + private final String message; + + public PacketDisconnect(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_DISCONNECT) { + throw new PacketTypeException(packet_type); + } + + reason = PacketDisconnect.Reason.values()[tr.readUINT32()]; + message = tr.readString(); + String lang = tr.readString(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public PacketDisconnect(Reason reason, String desc) { + this.reason = reason; + this.message = desc; + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_DISCONNECT); + tw.writeUINT32(reason.ordinal()); + tw.writeString(desc); + tw.writeString(""); + payload = tw.getBytes(); + } + + public Reason getReason() { + return reason; + } + + public String getMessage() { + return message; + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketGlobalCancelForwardRequest.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketGlobalCancelForwardRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketGlobalCancelForwardRequest { + + private final byte[] payload; + + public PacketGlobalCancelForwardRequest(boolean wantReply, String bindAddress, int bindPort) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_GLOBAL_REQUEST); + tw.writeString("cancel-tcpip-forward"); + tw.writeBoolean(wantReply); + tw.writeString(bindAddress); + tw.writeUINT32(bindPort); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketGlobalForwardRequest.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketGlobalForwardRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketGlobalForwardRequest { + + private final byte[] payload; + + public PacketGlobalForwardRequest(boolean wantReply, String bindAddress, int bindPort) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_GLOBAL_REQUEST); + tw.writeString("tcpip-forward"); + tw.writeBoolean(wantReply); + tw.writeString(bindAddress); + tw.writeUINT32(bindPort); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketIgnore.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketIgnore.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketIgnore { + private final byte[] payload; + + public PacketIgnore(byte[] data) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_IGNORE); + + if (data != null) { + tw.writeString(data, 0, data.length); + } + else { + tw.writeString(""); + } + + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketKexDHInit.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; +import java.math.BigInteger; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketKexDHInit.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketKexDHInit { + + private final byte[] payload; + + private final BigInteger e; + + public PacketKexDHInit(BigInteger e) { + this.e = e; + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_KEXDH_INIT); + tw.writeMPInt(e); + payload = tw.getBytes(); + } + + public PacketKexDHInit(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_KEXDH_INIT) { + throw new PacketTypeException(packet_type); + } + + e = tr.readMPINT(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public BigInteger getE() { + return e; + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketKexDHReply.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; +import java.math.BigInteger; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketKexDHReply.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketKexDHReply { + + private final byte[] payload; + + private final byte[] hostKey; + private final BigInteger f; + private final byte[] signature; + + public PacketKexDHReply(byte[] hostKey, BigInteger f, byte[] signature) { + this.hostKey = hostKey; + this.f = f; + this.signature = signature; + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_KEXDH_REPLY); + tw.writeString(hostKey, 0, hostKey.length); + tw.writeMPInt(f); + tw.writeString(signature, 0, signature.length); + payload = tw.getBytes(); + } + + public PacketKexDHReply(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_KEXDH_REPLY) { + throw new PacketTypeException(packet_type); + } + + hostKey = tr.readByteString(); + f = tr.readMPINT(); + signature = tr.readByteString(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } + + public BigInteger getF() { + return f; + } + + public byte[] getHostKey() { + return hostKey; + } + + public byte[] getSignature() { + return signature; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketKexDhGexGroup.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; +import java.math.BigInteger; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketKexDhGexGroup.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketKexDhGexGroup { + + private final BigInteger p; + private final BigInteger g; + + public PacketKexDhGexGroup(byte payload[]) throws IOException { + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_KEX_DH_GEX_GROUP) { + throw new PacketTypeException(packet_type); + } + + p = tr.readMPINT(); + g = tr.readMPINT(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public BigInteger getG() { + return g; + } + + public BigInteger getP() { + return p; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketKexDhGexInit.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.math.BigInteger; + +/** + * @author Christian Plattner + * @version $Id: PacketKexDhGexInit.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketKexDhGexInit { + + private final byte[] payload; + + public PacketKexDhGexInit(BigInteger e) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_KEX_DH_GEX_INIT); + tw.writeMPInt(e); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketKexDhGexReply.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; +import java.math.BigInteger; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketKexDhGexReply.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketKexDhGexReply { + + private final byte[] hostKey; + private final BigInteger f; + private final byte[] signature; + + public PacketKexDhGexReply(byte payload[]) throws IOException { + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_KEX_DH_GEX_REPLY) { + throw new PacketTypeException(packet_type); + } + + hostKey = tr.readByteString(); + f = tr.readMPINT(); + signature = tr.readByteString(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public BigInteger getF() { + return f; + } + + public byte[] getHostKey() { + return hostKey; + } + + public byte[] getSignature() { + return signature; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketKexDhGexRequest.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import ch.ethz.ssh2.DHGexParameters; + +/** + * @author Christian Plattner + * @version $Id: PacketKexDhGexRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketKexDhGexRequest { + private final byte[] payload; + + public PacketKexDhGexRequest(DHGexParameters para) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_KEX_DH_GEX_REQUEST); + tw.writeUINT32(para.getMin_group_len()); + tw.writeUINT32(para.getPref_group_len()); + tw.writeUINT32(para.getMax_group_len()); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketKexDhGexRequestOld.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import ch.ethz.ssh2.DHGexParameters; + +/** + * @author Christian Plattner + * @version $Id: PacketKexDhGexRequestOld.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketKexDhGexRequestOld { + + private final byte[] payload; + + public PacketKexDhGexRequestOld(DHGexParameters para) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_KEX_DH_GEX_REQUEST_OLD); + tw.writeUINT32(para.getPref_group_len()); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketKexInit.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; +import java.security.SecureRandom; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; +import ch.ethz.ssh2.crypto.CryptoWishList; +import ch.ethz.ssh2.transport.KexParameters; + +/** + * @author Christian Plattner + * @version $Id: PacketKexInit.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketKexInit { + private final byte[] payload; + + KexParameters kp = new KexParameters(); + + public PacketKexInit(CryptoWishList cwl, SecureRandom rnd) { + kp.cookie = new byte[16]; + rnd.nextBytes(kp.cookie); + kp.kex_algorithms = cwl.kexAlgorithms; + kp.server_host_key_algorithms = cwl.serverHostKeyAlgorithms; + kp.encryption_algorithms_client_to_server = cwl.c2s_enc_algos; + kp.encryption_algorithms_server_to_client = cwl.s2c_enc_algos; + kp.mac_algorithms_client_to_server = cwl.c2s_mac_algos; + kp.mac_algorithms_server_to_client = cwl.s2c_mac_algos; + kp.compression_algorithms_client_to_server = cwl.c2s_comp_algos; + kp.compression_algorithms_server_to_client = cwl.s2c_comp_algos; + kp.languages_client_to_server = new String[] {""}; + kp.languages_server_to_client = new String[] {""}; + kp.first_kex_packet_follows = false; + kp.reserved_field1 = 0; + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_KEXINIT); + tw.writeBytes(kp.cookie, 0, 16); + tw.writeNameList(kp.kex_algorithms); + tw.writeNameList(kp.server_host_key_algorithms); + tw.writeNameList(kp.encryption_algorithms_client_to_server); + tw.writeNameList(kp.encryption_algorithms_server_to_client); + tw.writeNameList(kp.mac_algorithms_client_to_server); + tw.writeNameList(kp.mac_algorithms_server_to_client); + tw.writeNameList(kp.compression_algorithms_client_to_server); + tw.writeNameList(kp.compression_algorithms_server_to_client); + tw.writeNameList(kp.languages_client_to_server); + tw.writeNameList(kp.languages_server_to_client); + tw.writeBoolean(kp.first_kex_packet_follows); + tw.writeUINT32(kp.reserved_field1); + payload = tw.getBytes(); + } + + public PacketKexInit(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_KEXINIT) { + throw new PacketTypeException(packet_type); + } + + kp.cookie = tr.readBytes(16); + kp.kex_algorithms = tr.readNameList(); + kp.server_host_key_algorithms = tr.readNameList(); + kp.encryption_algorithms_client_to_server = tr.readNameList(); + kp.encryption_algorithms_server_to_client = tr.readNameList(); + kp.mac_algorithms_client_to_server = tr.readNameList(); + kp.mac_algorithms_server_to_client = tr.readNameList(); + kp.compression_algorithms_client_to_server = tr.readNameList(); + kp.compression_algorithms_server_to_client = tr.readNameList(); + kp.languages_client_to_server = tr.readNameList(); + kp.languages_server_to_client = tr.readNameList(); + kp.first_kex_packet_follows = tr.readBoolean(); + kp.reserved_field1 = tr.readUINT32(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } + + public KexParameters getKexParameters() { + return kp; + } + + public String[] getCompression_algorithms_client_to_server() { + return kp.compression_algorithms_client_to_server; + } + + public String[] getCompression_algorithms_server_to_client() { + return kp.compression_algorithms_server_to_client; + } + + public byte[] getCookie() { + return kp.cookie; + } + + public String[] getEncryption_algorithms_client_to_server() { + return kp.encryption_algorithms_client_to_server; + } + + public String[] getEncryption_algorithms_server_to_client() { + return kp.encryption_algorithms_server_to_client; + } + + public boolean isFirst_kex_packet_follows() { + return kp.first_kex_packet_follows; + } + + public String[] getKex_algorithms() { + return kp.kex_algorithms; + } + + public String[] getLanguages_client_to_server() { + return kp.languages_client_to_server; + } + + public String[] getLanguages_server_to_client() { + return kp.languages_server_to_client; + } + + public String[] getMac_algorithms_client_to_server() { + return kp.mac_algorithms_client_to_server; + } + + public String[] getMac_algorithms_server_to_client() { + return kp.mac_algorithms_server_to_client; + } + + public int getReserved_field1() { + return kp.reserved_field1; + } + + public String[] getServer_host_key_algorithms() { + return kp.server_host_key_algorithms; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketNewKeys.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketNewKeys.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketNewKeys { + private final byte[] payload; + + public PacketNewKeys() { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_NEWKEYS); + payload = tw.getBytes(); + } + + public PacketNewKeys(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_NEWKEYS) { + throw new PacketTypeException(packet_type); + } + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketOpenDirectTCPIPChannel.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketOpenDirectTCPIPChannel.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketOpenDirectTCPIPChannel { + private final byte[] payload; + + public PacketOpenDirectTCPIPChannel(int channelID, int initialWindowSize, int maxPacketSize, + String host_to_connect, int port_to_connect, String originator_IP_address, + int originator_port) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN); + tw.writeString("direct-tcpip"); + tw.writeUINT32(channelID); + tw.writeUINT32(initialWindowSize); + tw.writeUINT32(maxPacketSize); + tw.writeString(host_to_connect); + tw.writeUINT32(port_to_connect); + tw.writeString(originator_IP_address); + tw.writeUINT32(originator_port); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketOpenSessionChannel.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketOpenSessionChannel.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketOpenSessionChannel { + private final byte[] payload; + + public PacketOpenSessionChannel(int channelID, int initialWindowSize, int maxPacketSize) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN); + tw.writeString("session"); + tw.writeUINT32(channelID); + tw.writeUINT32(initialWindowSize); + tw.writeUINT32(maxPacketSize); + payload = tw.getBytes(); + } + + public PacketOpenSessionChannel(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN) { + throw new PacketTypeException(packet_type); + } + + int channelID = tr.readUINT32(); + int initialWindowSize = tr.readUINT32(); + int maxPacketSize = tr.readUINT32(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketServiceAccept.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketServiceAccept.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketServiceAccept { + private final byte[] payload; + + public PacketServiceAccept(String serviceName) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_SERVICE_ACCEPT); + tw.writeString(serviceName); + payload = tw.getBytes(); + } + + public PacketServiceAccept(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_SERVICE_ACCEPT) { + throw new PacketTypeException(packet_type); + } + + if (tr.remain() != 0) { + String serviceName = tr.readString(); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketServiceRequest.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketServiceRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketServiceRequest { + private final byte[] payload; + + private final String serviceName; + + public PacketServiceRequest(String serviceName) { + this.serviceName = serviceName; + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_SERVICE_REQUEST); + tw.writeString(serviceName); + payload = tw.getBytes(); + } + + public String getServiceName() { + return serviceName; + } + + public PacketServiceRequest(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_SERVICE_REQUEST) { + throw new PacketTypeException(packet_type); + } + + serviceName = tr.readString(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketSessionExecCommand.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +/** + * @author Christian Plattner + * @version $Id: PacketSessionExecCommand.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketSessionExecCommand { + private final byte[] payload; + + public PacketSessionExecCommand(int recipientChannelID, boolean wantReply, String command, String charsetName) throws UnsupportedEncodingException { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); + tw.writeUINT32(recipientChannelID); + tw.writeString("exec"); + tw.writeBoolean(wantReply); + tw.writeString(command, charsetName); + payload = tw.getBytes(); + } + + public byte[] getPayload() throws IOException { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketSessionPtyRequest.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketSessionPtyRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketSessionPtyRequest { + private final byte[] payload; + + public PacketSessionPtyRequest(int recipientChannelID, boolean wantReply, String term, + int character_width, int character_height, int pixel_width, int pixel_height, + byte[] terminal_modes) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); + tw.writeUINT32(recipientChannelID); + tw.writeString("pty-req"); + tw.writeBoolean(wantReply); + tw.writeString(term); + tw.writeUINT32(character_width); + tw.writeUINT32(character_height); + tw.writeUINT32(pixel_width); + tw.writeUINT32(pixel_height); + tw.writeString(terminal_modes, 0, terminal_modes.length); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketSessionStartShell.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketSessionStartShell.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketSessionStartShell { + private final byte[] payload; + + public PacketSessionStartShell(int recipientChannelID, boolean wantReply) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); + tw.writeUINT32(recipientChannelID); + tw.writeString("shell"); + tw.writeBoolean(wantReply); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketSessionSubsystemRequest.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketSessionSubsystemRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketSessionSubsystemRequest { + private final byte[] payload; + + public PacketSessionSubsystemRequest(int recipientChannelID, boolean wantReply, String subsystem) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); + tw.writeUINT32(recipientChannelID); + tw.writeString("subsystem"); + tw.writeBoolean(wantReply); + tw.writeString(subsystem); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketSessionX11Request.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketSessionX11Request.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketSessionX11Request { + private final byte[] payload; + + public PacketSessionX11Request(int recipientChannelID, boolean wantReply, boolean singleConnection, + String x11AuthenticationProtocol, String x11AuthenticationCookie, int x11ScreenNumber) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); + tw.writeUINT32(recipientChannelID); + tw.writeString("x11-req"); + tw.writeBoolean(wantReply); + tw.writeBoolean(singleConnection); + tw.writeString(x11AuthenticationProtocol); + tw.writeString(x11AuthenticationCookie); + tw.writeUINT32(x11ScreenNumber); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketUserauthBanner.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketUserauthBanner.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketUserauthBanner { + private final byte[] payload; + + private final String message; + + public PacketUserauthBanner(String message) { + this.message = message; + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_USERAUTH_BANNER); + tw.writeString(message); + tw.writeString(""); + payload = tw.getBytes(); + } + + public String getBanner() { + return message; + } + + public PacketUserauthBanner(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_USERAUTH_BANNER) { + throw new PacketTypeException(packet_type); + } + + message = tr.readString("UTF-8"); + String language = tr.readString(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketUserauthFailure.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketUserauthFailure.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketUserauthFailure { + + private final byte[] payload; + + private Set<String> authThatCanContinue; + + private boolean partialSuccess; + + public PacketUserauthFailure(Set<String> authThatCanContinue, boolean partialSuccess) { + this.authThatCanContinue = authThatCanContinue; + this.partialSuccess = partialSuccess; + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_USERAUTH_FAILURE); + tw.writeNameList(authThatCanContinue.toArray(new String[authThatCanContinue.size()])); + tw.writeBoolean(partialSuccess); + payload = tw.getBytes(); + } + + public PacketUserauthFailure(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_USERAUTH_FAILURE) { + throw new PacketTypeException(packet_type); + } + + authThatCanContinue = new HashSet<String>(Arrays.asList(tr.readNameList())); + partialSuccess = tr.readBoolean(); + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } + + public Set<String> getAuthThatCanContinue() { + return authThatCanContinue; + } + + public boolean isPartialSuccess() { + return partialSuccess; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketUserauthInfoRequest.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketUserauthInfoRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketUserauthInfoRequest { + + private final String name; + private final String instruction; + private final String languageTag; + private final int numPrompts; + + private final String prompt[]; + private final boolean echo[]; + + public PacketUserauthInfoRequest(byte payload[]) throws IOException { + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_USERAUTH_INFO_REQUEST) { + throw new PacketTypeException(packet_type); + } + + name = tr.readString(); + instruction = tr.readString(); + languageTag = tr.readString(); + numPrompts = tr.readUINT32(); + prompt = new String[numPrompts]; + echo = new boolean[numPrompts]; + + for (int i = 0; i < numPrompts; i++) { + prompt[i] = tr.readString(); + echo[i] = tr.readBoolean(); + } + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public boolean[] getEcho() { + return echo; + } + + public String getInstruction() { + return instruction; + } + + public String getLanguageTag() { + return languageTag; + } + + public String getName() { + return name; + } + + public int getNumPrompts() { + return numPrompts; + } + + public String[] getPrompt() { + return prompt; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketUserauthInfoResponse.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketUserauthInfoResponse.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketUserauthInfoResponse { + private final byte[] payload; + + public PacketUserauthInfoResponse(String[] responses) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_USERAUTH_INFO_RESPONSE); + tw.writeUINT32(responses.length); + + for (String response : responses) { + tw.writeString(response); + } + + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketUserauthRequestInteractive.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * @author Christian Plattner + * @version $Id: PacketUserauthRequestInteractive.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketUserauthRequestInteractive { + + private final byte[] payload; + + public PacketUserauthRequestInteractive(String serviceName, String user, String[] submethods) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); + tw.writeString(user); + tw.writeString(serviceName); + tw.writeString("keyboard-interactive"); + tw.writeString(""); // draft-ietf-secsh-newmodes-04.txt says that + // the language tag should be empty. + tw.writeNameList(null == submethods ? new String[] {} : submethods); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketUserauthRequestNone.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketUserauthRequestNone.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketUserauthRequestNone { + + private final byte[] payload; + + public PacketUserauthRequestNone(String serviceName, String user) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); + tw.writeString(user); + tw.writeString(serviceName); + tw.writeString("none"); + payload = tw.getBytes(); + } + + public PacketUserauthRequestNone(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { + throw new PacketTypeException(packet_type); + } + + String userName = tr.readString(); + String serviceName = tr.readString(); + String method = tr.readString(); + + if (!method.equals("none")) { + throw new IOException(String.format("Unexpected method %s", method)); + } + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketUserauthRequestPassword.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketUserauthRequestPassword.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketUserauthRequestPassword { + + private final byte[] payload; + + public PacketUserauthRequestPassword(String serviceName, String user, String pass) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); + tw.writeString(user); + tw.writeString(serviceName); + tw.writeString("password"); + tw.writeBoolean(false); + tw.writeString(pass); + payload = tw.getBytes(); + } + + public PacketUserauthRequestPassword(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { + throw new PacketTypeException(packet_type); + } + + String userName = tr.readString(); + String serviceName = tr.readString(); + String method = tr.readString(); + + if (!method.equals("password")) { + throw new IOException(String.format("Unexpected method %s", method)); + } + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketUserauthRequestPublicKey.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketUserauthRequestPublicKey.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketUserauthRequestPublicKey { + + private final byte[] payload; + + public PacketUserauthRequestPublicKey(String serviceName, String user, + String pkAlgorithmName, byte[] pk, byte[] sig) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); + tw.writeString(user); + tw.writeString(serviceName); + tw.writeString("publickey"); + tw.writeBoolean(true); + tw.writeString(pkAlgorithmName); + tw.writeString(pk, 0, pk.length); + tw.writeString(sig, 0, sig.length); + payload = tw.getBytes(); + } + + public PacketUserauthRequestPublicKey(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { + throw new PacketTypeException(packet_type); + } + + String userName = tr.readString(); + String serviceName = tr.readString(); + String method = tr.readString(); + + if (!method.equals("publickey")) { + throw new IOException(String.format("Unexpected method %s", method)); + } + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketUserauthSuccess.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.PacketTypeException; + +/** + * @author Christian Plattner + * @version $Id: PacketUserauthSuccess.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class PacketUserauthSuccess { + + private final byte[] payload; + + public PacketUserauthSuccess() { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_USERAUTH_SUCCESS); + payload = tw.getBytes(); + } + + public PacketUserauthSuccess(byte payload[]) throws IOException { + this.payload = payload; + TypesReader tr = new TypesReader(payload); + int packet_type = tr.readByte(); + + if (packet_type != Packets.SSH_MSG_USERAUTH_SUCCESS) { + throw new PacketTypeException(packet_type); + } + + if (tr.remain() != 0) { + throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); + } + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/PacketWindowChange.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,30 @@ +package ch.ethz.ssh2.packets; + +/** + * Indicates that that size of the terminal (window) size has changed on the client side. + * <p/> + * See section 6.7 of RFC 4254. + * + * @author Kohsuke Kawaguchi + */ +public final class PacketWindowChange { + private final byte[] payload; + + public PacketWindowChange(int recipientChannelID, + int character_width, int character_height, int pixel_width, int pixel_height) { + TypesWriter tw = new TypesWriter(); + tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); + tw.writeUINT32(recipientChannelID); + tw.writeString("window-change"); + tw.writeBoolean(false); + tw.writeUINT32(character_width); + tw.writeUINT32(character_height); + tw.writeUINT32(pixel_width); + tw.writeUINT32(pixel_height); + payload = tw.getBytes(); + } + + public byte[] getPayload() { + return payload; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/Packets.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +/** + * Packets. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class Packets { + public static final int SSH_MSG_DISCONNECT = 1; + public static final int SSH_MSG_IGNORE = 2; + public static final int SSH_MSG_UNIMPLEMENTED = 3; + public static final int SSH_MSG_DEBUG = 4; + public static final int SSH_MSG_SERVICE_REQUEST = 5; + public static final int SSH_MSG_SERVICE_ACCEPT = 6; + + public static final int SSH_MSG_KEXINIT = 20; + public static final int SSH_MSG_NEWKEYS = 21; + + public static final int SSH_MSG_KEXDH_INIT = 30; + public static final int SSH_MSG_KEXDH_REPLY = 31; + + public static final int SSH_MSG_KEX_DH_GEX_REQUEST_OLD = 30; + public static final int SSH_MSG_KEX_DH_GEX_REQUEST = 34; + public static final int SSH_MSG_KEX_DH_GEX_GROUP = 31; + public static final int SSH_MSG_KEX_DH_GEX_INIT = 32; + public static final int SSH_MSG_KEX_DH_GEX_REPLY = 33; + + public static final int SSH_MSG_USERAUTH_REQUEST = 50; + public static final int SSH_MSG_USERAUTH_FAILURE = 51; + public static final int SSH_MSG_USERAUTH_SUCCESS = 52; + public static final int SSH_MSG_USERAUTH_BANNER = 53; + public static final int SSH_MSG_USERAUTH_INFO_REQUEST = 60; + public static final int SSH_MSG_USERAUTH_INFO_RESPONSE = 61; + + public static final int SSH_MSG_GLOBAL_REQUEST = 80; + public static final int SSH_MSG_REQUEST_SUCCESS = 81; + public static final int SSH_MSG_REQUEST_FAILURE = 82; + + public static final int SSH_MSG_CHANNEL_OPEN = 90; + public static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91; + public static final int SSH_MSG_CHANNEL_OPEN_FAILURE = 92; + public static final int SSH_MSG_CHANNEL_WINDOW_ADJUST = 93; + public static final int SSH_MSG_CHANNEL_DATA = 94; + public static final int SSH_MSG_CHANNEL_EXTENDED_DATA = 95; + public static final int SSH_MSG_CHANNEL_EOF = 96; + public static final int SSH_MSG_CHANNEL_CLOSE = 97; + public static final int SSH_MSG_CHANNEL_REQUEST = 98; + public static final int SSH_MSG_CHANNEL_SUCCESS = 99; + public static final int SSH_MSG_CHANNEL_FAILURE = 100; + + public static final int SSH_EXTENDED_DATA_STDERR = 1; + + public static final int SSH_OPEN_ADMINISTRATIVELY_PROHIBITED = 1; + public static final int SSH_OPEN_CONNECT_FAILED = 2; + public static final int SSH_OPEN_UNKNOWN_CHANNEL_TYPE = 3; + public static final int SSH_OPEN_RESOURCE_SHORTAGE = 4; + + private static final String[] reverseNames = new String[101]; + + static { + reverseNames[1] = "SSH_MSG_DISCONNECT"; + reverseNames[2] = "SSH_MSG_IGNORE"; + reverseNames[3] = "SSH_MSG_UNIMPLEMENTED"; + reverseNames[4] = "SSH_MSG_DEBUG"; + reverseNames[5] = "SSH_MSG_SERVICE_REQUEST"; + reverseNames[6] = "SSH_MSG_SERVICE_ACCEPT"; + reverseNames[20] = "SSH_MSG_KEXINIT"; + reverseNames[21] = "SSH_MSG_NEWKEYS"; + reverseNames[30] = "SSH_MSG_KEXDH_INIT"; + reverseNames[31] = "SSH_MSG_KEXDH_REPLY/SSH_MSG_KEX_DH_GEX_GROUP"; + reverseNames[32] = "SSH_MSG_KEX_DH_GEX_INIT"; + reverseNames[33] = "SSH_MSG_KEX_DH_GEX_REPLY"; + reverseNames[34] = "SSH_MSG_KEX_DH_GEX_REQUEST"; + reverseNames[50] = "SSH_MSG_USERAUTH_REQUEST"; + reverseNames[51] = "SSH_MSG_USERAUTH_FAILURE"; + reverseNames[52] = "SSH_MSG_USERAUTH_SUCCESS"; + reverseNames[53] = "SSH_MSG_USERAUTH_BANNER"; + reverseNames[60] = "SSH_MSG_USERAUTH_INFO_REQUEST"; + reverseNames[61] = "SSH_MSG_USERAUTH_INFO_RESPONSE"; + reverseNames[80] = "SSH_MSG_GLOBAL_REQUEST"; + reverseNames[81] = "SSH_MSG_REQUEST_SUCCESS"; + reverseNames[82] = "SSH_MSG_REQUEST_FAILURE"; + reverseNames[90] = "SSH_MSG_CHANNEL_OPEN"; + reverseNames[91] = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION"; + reverseNames[92] = "SSH_MSG_CHANNEL_OPEN_FAILURE"; + reverseNames[93] = "SSH_MSG_CHANNEL_WINDOW_ADJUST"; + reverseNames[94] = "SSH_MSG_CHANNEL_DATA"; + reverseNames[95] = "SSH_MSG_CHANNEL_EXTENDED_DATA"; + reverseNames[96] = "SSH_MSG_CHANNEL_EOF"; + reverseNames[97] = "SSH_MSG_CHANNEL_CLOSE"; + reverseNames[98] = "SSH_MSG_CHANNEL_REQUEST"; + reverseNames[99] = "SSH_MSG_CHANNEL_SUCCESS"; + reverseNames[100] = "SSH_MSG_CHANNEL_FAILURE"; + } + + public static final String getMessageName(int type) { + String res = null; + + if ((type >= 0) && (type < reverseNames.length)) { + res = reverseNames[type]; + } + + return (res == null) ? ("UNKNOWN MSG " + type) : res; + } + + // public static final void debug(String tag, byte[] msg) + // { + // System.err.println(tag + " Type: " + msg[0] + ", LEN: " + msg.length); + // + // for (int i = 0; i < msg.length; i++) + // { + // if (((msg[i] >= 'a') && (msg[i] <= 'z')) || ((msg[i] >= 'A') && (msg[i] <= 'Z')) + // || ((msg[i] >= '0') && (msg[i] <= '9')) || (msg[i] == ' ')) + // System.err.print((char) msg[i]); + // else + // System.err.print("."); + // } + // System.err.println(); + // System.err.flush(); + // } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/TypesReader.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.IOException; +import java.math.BigInteger; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.util.StringEncoder; + +/** + * @author Christian Plattner + * @version $Id: TypesReader.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class TypesReader { + byte[] arr; + int pos = 0; + int max = 0; + + public TypesReader(byte[] arr) { + this.arr = arr; + pos = 0; + max = arr.length; + } + + public TypesReader(byte[] arr, int off) { + this.arr = arr; + this.pos = off; + this.max = arr.length; + + if ((pos < 0) || (pos > arr.length)) { + throw new IllegalArgumentException("Illegal offset."); + } + } + + public TypesReader(byte[] arr, int off, int len) { + this.arr = arr; + this.pos = off; + this.max = off + len; + + if ((pos < 0) || (pos > arr.length)) { + throw new IllegalArgumentException("Illegal offset."); + } + + if ((max < 0) || (max > arr.length)) { + throw new IllegalArgumentException("Illegal length."); + } + } + + public int readByte() throws IOException { + if (pos >= max) { + throw new PacketFormatException("Packet too short."); + } + + return (arr[pos++] & 0xff); + } + + public byte[] readBytes(int len) throws IOException { + if ((pos + len) > max) { + throw new PacketFormatException("Packet too short."); + } + + byte[] res = new byte[len]; + System.arraycopy(arr, pos, res, 0, len); + pos += len; + return res; + } + + public void readBytes(byte[] dst, int off, int len) throws IOException { + if ((pos + len) > max) { + throw new PacketFormatException("Packet too short."); + } + + System.arraycopy(arr, pos, dst, off, len); + pos += len; + } + + public boolean readBoolean() throws IOException { + if (pos >= max) { + throw new PacketFormatException("Packet too short."); + } + + return (arr[pos++] != 0); + } + + public int readUINT32() throws IOException { + if ((pos + 4) > max) { + throw new PacketFormatException("Packet too short."); + } + + return ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8) + | (arr[pos++] & 0xff); + } + + public long readUINT64() throws IOException { + if ((pos + 8) > max) { + throw new PacketFormatException("Packet too short."); + } + + long high = ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8) + | (arr[pos++] & 0xff); /* sign extension may take place - will be shifted away =) */ + long low = ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8) + | (arr[pos++] & 0xff); /* sign extension may take place - handle below */ + return (high << 32) | (low & 0xffffffffl); /* see Java language spec (15.22.1, 5.6.2) */ + } + + public BigInteger readMPINT() throws IOException { + BigInteger b; + byte raw[] = readByteString(); + + if (raw.length == 0) { + b = BigInteger.ZERO; + } + else { + b = new BigInteger(raw); + } + + return b; + } + + public byte[] readByteString() throws IOException { + int len = readUINT32(); + + if ((len + pos) > max) { + throw new PacketFormatException("Malformed SSH byte string."); + } + + byte[] res = new byte[len]; + System.arraycopy(arr, pos, res, 0, len); + pos += len; + return res; + } + + public String readString(String charsetName) throws IOException { + int len = readUINT32(); + + if ((len + pos) > max) { + throw new PacketFormatException("Malformed SSH string."); + } + + String res = (charsetName == null) ? new String(arr, pos, len) : new String(arr, pos, len, charsetName); + pos += len; + return res; + } + + public String readString() throws IOException { + int len = readUINT32(); + + if ((len + pos) > max) { + throw new PacketFormatException("Malformed SSH string."); + } + + String res = StringEncoder.GetString(arr, pos, len); + pos += len; + return res; + } + + public String[] readNameList() throws IOException { + return readString().split(","); + } + + public int remain() { + return max - pos; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/packets/TypesWriter.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.packets; + +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; + +import ch.ethz.ssh2.util.StringEncoder; + +/** + * @author Christian Plattner + * @version $Id: TypesWriter.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public final class TypesWriter { + byte arr[]; + int pos; + + public TypesWriter() { + arr = new byte[256]; + pos = 0; + } + + private void resize(int len) { + byte new_arr[] = new byte[len]; + System.arraycopy(arr, 0, new_arr, 0, arr.length); + arr = new_arr; + } + + public int length() { + return pos; + } + + public byte[] getBytes() { + byte[] dst = new byte[pos]; + System.arraycopy(arr, 0, dst, 0, pos); + return dst; + } + + public void getBytes(byte dst[]) { + System.arraycopy(arr, 0, dst, 0, pos); + } + + public void writeUINT32(int val, int off) { + if ((off + 4) > arr.length) { + resize(off + 32); + } + + arr[off++] = (byte)(val >> 24); + arr[off++] = (byte)(val >> 16); + arr[off++] = (byte)(val >> 8); + arr[off++] = (byte) val; + } + + public void writeUINT32(int val) { + writeUINT32(val, pos); + pos += 4; + } + + public void writeUINT64(long val) { + if ((pos + 8) > arr.length) { + resize(arr.length + 32); + } + + arr[pos++] = (byte)(val >> 56); + arr[pos++] = (byte)(val >> 48); + arr[pos++] = (byte)(val >> 40); + arr[pos++] = (byte)(val >> 32); + arr[pos++] = (byte)(val >> 24); + arr[pos++] = (byte)(val >> 16); + arr[pos++] = (byte)(val >> 8); + arr[pos++] = (byte) val; + } + + public void writeBoolean(boolean v) { + if ((pos + 1) > arr.length) { + resize(arr.length + 32); + } + + arr[pos++] = v ? (byte) 1 : (byte) 0; + } + + public void writeByte(int v, int off) { + if ((off + 1) > arr.length) { + resize(off + 32); + } + + arr[off] = (byte) v; + } + + public void writeByte(int v) { + writeByte(v, pos); + pos++; + } + + public void writeMPInt(BigInteger b) { + byte raw[] = b.toByteArray(); + + if ((raw.length == 1) && (raw[0] == 0)) { + writeUINT32(0); /* String with zero bytes of data */ + } + else { + writeString(raw, 0, raw.length); + } + } + + public void writeBytes(byte[] buff) { + writeBytes(buff, 0, buff.length); + } + + public void writeBytes(byte[] buff, int off, int len) { + if ((pos + len) > arr.length) { + resize(arr.length + len + 32); + } + + System.arraycopy(buff, off, arr, pos, len); + pos += len; + } + + public void writeString(byte[] buff, int off, int len) { + writeUINT32(len); + writeBytes(buff, off, len); + } + + public void writeString(String v) { + byte[] b = StringEncoder.GetBytes(v); + writeUINT32(b.length); + writeBytes(b, 0, b.length); + } + + public void writeString(String v, String charsetName) throws UnsupportedEncodingException { + byte[] b = (charsetName == null) ? StringEncoder.GetBytes(v) : v.getBytes(charsetName); + writeUINT32(b.length); + writeBytes(b, 0, b.length); + } + + public void writeNameList(String v[]) { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < v.length; i++) { + if (i > 0) { + sb.append(','); + } + + sb.append(v[i]); + } + + writeString(sb.toString()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/server/ServerConnectionState.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.server; + +import java.net.Socket; + +import ch.ethz.ssh2.ServerAuthenticationCallback; +import ch.ethz.ssh2.ServerConnection; +import ch.ethz.ssh2.ServerConnectionCallback; +import ch.ethz.ssh2.auth.ServerAuthenticationManager; +import ch.ethz.ssh2.channel.ChannelManager; +import ch.ethz.ssh2.crypto.CryptoWishList; +import ch.ethz.ssh2.crypto.SecureRandomFix; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.RSAPrivateKey; +import ch.ethz.ssh2.transport.ClientServerHello; +import ch.ethz.ssh2.transport.ServerTransportManager; + +public class ServerConnectionState { + public ServerConnection conn; + + public SecureRandomFix generator = new SecureRandomFix(); + + public String softwareversion; + + //public String auth_banner = null; + public ServerConnectionCallback cb_conn; + public ServerAuthenticationCallback cb_auth; + + /* Settings for the next key exchange */ + public CryptoWishList next_cryptoWishList = CryptoWishList.forServer(); + public KeyPair next_dsa_key; + public KeyPair next_ec_key; + public KeyPair next_rsa_key; + + public Socket s; + + public ClientServerHello csh; + public ServerTransportManager tm; + public ServerAuthenticationManager am; + public ChannelManager cm; + + public boolean flag_auth_serviceRequested = false; + public boolean flag_auth_completed = false; + + public ServerConnectionState(ServerConnection conn) { + this.conn = conn; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/AceFlags.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,17 @@ +package ch.ethz.ssh2.sftp; + +/** + * @version $Id: AceFlags.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public final class AceFlags { + private AceFlags() { + } + + public static final int ACE4_FILE_INHERIT_ACE = 0x00000001; + public static final int ACE4_DIRECTORY_INHERIT_ACE = 0x00000002; + public static final int ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004; + public static final int ACE4_INHERIT_ONLY_ACE = 0x00000008; + public static final int ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010; + public static final int ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020; + public static final int ACE4_IDENTIFIER_GROUP = 0x00000040; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/AceMask.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,28 @@ +package ch.ethz.ssh2.sftp; + +/** + * @version $Id: AceMask.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public final class AceMask { + private AceMask() { + } + + public static final int ACE4_READ_DATA = 0x00000001; + public static final int ACE4_LIST_DIRECTORY = 0x00000001; + public static final int ACE4_WRITE_DATA = 0x00000002; + public static final int ACE4_ADD_FILE = 0x00000002; + public static final int ACE4_APPEND_DATA = 0x00000004; + public static final int ACE4_ADD_SUBDIRECTORY = 0x00000004; + public static final int ACE4_READ_NAMED_ATTRS = 0x00000008; + public static final int ACE4_WRITE_NAMED_ATTRS = 0x00000010; + public static final int ACE4_EXECUTE = 0x00000020; + public static final int ACE4_DELETE_CHILD = 0x00000040; + public static final int ACE4_READ_ATTRIBUTES = 0x00000080; + public static final int ACE4_WRITE_ATTRIBUTES = 0x00000100; + public static final int ACE4_DELETE = 0x00010000; + public static final int ACE4_READ_ACL = 0x00020000; + public static final int ACE4_WRITE_ACL = 0x00040000; + public static final int ACE4_WRITE_OWNER = 0x00080000; + public static final int ACE4_SYNCHRONIZE = 0x00100000; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/AceType.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,16 @@ +package ch.ethz.ssh2.sftp; + +/** + * @version $Id: AceType.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public final class AceType { + + private AceType() { + } + + private static final int ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000; + private static final int ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001; + private static final int ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002; + private static final int ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/AclFlags.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,45 @@ +package ch.ethz.ssh2.sftp; + +/** + * @version $Id: AclFlags.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public final class AclFlags { + + /** + * If INCLUDED is set during a setstat operation, then the client + * intends to modify the ALLOWED/DENIED entries of the ACL. + * Otherwise, the client intends for these entries to be + * preserved. + */ + public static final int SFX_ACL_CONTROL_INCLUDED = 0x00000001; + /** + * If the PRESENT bit is not set, then the client wishes to remove + * control entries. If the server doesn't support separate + * control and audit information, the client MUST not clear this + * bit without also clearing the AUDIT_ALARM_PRESENT bit. + */ + public static final int SFX_ACL_CONTROL_PRESENT = 0x00000002; + /** + * If INHERITED is set, then ALLOW/DENY ACEs MAY be inherited from + * the parent directory. If it is off, then they MUST not be + * INHERITED. If the server does not support controlling + * inheritance, then the client MUST clear this bit; in this case + * the inheritance properties of the server are undefined. + */ + public static final int SFX_ACL_CONTROL_INHERITED = 0x00000004; + /** + * If INCLUDE is set during a setstat operation, then the client + * intends to modify the AUDIT/ALARM entries of the ACL. + * Otherwise, the client intends for these entries to be + * preserved. + */ + public static final int SFX_ACL_AUDIT_ALARM_INCLUDED = 0x00000010; + /** + * If INHERITED is set, then AUDIT/ALARM ACEs MAY be inherited + * from the parent directory. If it is off, then they MUST not be + * INHERITED. If the server does not support controlling + * inheritance, then the client MUST clear this bit; in this case + * the inheritance properties of the server are undefined. + */ + public static final int SFX_ACL_AUDIT_ALARM_INHERITED = 0x00000020; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/AttrTextHints.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.sftp; + +/** + * + * Values for the 'text-hint' field in the SFTP ATTRS data type. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + * + */ +public class AttrTextHints { + /** + * The server knows the file is a text file, and should be opened + * using the SSH_FXF_ACCESS_TEXT_MODE flag. + */ + public static final int SSH_FILEXFER_ATTR_KNOWN_TEXT = 0x00; + + /** + * The server has applied a heuristic or other mechanism and + * believes that the file should be opened with the + * SSH_FXF_ACCESS_TEXT_MODE flag. + */ + public static final int SSH_FILEXFER_ATTR_GUESSED_TEXT = 0x01; + + /** + * The server knows the file has binary content. + */ + public static final int SSH_FILEXFER_ATTR_KNOWN_BINARY = 0x02; + + /** + * The server has applied a heuristic or other mechanism and + * believes has binary content, and should not be opened with the + * SSH_FXF_ACCESS_TEXT_MODE flag. + */ + public static final int SSH_FILEXFER_ATTR_GUESSED_BINARY = 0x03; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/AttribBits.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.sftp; + +/** + * SFTP Attribute Bits for the "attrib-bits" and "attrib-bits-valid" fields + * of the SFTP ATTR data type. + * <p/> + * Yes, these are the "attrib-bits", even though they have "_FLAGS_" in + * their name. Don't ask - I did not invent it. + * <p/> + * "<i>These fields, taken together, reflect various attributes of the file + * or directory, on the server. Bits not set in 'attrib-bits-valid' MUST be + * ignored in the 'attrib-bits' field. This allows both the server and the + * client to communicate only the bits it knows about without inadvertently + * twiddling bits they don't understand.</i>" + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class AttribBits { + + private AttribBits() { + } + + /** + * Advisory, read-only bit. This bit is not part of the access + * control information on the file, but is rather an advisory field + * indicating that the file should not be written. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_READONLY = 0x00000001; + + /** + * The file is part of the operating system. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_SYSTEM = 0x00000002; + + /** + * File SHOULD NOT be shown to user unless specifically requested. + * For example, most UNIX systems SHOULD set this bit if the filename + * begins with a 'period'. This bit may be read-only (see section 5.4 of + * the SFTP standard draft). Most UNIX systems will not allow this to be + * changed. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_HIDDEN = 0x00000004; + + /** + * This attribute applies only to directories. This attribute is + * always read-only, and cannot be modified. This attribute means + * that files and directory names in this directory should be compared + * without regard to case. + * <p/> + * It is recommended that where possible, the server's filesystem be + * allowed to do comparisons. For example, if a client wished to prompt + * a user before overwriting a file, it should not compare the new name + * with the previously retrieved list of names in the directory. Rather, + * it should first try to create the new file by specifying + * SSH_FXF_CREATE_NEW flag. Then, if this fails and returns + * SSH_FX_FILE_ALREADY_EXISTS, it should prompt the user and then retry + * the create specifying SSH_FXF_CREATE_TRUNCATE. + * <p/> + * Unless otherwise specified, filenames are assumed to be case sensitive. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE = 0x00000008; + + /** + * The file should be included in backup / archive operations. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_ARCHIVE = 0x00000010; + + /** + * The file is stored on disk using file-system level transparent + * encryption. This flag does not affect the file data on the wire + * (for either READ or WRITE requests.) + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED = 0x00000020; + + /** + * The file is stored on disk using file-system level transparent + * compression. This flag does not affect the file data on the wire. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_COMPRESSED = 0x00000040; + + /** + * The file is a sparse file; this means that file blocks that have + * not been explicitly written are not stored on disk. For example, if + * a client writes a buffer at 10 M from the beginning of the file, + * the blocks between the previous EOF marker and the 10 M offset would + * not consume physical disk space. + * <p/> + * Some servers may store all files as sparse files, in which case + * this bit will be unconditionally set. Other servers may not have + * a mechanism for determining if the file is sparse, and so the file + * MAY be stored sparse even if this flag is not set. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_SPARSE = 0x00000080; + + /** + * Opening the file without either the SSH_FXF_ACCESS_APPEND_DATA or + * the SSH_FXF_ACCESS_APPEND_DATA_ATOMIC flag (see section 8.1.1.3 + * of the SFTP standard draft) MUST result in an + * SSH_FX_INVALID_PARAMETER error. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY = 0x00000100; + + /** + * The file cannot be deleted or renamed, no hard link can be created + * to this file, and no data can be written to the file. + * <p/> + * This bit implies a stronger level of protection than + * SSH_FILEXFER_ATTR_FLAGS_READONLY, the file permission mask or ACLs. + * Typically even the superuser cannot write to immutable files, and + * only the superuser can set or remove the bit. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE = 0x00000200; + + /** + * When the file is modified, the changes are written synchronously + * to the disk. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_SYNC = 0x00000400; + + /** + * The server MAY include this bit in a directory listing or realpath + * response. It indicates there was a failure in the translation to UTF-8. + * If this flag is included, the server SHOULD also include the + * UNTRANSLATED_NAME attribute. + */ + public static final int SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR = 0x00000800; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/AttribFlags.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.sftp; + +/** + * Attribute Flags. The 'valid-attribute-flags' field in + * the SFTP ATTRS data type specifies which of the fields are actually present. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class AttribFlags { + + private AttribFlags() { + } + + /** + * Indicates that the 'allocation-size' field is present. + */ + public static final int SSH_FILEXFER_ATTR_SIZE = 0x00000001; + + /** + * Protocol version 6: + * 0x00000002 was used in a previous version of this protocol. + * It is now a reserved value and MUST NOT appear in the mask. + * Some future version of this protocol may reuse this value. + */ + public static final int SSH_FILEXFER_ATTR_V3_UIDGID = 0x00000002; + + /** + * Indicates that the 'permissions' field is present. + */ + public static final int SSH_FILEXFER_ATTR_PERMISSIONS = 0x00000004; + + /** + * Indicates that the 'atime' and 'mtime' field are present + * (protocol v3). + */ + public static final int SSH_FILEXFER_ATTR_V3_ACMODTIME = 0x00000008; + + /** + * Indicates that the 'atime' field is present. + */ + public static final int SSH_FILEXFER_ATTR_ACCESSTIME = 0x00000008; + + /** + * Indicates that the 'createtime' field is present. + */ + public static final int SSH_FILEXFER_ATTR_CREATETIME = 0x00000010; + + /** + * Indicates that the 'mtime' field is present. + */ + public static final int SSH_FILEXFER_ATTR_MODIFYTIME = 0x00000020; + + /** + * Indicates that the 'acl' field is present. + */ + public static final int SSH_FILEXFER_ATTR_ACL = 0x00000040; + + /** + * Indicates that the 'owner' and 'group' fields are present. + */ + public static final int SSH_FILEXFER_ATTR_OWNERGROUP = 0x00000080; + + /** + * Indicates that additionally to the 'atime', 'createtime', + * 'mtime' and 'ctime' fields (if present), there is also + * 'atime-nseconds', 'createtime-nseconds', 'mtime-nseconds' + * and 'ctime-nseconds'. + */ + public static final int SSH_FILEXFER_ATTR_SUBSECOND_TIMES = 0x00000100; + + /** + * Indicates that the 'attrib-bits' and 'attrib-bits-valid' + * fields are present. + */ + public static final int SSH_FILEXFER_ATTR_BITS = 0x00000200; + + /** + * Indicates that the 'allocation-size' field is present. Field specifies the number of bytes that the + * file consumes on disk. + */ + public static final int SSH_FILEXFER_ATTR_ALLOCATION_SIZE = 0x00000400; + + /** + * Indicates that the 'text-hint' field is present. + */ + public static final int SSH_FILEXFER_ATTR_TEXT_HINT = 0x00000800; + + /** + * Indicates that the 'mime-type' field is present. + */ + public static final int SSH_FILEXFER_ATTR_MIME_TYPE = 0x00001000; + + /** + * Indicates that the 'link-count' field is present. + */ + public static final int SSH_FILEXFER_ATTR_LINK_COUNT = 0x00002000; + + /** + * Indicates that the 'untranslated-name' field is present. + */ + public static final int SSH_FILEXFER_ATTR_UNTRANSLATED_NAME = 0x00004000; + + /** + * Indicates that the 'ctime' field is present. + */ + public static final int SSH_FILEXFER_ATTR_CTIME = 0x00008000; + + /** + * Indicates that the 'extended-count' field (and probablby some + * 'extensions') is present. + */ + public static final int SSH_FILEXFER_ATTR_EXTENDED = 0x80000000; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/AttribPermissions.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.sftp; + +/** + * Permissions for the 'permissions' field in the SFTP ATTRS data type. + * <p/> + * "<i>The 'permissions' field contains a bit mask specifying file permissions. + * These permissions correspond to the st_mode field of the stat structure + * defined by POSIX [IEEE.1003-1.1996].</i>" + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class AttribPermissions { + private AttribPermissions() { + } + + /* Octal values! */ + + public static final int S_IRUSR = 0400; + public static final int S_IWUSR = 0200; + public static final int S_IXUSR = 0100; + public static final int S_IRGRP = 0040; + public static final int S_IWGRP = 0020; + public static final int S_IXGRP = 0010; + public static final int S_IROTH = 0004; + public static final int S_IWOTH = 0002; + public static final int S_IXOTH = 0001; + public static final int S_ISUID = 04000; + public static final int S_ISGID = 02000; + public static final int S_ISVTX = 01000; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/AttribTypes.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.sftp; + +/** + * Types for the 'type' field in the SFTP ATTRS data type. + * <p/> + * "<i>On a POSIX system, these values would be derived from the mode field + * of the stat structure. SPECIAL should be used for files that are of + * a known type which cannot be expressed in the protocol. UNKNOWN + * should be used if the type is not known.</i>" + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class AttribTypes { + private AttribTypes() { + } + + public static final int SSH_FILEXFER_TYPE_REGULAR = 1; + public static final int SSH_FILEXFER_TYPE_DIRECTORY = 2; + public static final int SSH_FILEXFER_TYPE_SYMLINK = 3; + public static final int SSH_FILEXFER_TYPE_SPECIAL = 4; + /** + * Should be used if the type is not known. + */ + public static final int SSH_FILEXFER_TYPE_UNKNOWN = 5; + public static final int SSH_FILEXFER_TYPE_SOCKET = 6; + public static final int SSH_FILEXFER_TYPE_CHAR_DEVICE = 7; + public static final int SSH_FILEXFER_TYPE_BLOCK_DEVICE = 8; + public static final int SSH_FILEXFER_TYPE_FIFO = 9; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/ErrorCodes.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.sftp; + +/** + * SFTP Error Codes + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class ErrorCodes { + private ErrorCodes() { + } + + public static final int SSH_FX_OK = 0; + public static final int SSH_FX_EOF = 1; + public static final int SSH_FX_NO_SUCH_FILE = 2; + public static final int SSH_FX_PERMISSION_DENIED = 3; + public static final int SSH_FX_FAILURE = 4; + public static final int SSH_FX_BAD_MESSAGE = 5; + public static final int SSH_FX_NO_CONNECTION = 6; + public static final int SSH_FX_CONNECTION_LOST = 7; + /** + * The server MUST respond with SSH_FXP_STATUS(SSH_FX_OP_UNSUPPORTED) if + * it receives a packet it does not recognize. + */ + public static final int SSH_FX_OP_UNSUPPORTED = 8; + public static final int SSH_FX_INVALID_HANDLE = 9; + public static final int SSH_FX_NO_SUCH_PATH = 10; + public static final int SSH_FX_FILE_ALREADY_EXISTS = 11; + public static final int SSH_FX_WRITE_PROTECT = 12; + public static final int SSH_FX_NO_MEDIA = 13; + public static final int SSH_FX_NO_SPACE_ON_FILESYSTEM = 14; + public static final int SSH_FX_QUOTA_EXCEEDED = 15; + public static final int SSH_FX_UNKNOWN_PRINCIPAL = 16; + public static final int SSH_FX_LOCK_CONFLICT = 17; + public static final int SSH_FX_DIR_NOT_EMPTY = 18; + public static final int SSH_FX_NOT_A_DIRECTORY = 19; + public static final int SSH_FX_INVALID_FILENAME = 20; + public static final int SSH_FX_LINK_LOOP = 21; + public static final int SSH_FX_CANNOT_DELETE = 22; + public static final int SSH_FX_INVALID_PARAMETER = 23; + public static final int SSH_FX_FILE_IS_A_DIRECTORY = 24; + public static final int SSH_FX_BYTE_RANGE_LOCK_CONFLICT = 25; + public static final int SSH_FX_BYTE_RANGE_LOCK_REFUSED = 26; + public static final int SSH_FX_DELETE_PENDING = 27; + public static final int SSH_FX_FILE_CORRUPT = 28; + public static final int SSH_FX_OWNER_INVALID = 29; + public static final int SSH_FX_GROUP_INVALID = 30; + public static final int SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK = 31; + + private static final String[][] messages = { + + {"SSH_FX_OK", "Indicates successful completion of the operation."}, + { + "SSH_FX_EOF", + "An attempt to read past the end-of-file was made; or, there are no more directory entries to return." + }, + {"SSH_FX_NO_SUCH_FILE", "A reference was made to a file which does not exist."}, + {"SSH_FX_PERMISSION_DENIED", "The user does not have sufficient permissions to perform the operation."}, + {"SSH_FX_FAILURE", "An error occurred, but no specific error code exists to describe the failure."}, + {"SSH_FX_BAD_MESSAGE", "A badly formatted packet or other SFTP protocol incompatibility was detected."}, + {"SSH_FX_NO_CONNECTION", "There is no connection to the server."}, + {"SSH_FX_CONNECTION_LOST", "The connection to the server was lost."}, + { + "SSH_FX_OP_UNSUPPORTED", + "An attempted operation could not be completed by the server because the server does not support the operation." + }, + {"SSH_FX_INVALID_HANDLE", "The handle value was invalid."}, + {"SSH_FX_NO_SUCH_PATH", "The file path does not exist or is invalid."}, + {"SSH_FX_FILE_ALREADY_EXISTS", "The file already exists."}, + {"SSH_FX_WRITE_PROTECT", "The file is on read-only media, or the media is write protected."}, + { + "SSH_FX_NO_MEDIA", + "The requested operation cannot be completed because there is no media available in the drive." + }, + { + "SSH_FX_NO_SPACE_ON_FILESYSTEM", + "The requested operation cannot be completed because there is insufficient free space on the filesystem." + }, + { + "SSH_FX_QUOTA_EXCEEDED", + "The operation cannot be completed because it would exceed the user's storage quota." + }, + { + "SSH_FX_UNKNOWN_PRINCIPAL", + "A principal referenced by the request (either the 'owner', 'group', or 'who' field of an ACL), was unknown. The error specific data contains the problematic names." + }, + {"SSH_FX_LOCK_CONFLICT", "The file could not be opened because it is locked by another process."}, + {"SSH_FX_DIR_NOT_EMPTY", "The directory is not empty."}, + {"SSH_FX_NOT_A_DIRECTORY", "The specified file is not a directory."}, + {"SSH_FX_INVALID_FILENAME", "The filename is not valid."}, + { + "SSH_FX_LINK_LOOP", + "Too many symbolic links encountered or, an SSH_FXF_NOFOLLOW open encountered a symbolic link as the final component." + }, + { + "SSH_FX_CANNOT_DELETE", + "The file cannot be deleted. One possible reason is that the advisory READONLY attribute-bit is set." + }, + { + "SSH_FX_INVALID_PARAMETER", + "One of the parameters was out of range, or the parameters specified cannot be used together." + }, + { + "SSH_FX_FILE_IS_A_DIRECTORY", + "The specified file was a directory in a context where a directory cannot be used." + }, + { + "SSH_FX_BYTE_RANGE_LOCK_CONFLICT", + " A read or write operation failed because another process's mandatory byte-range lock overlaps with the request." + }, + {"SSH_FX_BYTE_RANGE_LOCK_REFUSED", "A request for a byte range lock was refused."}, + {"SSH_FX_DELETE_PENDING", "An operation was attempted on a file for which a delete operation is pending."}, + {"SSH_FX_FILE_CORRUPT", "The file is corrupt; an filesystem integrity check should be run."}, + {"SSH_FX_OWNER_INVALID", "The principal specified can not be assigned as an owner of a file."}, + {"SSH_FX_GROUP_INVALID", "The principal specified can not be assigned as the primary group of a file."}, + { + "SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK", + "The requested operation could not be completed because the specifed byte range lock has not been granted." + }, + + }; + + public static final String[] getDescription(int errorCode) { + if ((errorCode < 0) || (errorCode >= messages.length)) { + return null; + } + + return messages[errorCode]; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/OpenFlags.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.sftp; + +/** + * SFTP Open Flags. + * <p/> + * The following table is provided to assist in mapping POSIX semantics + * to equivalent SFTP file open parameters: + * <p/> + * <ul> + * <li>O_RDONLY + * <ul><li>desired-access = READ_DATA | READ_ATTRIBUTES</li></ul> + * </li> + * </ul> + * <ul> + * <li>O_WRONLY + * <ul><li>desired-access = WRITE_DATA | WRITE_ATTRIBUTES</li></ul> + * </li> + * </ul> + * <ul> + * <li>O_RDWR + * <ul><li>desired-access = READ_DATA | READ_ATTRIBUTES | WRITE_DATA | WRITE_ATTRIBUTES</li></ul> + * </li> + * </ul> + * <ul> + * <li>O_APPEND + * <ul> + * <li>desired-access = WRITE_DATA | WRITE_ATTRIBUTES | APPEND_DATA</li> + * <li>flags = SSH_FXF_ACCESS_APPEND_DATA and or SSH_FXF_ACCESS_APPEND_DATA_ATOMIC</li> + * </ul> + * </li> + * </ul> + * <ul> + * <li>O_CREAT + * <ul> + * <li>flags = SSH_FXF_OPEN_OR_CREATE</li> + * </ul> + * </li> + * </ul> + * <ul> + * <li>O_TRUNC + * <ul> + * <li>flags = SSH_FXF_TRUNCATE_EXISTING</li> + * </ul> + * </li> + * </ul> + * <ul> + * <li>O_TRUNC|O_CREATE + * <ul> + * <li>flags = SSH_FXF_CREATE_TRUNCATE</li> + * </ul> + * </li> + * </ul> + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public final class OpenFlags { + private OpenFlags() { + } + + /** + * Disposition is a 3 bit field that controls how the file is opened. + * The server MUST support these bits (possible enumaration values: + * SSH_FXF_CREATE_NEW, SSH_FXF_CREATE_TRUNCATE, SSH_FXF_OPEN_EXISTING, + * SSH_FXF_OPEN_OR_CREATE or SSH_FXF_TRUNCATE_EXISTING). + */ + public static final int SSH_FXF_ACCESS_DISPOSITION = 0x00000007; + + /** + * A new file is created; if the file already exists, the server + * MUST return status SSH_FX_FILE_ALREADY_EXISTS. + */ + public static final int SSH_FXF_CREATE_NEW = 0x00000000; + + /** + * A new file is created; if the file already exists, it is opened + * and truncated. + */ + public static final int SSH_FXF_CREATE_TRUNCATE = 0x00000001; + + /** + * An existing file is opened. If the file does not exist, the + * server MUST return SSH_FX_NO_SUCH_FILE. If a directory in the + * path does not exist, the server SHOULD return + * SSH_FX_NO_SUCH_PATH. It is also acceptable if the server + * returns SSH_FX_NO_SUCH_FILE in this case. + */ + public static final int SSH_FXF_OPEN_EXISTING = 0x00000002; + + /** + * If the file exists, it is opened. If the file does not exist, + * it is created. + */ + public static final int SSH_FXF_OPEN_OR_CREATE = 0x00000003; + + /** + * An existing file is opened and truncated. If the file does not + * exist, the server MUST return the same error codes as defined + * for SSH_FXF_OPEN_EXISTING. + */ + public static final int SSH_FXF_TRUNCATE_EXISTING = 0x00000004; + + /** + * Data is always written at the end of the file. The offset field + * of the SSH_FXP_WRITE requests are ignored. + * <p/> + * Data is not required to be appended atomically. This means that + * if multiple writers attempt to append data simultaneously, data + * from the first may be lost. However, data MAY be appended + * atomically. + */ + public static final int SSH_FXF_ACCESS_APPEND_DATA = 0x00000008; + + /** + * Data is always written at the end of the file. The offset field + * of the SSH_FXP_WRITE requests are ignored. + * <p/> + * Data MUST be written atomically so that there is no chance that + * multiple appenders can collide and result in data being lost. + * <p/> + * If both append flags are specified, the server SHOULD use atomic + * append if it is available, but SHOULD use non-atomic appends + * otherwise. The server SHOULD NOT fail the request in this case. + */ + public static final int SSH_FXF_ACCESS_APPEND_DATA_ATOMIC = 0x00000010; + + /** + * Indicates that the server should treat the file as text and + * convert it to the canonical newline convention in use. + * (See Determining Server Newline Convention in section 5.3 in the + * SFTP standard draft). + * <p/> + * When a file is opened with this flag, the offset field in the read + * and write functions is ignored. + * <p/> + * Servers MUST process multiple, parallel reads and writes correctly + * in this mode. Naturally, it is permissible for them to do this by + * serializing the requests. + * <p/> + * Clients SHOULD use the SSH_FXF_ACCESS_APPEND_DATA flag to append + * data to a text file rather then using write with a calculated offset. + */ + public static final int SSH_FXF_ACCESS_TEXT_MODE = 0x00000020; + + /** + * The server MUST guarantee that no other handle has been opened + * with ACE4_READ_DATA access, and that no other handle will be + * opened with ACE4_READ_DATA access until the client closes the + * handle. (This MUST apply both to other clients and to other + * processes on the server.) + * <p/> + * If there is a conflicting lock the server MUST return + * SSH_FX_LOCK_CONFLICT. If the server cannot make the locking + * guarantee, it MUST return SSH_FX_OP_UNSUPPORTED. + * <p/> + * Other handles MAY be opened for ACE4_WRITE_DATA or any other + * combination of accesses, as long as ACE4_READ_DATA is not included + * in the mask. + */ + public static final int SSH_FXF_ACCESS_BLOCK_READ = 0x00000040; + + /** + * The server MUST guarantee that no other handle has been opened + * with ACE4_WRITE_DATA or ACE4_APPEND_DATA access, and that no other + * handle will be opened with ACE4_WRITE_DATA or ACE4_APPEND_DATA + * access until the client closes the handle. (This MUST apply both + * to other clients and to other processes on the server.) + * <p/> + * If there is a conflicting lock the server MUST return + * SSH_FX_LOCK_CONFLICT. If the server cannot make the locking + * guarantee, it MUST return SSH_FX_OP_UNSUPPORTED. + * <p/> + * Other handles MAY be opened for ACE4_READ_DATA or any other + * combination of accesses, as long as neither ACE4_WRITE_DATA nor + * ACE4_APPEND_DATA are included in the mask. + */ + public static final int SSH_FXF_ACCESS_BLOCK_WRITE = 0x00000080; + + /** + * The server MUST guarantee that no other handle has been opened + * with ACE4_DELETE access, opened with the + * SSH_FXF_ACCESS_DELETE_ON_CLOSE flag set, and that no other handle + * will be opened with ACE4_DELETE access or with the + * SSH_FXF_ACCESS_DELETE_ON_CLOSE flag set, and that the file itself + * is not deleted in any other way until the client closes the handle. + * <p/> + * If there is a conflicting lock the server MUST return + * SSH_FX_LOCK_CONFLICT. If the server cannot make the locking + * guarantee, it MUST return SSH_FX_OP_UNSUPPORTED. + */ + public static final int SSH_FXF_ACCESS_BLOCK_DELETE = 0x00000100; + + /** + * If this bit is set, the above BLOCK modes are advisory. In advisory + * mode, only other accesses that specify a BLOCK mode need be + * considered when determining whether the BLOCK can be granted, + * and the server need not prevent I/O operations that violate the + * block mode. + * <p/> + * The server MAY perform mandatory locking even if the BLOCK_ADVISORY + * bit is set. + */ + public static final int SSH_FXF_ACCESS_BLOCK_ADVISORY = 0x00000200; + + /** + * If the final component of the path is a symlink, then the open + * MUST fail, and the error SSH_FX_LINK_LOOP MUST be returned. + */ + public static final int SSH_FXF_ACCESS_NOFOLLOW = 0x00000400; + + /** + * The file should be deleted when the last handle to it is closed. + * (The last handle may not be an sftp-handle.) This MAY be emulated + * by a server if the OS doesn't support it by deleting the file when + * this handle is closed. + * <p/> + * It is implementation specific whether the directory entry is + * removed immediately or when the handle is closed. + */ + public static final int SSH_FXF_ACCESS_DELETE_ON_CLOSE = 0x00000800; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/sftp/Packet.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.sftp; + +/** + * SFTP Paket Types + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class Packet { + public static final int SSH_FXP_INIT = 1; + public static final int SSH_FXP_VERSION = 2; + public static final int SSH_FXP_OPEN = 3; + public static final int SSH_FXP_CLOSE = 4; + public static final int SSH_FXP_READ = 5; + public static final int SSH_FXP_WRITE = 6; + public static final int SSH_FXP_LSTAT = 7; + public static final int SSH_FXP_FSTAT = 8; + public static final int SSH_FXP_SETSTAT = 9; + public static final int SSH_FXP_FSETSTAT = 10; + public static final int SSH_FXP_OPENDIR = 11; + public static final int SSH_FXP_READDIR = 12; + public static final int SSH_FXP_REMOVE = 13; + public static final int SSH_FXP_MKDIR = 14; + public static final int SSH_FXP_RMDIR = 15; + public static final int SSH_FXP_REALPATH = 16; + public static final int SSH_FXP_STAT = 17; + public static final int SSH_FXP_RENAME = 18; + public static final int SSH_FXP_READLINK = 19; + public static final int SSH_FXP_SYMLINK = 20; + public static final int SSH_FXP_LINK = 21; + + public static final int SSH_FXP_STATUS = 101; + public static final int SSH_FXP_HANDLE = 102; + public static final int SSH_FXP_DATA = 103; + public static final int SSH_FXP_NAME = 104; + public static final int SSH_FXP_ATTRS = 105; + + /** + * SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY packets can be used to + * implement extensions, which can be vendor specific. + */ + public static final int SSH_FXP_EXTENDED = 200; + /** + * SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY packets can be used to + * implement extensions, which can be vendor specific. + */ + public static final int SSH_FXP_EXTENDED_REPLY = 201; + + public static String forName(int type) { + switch (type) { + case SSH_FXP_INIT: + return "SSH_FXP_INIT"; + + case SSH_FXP_VERSION: + return "SSH_FXP_VERSION"; + + case SSH_FXP_OPEN: + return "SSH_FXP_OPEN"; + + case SSH_FXP_CLOSE: + return "SSH_FXP_CLOSE"; + + case SSH_FXP_READ: + return "SSH_FXP_READ"; + + case SSH_FXP_WRITE: + return "SSH_FXP_WRITE"; + + case SSH_FXP_LSTAT: + return "SSH_FXP_LSTAT"; + + case SSH_FXP_FSTAT: + return "SSH_FXP_FSTAT"; + + case SSH_FXP_SETSTAT: + return "SSH_FXP_SETSTAT"; + + case SSH_FXP_FSETSTAT: + return "SSH_FXP_FSETSTAT"; + + case SSH_FXP_OPENDIR: + return "SSH_FXP_OPENDIR"; + + case SSH_FXP_READDIR: + return "SSH_FXP_READDIR"; + + case SSH_FXP_REMOVE: + return "SSH_FXP_REMOVE"; + + case SSH_FXP_MKDIR: + return "SSH_FXP_MKDIR"; + + case SSH_FXP_RMDIR: + return "SSH_FXP_RMDIR"; + + case SSH_FXP_REALPATH: + return "SSH_FXP_REALPATH"; + + case SSH_FXP_STAT: + return "SSH_FXP_STAT"; + + case SSH_FXP_RENAME: + return "SSH_FXP_RENAME"; + + case SSH_FXP_READLINK: + return "SSH_FXP_READLINK"; + + case SSH_FXP_SYMLINK: + return "SSH_FXP_SYMLINK"; + + case SSH_FXP_STATUS: + return "SSH_FXP_STATUS"; + + case SSH_FXP_HANDLE: + return "SSH_FXP_HANDLE"; + + case SSH_FXP_DATA: + return "SSH_FXP_DATA"; + + case SSH_FXP_NAME: + return "SSH_FXP_NAME"; + + case SSH_FXP_ATTRS: + return "SSH_FXP_ATTRS"; + + case SSH_FXP_EXTENDED: + return "SSH_FXP_EXTENDED"; + + case SSH_FXP_EXTENDED_REPLY: + return "SSH_FXP_EXTENDED_REPLY"; + } + + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/signature/DSASHA1Verify.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,230 @@ + +package ch.ethz.ssh2.signature; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.SignatureException; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.packets.TypesWriter; + + +/** + * DSASHA1Verify. + * + * @author Christian Plattner, plattner@trilead.com + * @version $Id: DSASHA1Verify.java,v 1.2 2008/04/01 12:38:09 cplattne Exp $ + */ +public class DSASHA1Verify { + private static final Logger log = Logger.getLogger(DSASHA1Verify.class); + + public static DSAPublicKey decodeSSHDSAPublicKey(byte[] key) throws IOException { + TypesReader tr = new TypesReader(key); + String key_format = tr.readString(); + + if (key_format.equals("ssh-dss") == false) + throw new IllegalArgumentException("This is not a ssh-dss public key!"); + + BigInteger p = tr.readMPINT(); + BigInteger q = tr.readMPINT(); + BigInteger g = tr.readMPINT(); + BigInteger y = tr.readMPINT(); + + if (tr.remain() != 0) + throw new IOException("Padding in DSA public key!"); + + try { + KeyFactory kf = KeyFactory.getInstance("DSA"); + KeySpec ks = new DSAPublicKeySpec(y, p, q, g); + return (DSAPublicKey) kf.generatePublic(ks); + } + catch (NoSuchAlgorithmException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + catch (InvalidKeySpecException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + } + + public static byte[] encodeSSHDSAPublicKey(DSAPublicKey pk) throws IOException { + TypesWriter tw = new TypesWriter(); + tw.writeString("ssh-dss"); + DSAParams params = pk.getParams(); + tw.writeMPInt(params.getP()); + tw.writeMPInt(params.getQ()); + tw.writeMPInt(params.getG()); + tw.writeMPInt(pk.getY()); + return tw.getBytes(); + } + + /** + * Convert from Java's signature ASN.1 encoding to the SSH spec. + * <p> + * Java ASN.1 encoding: + * <pre> + * SEQUENCE ::= { + * r INTEGER, + * s INTEGER + * } + * </pre> + */ + public static byte[] encodeSSHDSASignature(byte[] ds) { + TypesWriter tw = new TypesWriter(); + tw.writeString("ssh-dss"); + int len, index; + index = 3; + len = ds[index++] & 0xff; + byte[] r = new byte[len]; + System.arraycopy(ds, index, r, 0, r.length); + index = index + len + 1; + len = ds[index++] & 0xff; + byte[] s = new byte[len]; + System.arraycopy(ds, index, s, 0, s.length); + byte[] a40 = new byte[40]; + /* Patch (unsigned) r and s into the target array. */ + int r_copylen = (r.length < 20) ? r.length : 20; + int s_copylen = (s.length < 20) ? s.length : 20; + System.arraycopy(r, r.length - r_copylen, a40, 20 - r_copylen, r_copylen); + System.arraycopy(s, s.length - s_copylen, a40, 40 - s_copylen, s_copylen); + tw.writeString(a40, 0, 40); + return tw.getBytes(); + } + + public static byte[] decodeSSHDSASignature(byte[] sig) throws IOException { + byte[] rsArray = null; + + if (sig.length == 40) { + /* OK, another broken SSH server. */ + rsArray = sig; + } + else { + /* Hopefully a server obeying the standard... */ + TypesReader tr = new TypesReader(sig); + String sig_format = tr.readString(); + + if (sig_format.equals("ssh-dss") == false) + throw new IOException("Peer sent wrong signature format"); + + rsArray = tr.readByteString(); + + if (rsArray.length != 40) + throw new IOException("Peer sent corrupt signature"); + + if (tr.remain() != 0) + throw new IOException("Padding in DSA signature!"); + } + + int i = 0; + int j = 0; + byte[] tmp; + + if (rsArray[0] == 0 && rsArray[1] == 0 && rsArray[2] == 0) { + j = ((rsArray[i++] << 24) & 0xff000000) | ((rsArray[i++] << 16) & 0x00ff0000) + | ((rsArray[i++] << 8) & 0x0000ff00) | ((rsArray[i++]) & 0x000000ff); + i += j; + j = ((rsArray[i++] << 24) & 0xff000000) | ((rsArray[i++] << 16) & 0x00ff0000) + | ((rsArray[i++] << 8) & 0x0000ff00) | ((rsArray[i++]) & 0x000000ff); + tmp = new byte[j]; + System.arraycopy(rsArray, i, tmp, 0, j); + rsArray = tmp; + } + + /* ASN.1 */ + int frst = ((rsArray[0] & 0x80) != 0 ? 1 : 0); + int scnd = ((rsArray[20] & 0x80) != 0 ? 1 : 0); + /* Calculate output length */ + int length = rsArray.length + 6 + frst + scnd; + tmp = new byte[length]; + /* DER-encoding to match Java */ + tmp[0] = (byte) 0x30; + + if (rsArray.length != 40) + throw new IOException("Peer sent corrupt signature"); + + /* Calculate length */ + tmp[1] = (byte) 0x2c; + tmp[1] += frst; + tmp[1] += scnd; + /* First item */ + tmp[2] = (byte) 0x02; + /* First item length */ + tmp[3] = (byte) 0x14; + tmp[3] += frst; + /* Copy in the data for first item */ + System.arraycopy(rsArray, 0, tmp, 4 + frst, 20); + /* Second item */ + tmp[4 + tmp[3]] = (byte) 0x02; + /* Second item length */ + tmp[5 + tmp[3]] = (byte) 0x14; + tmp[5 + tmp[3]] += scnd; + /* Copy in the data for the second item */ + System.arraycopy(rsArray, 20, tmp, 6 + tmp[3] + scnd, 20); + /* Swap buffers */ + rsArray = tmp; + return rsArray; + } + + public static boolean verifySignature(byte[] message, byte[] ds, DSAPublicKey dpk) throws IOException { + try { + Signature s = Signature.getInstance("SHA1withDSA"); + s.initVerify(dpk); + s.update(message); + return s.verify(ds); + } + catch (NoSuchAlgorithmException e) { + IOException ex = new IOException("No such algorithm"); + ex.initCause(e); + throw ex; + } + catch (InvalidKeyException e) { + IOException ex = new IOException("No such algorithm"); + ex.initCause(e); + throw ex; + } + catch (SignatureException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + } + + public static byte[] generateSignature(byte[] message, DSAPrivateKey pk, SecureRandom rnd) throws IOException { + try { + Signature s = Signature.getInstance("SHA1withDSA"); + s.initSign(pk); + s.update(message); + return s.sign(); + } + catch (NoSuchAlgorithmException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + catch (InvalidKeyException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + catch (SignatureException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/signature/ECDSASHA2Verify.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,488 @@ +/** + * + */ +package ch.ethz.ssh2.signature; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.Signature; +import java.security.SignatureException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.EllipticCurve; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.util.Map; +import java.util.TreeMap; + +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.packets.TypesWriter; + +/** + * @author Kenny Root + * + */ +public class ECDSASHA2Verify { + private static final Logger log = Logger.getLogger(ECDSASHA2Verify.class); + + public static final String ECDSA_SHA2_PREFIX = "ecdsa-sha2-"; + + private static final String NISTP256 = "nistp256"; + private static final String NISTP256_OID = "1.2.840.10045.3.1.7"; + private static final String NISTP384 = "nistp384"; + private static final String NISTP384_OID = "1.3.132.0.34"; + private static final String NISTP521 = "nistp521"; + private static final String NISTP521_OID = "1.3.132.0.35"; + + private static final Map<String, ECParameterSpec> CURVES = new TreeMap<String, ECParameterSpec>(); + static { + CURVES.put(NISTP256, EllipticCurves.nistp256); + CURVES.put(NISTP384, EllipticCurves.nistp384); + CURVES.put(NISTP521, EllipticCurves.nistp521); + } + + private static final Map<Integer, String> CURVE_SIZES = new TreeMap<Integer, String>(); + static { + CURVE_SIZES.put(256, NISTP256); + CURVE_SIZES.put(384, NISTP384); + CURVE_SIZES.put(521, NISTP521); + } + + private static final Map<String, String> CURVE_OIDS = new TreeMap<String, String>(); + static { + CURVE_OIDS.put(NISTP256_OID, NISTP256); + CURVE_OIDS.put(NISTP384_OID, NISTP256); + CURVE_OIDS.put(NISTP521_OID, NISTP256); + } + + public static int[] getCurveSizes() { + int[] keys = new int[CURVE_SIZES.size()]; + int i = 0; + + for (Integer n : CURVE_SIZES.keySet().toArray(new Integer[keys.length])) { + keys[i++] = n; + } + + return keys; + } + + public static ECParameterSpec getCurveForSize(int size) { + final String name = CURVE_SIZES.get(size); + + if (name == null) { + return null; + } + + return CURVES.get(name); + } + + public static ECPublicKey decodeSSHECDSAPublicKey(byte[] key) throws IOException { + TypesReader tr = new TypesReader(key); + String key_format = tr.readString(); + + if (key_format.startsWith(ECDSA_SHA2_PREFIX) == false) + throw new IllegalArgumentException("This is not an ECDSA public key"); + + String curveName = tr.readString(); + byte[] groupBytes = tr.readByteString(); + + if (tr.remain() != 0) + throw new IOException("Padding in ECDSA public key!"); + + if (key_format.equals(ECDSA_SHA2_PREFIX + curveName) == false) { + throw new IOException("Key format is inconsistent with curve name: " + key_format + + " != " + curveName); + } + + ECParameterSpec params = CURVES.get(curveName); + + if (params == null) { + throw new IOException("Curve is not supported: " + curveName); + } + + ECPoint group = ECDSASHA2Verify.decodeECPoint(groupBytes, params.getCurve()); + + if (group == null) { + throw new IOException("Invalid ECDSA group"); + } + + KeySpec keySpec = new ECPublicKeySpec(group, params); + + try { + KeyFactory kf = KeyFactory.getInstance("EC"); + return (ECPublicKey) kf.generatePublic(keySpec); + } + catch (NoSuchAlgorithmException nsae) { + IOException ioe = new IOException("No EC KeyFactory available"); + ioe.initCause(nsae); + throw ioe; + } + catch (InvalidKeySpecException ikse) { + IOException ioe = new IOException("No EC KeyFactory available"); + ioe.initCause(ikse); + throw ioe; + } + } + + public static byte[] encodeSSHECDSAPublicKey(ECPublicKey key) throws IOException { + TypesWriter tw = new TypesWriter(); + String curveName = getCurveName(key.getParams()); + String keyFormat = ECDSA_SHA2_PREFIX + curveName; + tw.writeString(keyFormat); + tw.writeString(curveName); + byte[] encoded = encodeECPoint(key.getW(), key.getParams().getCurve()); + tw.writeString(encoded, 0, encoded.length); + return tw.getBytes(); + } + + public static String getCurveName(ECParameterSpec params) throws IOException { + int fieldSize = getCurveSize(params); + final String curveName = getCurveName(fieldSize); + + if (curveName == null) { + throw new IOException("invalid curve size " + fieldSize); + } + + return curveName; + } + + public static String getCurveName(int fieldSize) { + String curveName = CURVE_SIZES.get(fieldSize); + + if (curveName == null) { + return null; + } + + return curveName; + } + + public static int getCurveSize(ECParameterSpec params) { + return params.getCurve().getField().getFieldSize(); + } + + public static ECParameterSpec getCurveForOID(String oid) { + String name = CURVE_OIDS.get(oid); + + if (name == null) + return null; + + return CURVES.get(name); + } + + public static byte[] decodeSSHECDSASignature(byte[] sig) throws IOException { + byte[] rsArray = null; + TypesReader tr = new TypesReader(sig); + String sig_format = tr.readString(); + + if (sig_format.startsWith(ECDSA_SHA2_PREFIX) == false) + throw new IOException("Peer sent wrong signature format"); + + String curveName = sig_format.substring(ECDSA_SHA2_PREFIX.length()); + + if (CURVES.containsKey(curveName) == false) { + throw new IOException("Unsupported curve: " + curveName); + } + + rsArray = tr.readByteString(); + + if (tr.remain() != 0) + throw new IOException("Padding in ECDSA signature!"); + + byte[] rArray; + byte[] sArray; + { + TypesReader rsReader = new TypesReader(rsArray); + rArray = rsReader.readMPINT().toByteArray(); + sArray = rsReader.readMPINT().toByteArray(); + } + int first = rArray.length; + int second = sArray.length; + + /* We can't have the high bit set, so add an extra zero at the beginning if so. */ + if ((rArray[0] & 0x80) != 0) { + first++; + } + + if ((sArray[0] & 0x80) != 0) { + second++; + } + + /* Calculate total output length */ + ByteArrayOutputStream os = new ByteArrayOutputStream(6 + first + second); + /* ASN.1 SEQUENCE tag */ + os.write(0x30); + /* Size of SEQUENCE */ + writeLength(4 + first + second, os); + /* ASN.1 INTEGER tag */ + os.write(0x02); + /* "r" INTEGER length */ + writeLength(first, os); + + /* Copy in the "r" INTEGER */ + if (first != rArray.length) { + os.write(0x00); + } + + os.write(rArray); + /* ASN.1 INTEGER tag */ + os.write(0x02); + /* "s" INTEGER length */ + writeLength(second, os); + + /* Copy in the "s" INTEGER */ + if (second != sArray.length) { + os.write(0x00); + } + + os.write(sArray); + return os.toByteArray(); + } + + private static final void writeLength(int length, OutputStream os) throws IOException { + if (length <= 0x7F) { + os.write(length); + return; + } + + int numOctets = 0; + int lenCopy = length; + + while (lenCopy != 0) { + lenCopy >>>= 8; + numOctets++; + } + + os.write(0x80 | numOctets); + + for (int i = (numOctets - 1) * 8; i >= 0; i -= 8) { + os.write((byte)(length >> i)); + } + } + + public static byte[] encodeSSHECDSASignature(byte[] sig, ECParameterSpec params) throws IOException { + TypesWriter tw = new TypesWriter(); + String curveName = getCurveName(params); + tw.writeString(ECDSA_SHA2_PREFIX + curveName); + + if ((sig[0] != 0x30) || (sig[1] != sig.length - 2) || (sig[2] != 0x02)) { + throw new IOException("Invalid signature format"); + } + + int rLength = sig[3]; + + if ((rLength + 6 > sig.length) || (sig[4 + rLength] != 0x02)) { + throw new IOException("Invalid signature format"); + } + + int sLength = sig[5 + rLength]; + + if (6 + rLength + sLength > sig.length) { + throw new IOException("Invalid signature format"); + } + + byte[] rArray = new byte[rLength]; + byte[] sArray = new byte[sLength]; + System.arraycopy(sig, 4, rArray, 0, rLength); + System.arraycopy(sig, 6 + rLength, sArray, 0, sLength); + BigInteger r = new BigInteger(rArray); + BigInteger s = new BigInteger(sArray); + // Write the <r,s> to its own types writer. + TypesWriter rsWriter = new TypesWriter(); + rsWriter.writeMPInt(r); + rsWriter.writeMPInt(s); + byte[] encoded = rsWriter.getBytes(); + tw.writeString(encoded, 0, encoded.length); + return tw.getBytes(); + } + + public static byte[] generateSignature(byte[] message, ECPrivateKey pk) throws IOException { + final String algo = getSignatureAlgorithmForParams(pk.getParams()); + + try { + Signature s = Signature.getInstance(algo); + s.initSign(pk); + s.update(message); + return s.sign(); + } + catch (NoSuchAlgorithmException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + catch (InvalidKeyException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + catch (SignatureException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + } + + public static boolean verifySignature(byte[] message, byte[] ds, ECPublicKey dpk) throws IOException { + final String algo = getSignatureAlgorithmForParams(dpk.getParams()); + + try { + Signature s = Signature.getInstance(algo); + s.initVerify(dpk); + s.update(message); + return s.verify(ds); + } + catch (NoSuchAlgorithmException e) { + IOException ex = new IOException("No such algorithm"); + ex.initCause(e); + throw ex; + } + catch (InvalidKeyException e) { + IOException ex = new IOException("No such algorithm"); + ex.initCause(e); + throw ex; + } + catch (SignatureException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + } + + private static String getSignatureAlgorithmForParams(ECParameterSpec params) { + int size = getCurveSize(params); + + if (size <= 256) { + return "SHA256withECDSA"; + } + else if (size <= 384) { + return "SHA384withECDSA"; + } + else { + return "SHA512withECDSA"; + } + } + + public static String getDigestAlgorithmForParams(ECParameterSpec params) { + int size = getCurveSize(params); + + if (size <= 256) { + return "SHA256"; + } + else if (size <= 384) { + return "SHA384"; + } + else { + return "SHA512"; + } + } + + /** + * Decode an OctetString to EllipticCurvePoint according to SECG 2.3.4 + */ + public static ECPoint decodeECPoint(byte[] M, EllipticCurve curve) { + if (M.length == 0) { + return null; + } + + // M has len 2 ceil(log_2(q)/8) + 1 ? + int elementSize = (curve.getField().getFieldSize() + 7) / 8; + + if (M.length != 2 * elementSize + 1) { + return null; + } + + // step 3.2 + if (M[0] != 0x04) { + return null; + } + + // Step 3.3 + byte[] xp = new byte[elementSize]; + System.arraycopy(M, 1, xp, 0, elementSize); + // Step 3.4 + byte[] yp = new byte[elementSize]; + System.arraycopy(M, 1 + elementSize, yp, 0, elementSize); + ECPoint P = new ECPoint(new BigInteger(1, xp), new BigInteger(1, yp)); + // TODO check point 3.5 + // Step 3.6 + return P; + } + + /** + * Encode EllipticCurvePoint to an OctetString + */ + public static byte[] encodeECPoint(ECPoint group, EllipticCurve curve) { + // M has len 2 ceil(log_2(q)/8) + 1 ? + int elementSize = (curve.getField().getFieldSize() + 7) / 8; + byte[] M = new byte[2 * elementSize + 1]; + // Uncompressed format + M[0] = 0x04; + { + byte[] affineX = removeLeadingZeroes(group.getAffineX().toByteArray()); + System.arraycopy(affineX, 0, M, 1 + elementSize - affineX.length, affineX.length); + } + { + byte[] affineY = removeLeadingZeroes(group.getAffineY().toByteArray()); + System.arraycopy(affineY, 0, M, 1 + elementSize + elementSize - affineY.length, + affineY.length); + } + return M; + } + + private static byte[] removeLeadingZeroes(byte[] input) { + if (input[0] != 0x00) { + return input; + } + + int pos = 1; + + while (pos < input.length - 1 && input[pos] == 0x00) { + pos++; + } + + byte[] output = new byte[input.length - pos]; + System.arraycopy(input, pos, output, 0, output.length); + return output; + } + + public static class EllipticCurves { + public static ECParameterSpec nistp256 = new ECParameterSpec( + new EllipticCurve( + new ECFieldFp(new BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16)), + new BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)), + new ECPoint(new BigInteger("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 16), + new BigInteger("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", 16)), + new BigInteger("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 16), + 1); + + public static ECParameterSpec nistp384 = new ECParameterSpec( + new EllipticCurve( + new ECFieldFp(new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", 16)), + new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", 16), + new BigInteger("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", 16)), + new ECPoint(new BigInteger("AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", 16), + new BigInteger("3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", 16)), + new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", 16), + 1); + + public static ECParameterSpec nistp521 = new ECParameterSpec( + new EllipticCurve( + new ECFieldFp(new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16)), + new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", 16), + new BigInteger("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 16)), + new ECPoint(new BigInteger("00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", 16), + new BigInteger("011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", 16)), + new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 16), + 1); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/signature/RSASHA1Verify.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,174 @@ + +package ch.ethz.ssh2.signature; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.Signature; +import java.security.SignatureException; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.RSAPublicKeySpec; + +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.TypesReader; +import ch.ethz.ssh2.packets.TypesWriter; + + +/** + * RSASHA1Verify. + * + * @author Christian Plattner, plattner@trilead.com + * @version $Id: RSASHA1Verify.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $ + */ +public class RSASHA1Verify { + private static final Logger log = Logger.getLogger(RSASHA1Verify.class); + + public static RSAPublicKey decodeSSHRSAPublicKey(byte[] key) throws IOException { + TypesReader tr = new TypesReader(key); + String key_format = tr.readString(); + + if (key_format.equals("ssh-rsa") == false) + throw new IllegalArgumentException("This is not a ssh-rsa public key"); + + BigInteger e = tr.readMPINT(); + BigInteger n = tr.readMPINT(); + + if (tr.remain() != 0) + throw new IOException("Padding in RSA public key!"); + + KeySpec keySpec = new RSAPublicKeySpec(n, e); + + try { + KeyFactory kf = KeyFactory.getInstance("RSA"); + return (RSAPublicKey) kf.generatePublic(keySpec); + } + catch (NoSuchAlgorithmException nsae) { + IOException ioe = new IOException("No RSA KeyFactory available"); + ioe.initCause(nsae); + throw ioe; + } + catch (InvalidKeySpecException ikse) { + IOException ioe = new IOException("No RSA KeyFactory available"); + ioe.initCause(ikse); + throw ioe; + } + } + + public static byte[] encodeSSHRSAPublicKey(RSAPublicKey pk) throws IOException { + TypesWriter tw = new TypesWriter(); + tw.writeString("ssh-rsa"); + tw.writeMPInt(pk.getPublicExponent()); + tw.writeMPInt(pk.getModulus()); + return tw.getBytes(); + } + + public static byte[] decodeSSHRSASignature(byte[] sig) throws IOException { + TypesReader tr = new TypesReader(sig); + String sig_format = tr.readString(); + + if (sig_format.equals("ssh-rsa") == false) + throw new IOException("Peer sent wrong signature format"); + + /* S is NOT an MPINT. "The value for 'rsa_signature_blob' is encoded as a string + * containing s (which is an integer, without lengths or padding, unsigned and in + * network byte order)." See also below. + */ + byte[] s = tr.readByteString(); + + if (s.length == 0) + throw new IOException("Error in RSA signature, S is empty."); + + if (log.isEnabled()) { + log.info("Decoding ssh-rsa signature string (length: " + s.length + ")"); + } + + if (tr.remain() != 0) + throw new IOException("Padding in RSA signature!"); + + if (s[0] == 0 && s[1] == 0 && s[2] == 0) { + int i = 0; + int j = ((s[i++] << 24) & 0xff000000) | ((s[i++] << 16) & 0x00ff0000) + | ((s[i++] << 8) & 0x0000ff00) | ((s[i++]) & 0x000000ff); + i += j; + j = ((s[i++] << 24) & 0xff000000) | ((s[i++] << 16) & 0x00ff0000) + | ((s[i++] << 8) & 0x0000ff00) | ((s[i++]) & 0x000000ff); + byte[] tmp = new byte[j]; + System.arraycopy(s, i, tmp, 0, j); + sig = tmp; + } + + return s; + } + + public static byte[] encodeSSHRSASignature(byte[] s) throws IOException { + TypesWriter tw = new TypesWriter(); + tw.writeString("ssh-rsa"); + + /* S is NOT an MPINT. "The value for 'rsa_signature_blob' is encoded as a string + * containing s (which is an integer, without lengths or padding, unsigned and in + * network byte order)." + */ + + /* Remove first zero sign byte, if present */ + + if ((s.length > 1) && (s[0] == 0x00)) + tw.writeString(s, 1, s.length - 1); + else + tw.writeString(s, 0, s.length); + + return tw.getBytes(); + } + + public static byte[] generateSignature(byte[] message, RSAPrivateKey pk) throws IOException { + try { + Signature s = Signature.getInstance("SHA1withRSA"); + s.initSign(pk); + s.update(message); + return s.sign(); + } + catch (NoSuchAlgorithmException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + catch (InvalidKeyException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + catch (SignatureException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + } + + public static boolean verifySignature(byte[] message, byte[] ds, RSAPublicKey dpk) throws IOException { + try { + Signature s = Signature.getInstance("SHA1withRSA"); + s.initVerify(dpk); + s.update(message); + return s.verify(ds); + } + catch (NoSuchAlgorithmException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + catch (InvalidKeyException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + catch (SignatureException e) { + IOException ex = new IOException(); + ex.initCause(e); + throw ex; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/ClientKexManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.transport; + +import java.io.IOException; +import java.security.DigestException; +import java.security.SecureRandom; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey; + +import ch.ethz.ssh2.ConnectionInfo; +import ch.ethz.ssh2.PacketTypeException; +import ch.ethz.ssh2.ServerHostKeyVerifier; +import ch.ethz.ssh2.compression.CompressionFactory; +import ch.ethz.ssh2.compression.Compressor; +import ch.ethz.ssh2.crypto.CryptoWishList; +import ch.ethz.ssh2.crypto.cipher.BlockCipher; +import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; +import ch.ethz.ssh2.crypto.dh.GenericDhExchange; +import ch.ethz.ssh2.crypto.dh.DhGroupExchange; +import ch.ethz.ssh2.crypto.digest.MAC; +import ch.ethz.ssh2.packets.PacketKexDHInit; +import ch.ethz.ssh2.packets.PacketKexDHReply; +import ch.ethz.ssh2.packets.PacketKexDhGexGroup; +import ch.ethz.ssh2.packets.PacketKexDhGexInit; +import ch.ethz.ssh2.packets.PacketKexDhGexReply; +import ch.ethz.ssh2.packets.PacketKexDhGexRequest; +import ch.ethz.ssh2.packets.PacketKexDhGexRequestOld; +import ch.ethz.ssh2.packets.PacketKexInit; +import ch.ethz.ssh2.packets.Packets; +import ch.ethz.ssh2.signature.DSASHA1Verify; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; +import ch.ethz.ssh2.signature.RSASHA1Verify; + +/** + * @version $Id: ClientKexManager.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public class ClientKexManager extends KexManager { + + private final ServerHostKeyVerifier verifier; + + private final String hostname; + + private final int port; + + public ClientKexManager(TransportManager tm, ClientServerHello csh, CryptoWishList initialCwl, String hostname, int port, + ServerHostKeyVerifier keyVerifier, SecureRandom rnd) { + super(tm, csh, initialCwl, rnd); + this.hostname = hostname; + this.port = port; + this.verifier = keyVerifier; + } + + protected boolean verifySignature(byte[] sig, byte[] hostkey) throws IOException { + if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) { + byte[] rs = ECDSASHA2Verify.decodeSSHECDSASignature(sig); + ECPublicKey epk = ECDSASHA2Verify.decodeSSHECDSAPublicKey(hostkey); + log.debug("Verifying ecdsa signature"); + return ECDSASHA2Verify.verifySignature(kxs.H, rs, epk); + } + + if (kxs.np.server_host_key_algo.equals("ssh-rsa")) { + byte[] rs = RSASHA1Verify.decodeSSHRSASignature(sig); + RSAPublicKey rpk = RSASHA1Verify.decodeSSHRSAPublicKey(hostkey); + log.debug("Verifying ssh-rsa signature"); + return RSASHA1Verify.verifySignature(kxs.H, rs, rpk); + } + + if (kxs.np.server_host_key_algo.equals("ssh-dss")) { + byte[] ds = DSASHA1Verify.decodeSSHDSASignature(sig); + DSAPublicKey dpk = DSASHA1Verify.decodeSSHDSAPublicKey(hostkey); + log.debug("Verifying ssh-dss signature"); + return DSASHA1Verify.verifySignature(kxs.H, ds, dpk); + } + + throw new IOException("Unknown server host key algorithm '" + kxs.np.server_host_key_algo + "'"); + } + + public void handleFailure(final IOException failure) { + synchronized (accessLock) { + connectionClosed = true; + accessLock.notifyAll(); + } + } + + public synchronized void handleMessage(byte[] msg) throws IOException { + PacketKexInit kip; + + if (msg == null) { + synchronized (accessLock) { + connectionClosed = true; + accessLock.notifyAll(); + return; + } + } + + log.debug(String.format("client kex manager, packet type %d", msg[0])); + + if ((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) { + throw new PacketTypeException(msg[0]); + } + + if (ignore_next_kex_packet) { + ignore_next_kex_packet = false; + return; + } + + if (msg[0] == Packets.SSH_MSG_KEXINIT) { + if ((kxs != null) && (kxs.state != 0)) { + throw new PacketTypeException(msg[0]); + } + + if (kxs == null) { + /* + * Ah, OK, peer wants to do KEX. Let's be nice and play + * together. + */ + kxs = new KexState(); + kxs.dhgexParameters = nextKEXdhgexParameters; + kip = new PacketKexInit(nextKEXcryptoWishList, rnd); + kxs.localKEX = kip; + tm.sendKexMessage(kip.getPayload()); + } + + kip = new PacketKexInit(msg); + kxs.remoteKEX = kip; + kxs.np = mergeKexParameters(kxs.localKEX.getKexParameters(), kxs.remoteKEX.getKexParameters()); + + if (kxs.np == null) + throw new IOException("Cannot negotiate, proposals do not match."); + + if (kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) { + // Guess was wrong, we need to ignore the next kex packet. + ignore_next_kex_packet = true; + } + + if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1") || + kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha256")) { + if (kxs.dhgexParameters.getMin_group_len() == 0) { + PacketKexDhGexRequestOld dhgexreq = new PacketKexDhGexRequestOld(kxs.dhgexParameters); + tm.sendKexMessage(dhgexreq.getPayload()); + } + else { + PacketKexDhGexRequest dhgexreq = new PacketKexDhGexRequest(kxs.dhgexParameters); + tm.sendKexMessage(dhgexreq.getPayload()); + } + + if (kxs.np.kex_algo.endsWith("sha1")) { + kxs.hashAlgo = "SHA1"; + } + else { + kxs.hashAlgo = "SHA2"; + } + + kxs.state = 1; + return; + } + + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || + kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp256") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp384") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) { + kxs.dhx = GenericDhExchange.getInstance(kxs.np.kex_algo); + kxs.dhx.init(kxs.np.kex_algo); + kxs.hashAlgo = kxs.dhx.getHashAlgo(); + PacketKexDHInit kp = new PacketKexDHInit(kxs.dhx.getE()); + tm.sendKexMessage(kp.getPayload()); + kxs.state = 1; + return; + } + + throw new IllegalStateException("Unkown KEX method!"); + } + + if (msg[0] == Packets.SSH_MSG_NEWKEYS) { + if (km == null) { + throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!"); + } + + BlockCipher cbc; + MAC mac; + Compressor comp; + + try { + cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_server_to_client, false, + km.enc_key_server_to_client, km.initial_iv_server_to_client); + + try { + mac = new MAC(kxs.np.mac_algo_server_to_client, km.integrity_key_server_to_client); + } + catch (DigestException e) { + throw new IOException(e); + } + + comp = CompressionFactory.createCompressor(kxs.np.comp_algo_server_to_client); + } + catch (IllegalArgumentException e) { + throw new IOException(e.getMessage()); + } + + tm.changeRecvCipher(cbc, mac); + tm.changeRecvCompression(comp); + ConnectionInfo sci = new ConnectionInfo(); + kexCount++; + sci.keyExchangeAlgorithm = kxs.np.kex_algo; + sci.keyExchangeCounter = kexCount; + sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server; + sci.serverToClientCryptoAlgorithm = kxs.np.enc_algo_server_to_client; + sci.clientToServerMACAlgorithm = kxs.np.mac_algo_client_to_server; + sci.serverToClientMACAlgorithm = kxs.np.mac_algo_server_to_client; + sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo; + sci.serverHostKey = kxs.remote_hostkey; + + synchronized (accessLock) { + lastConnInfo = sci; + accessLock.notifyAll(); + } + + kxs = null; + return; + } + + if ((kxs == null) || (kxs.state == 0)) { + throw new IOException("Unexpected Kex submessage!"); + } + + if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1") || + kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha256")) { + if (kxs.state == 1) { + PacketKexDhGexGroup dhgexgrp = new PacketKexDhGexGroup(msg); + kxs.dhgx = new DhGroupExchange(dhgexgrp.getP(), dhgexgrp.getG()); + kxs.dhgx.init(rnd); + PacketKexDhGexInit dhgexinit = new PacketKexDhGexInit(kxs.dhgx.getE()); + tm.sendKexMessage(dhgexinit.getPayload()); + kxs.state = 2; + return; + } + + if (kxs.state == 2) { + PacketKexDhGexReply dhgexrpl = new PacketKexDhGexReply(msg); + kxs.remote_hostkey = dhgexrpl.getHostKey(); + + if (verifier != null) { + try { + if (!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) { + throw new IOException("The server host key was not accepted by the verifier callback"); + } + } + catch (Exception e) { + throw new IOException( + "The server host key was not accepted by the verifier callback.", e); + } + } + + kxs.dhgx.setF(dhgexrpl.getF()); + + try { + kxs.H = kxs.dhgx.calculateH(kxs.hashAlgo, csh.getClientString(), csh.getServerString(), + kxs.localKEX.getPayload(), kxs.remoteKEX.getPayload(), dhgexrpl.getHostKey(), + kxs.dhgexParameters); + } + catch (IllegalArgumentException e) { + throw new IOException("KEX error.", e); + } + + if (!verifySignature(dhgexrpl.getSignature(), kxs.remote_hostkey)) { + throw new IOException("Invalid remote host key signature"); + } + + kxs.K = kxs.dhgx.getK(); + finishKex(true); + kxs.state = -1; + return; + } + + throw new IllegalStateException("Illegal State in KEX Exchange!"); + } + + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || + kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp256") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp384") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) { + if (kxs.state == 1) { + PacketKexDHReply dhr = new PacketKexDHReply(msg); + kxs.remote_hostkey = dhr.getHostKey(); + + if (verifier != null) { + try { + if (!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) { + throw new IOException("The server host key was not accepted by the verifier callback"); + } + } + catch (Exception e) { + throw new IOException("The server host key was not accepted by the verifier callback", e); + } + } + + kxs.dhx.setF(dhr.getF().toByteArray()); + + try { + kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(), kxs.localKEX.getPayload(), + kxs.remoteKEX.getPayload(), dhr.getHostKey()); + } + catch (IllegalArgumentException e) { + throw new IOException("KEX error.", e); + } + + if (!verifySignature(dhr.getSignature(), kxs.remote_hostkey)) { + throw new IOException("Invalid remote host key signature"); + } + + kxs.K = kxs.dhx.getK(); + finishKex(true); + kxs.state = -1; + return; + } + } + + throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/ClientServerHello.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2.transport; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.OutputStream; + +import ch.ethz.ssh2.util.StringEncoder; + +/** + * @author Christian Plattner + * @version $Id: ClientServerHello.java 155 2014-04-28 12:01:19Z dkocher@sudo.ch $ + */ +public class ClientServerHello { + private final String client_line; + private final String server_line; + + public final static int readLineRN(InputStream is, byte[] buffer) throws IOException { + int pos = 0; + boolean need10 = false; + int len = 0; + + while (true) { + int c = is.read(); + + if (c == -1) + throw new IOException("Premature connection close"); + + buffer[pos++] = (byte) c; + + if (c == 13) { + need10 = true; + continue; + } + + if (c == 10) + break; + + if (need10 == true) + throw new IOException("Malformed line sent by the server, the line does not end correctly."); + + len++; + + if (pos >= buffer.length) + throw new IOException("The server sent a too long line."); + } + + return len; + } + + private ClientServerHello(String client_line, String server_line) { + this.client_line = client_line; + this.server_line = server_line; + } + + public static ClientServerHello clientHello(String softwareversion, InputStream bi, OutputStream bo) + throws IOException { + return exchange(softwareversion, bi, bo, true); + } + + public static ClientServerHello serverHello(String softwareversion, InputStream bi, OutputStream bo) + throws IOException { + return exchange(softwareversion, bi, bo, false); + } + + private static ClientServerHello exchange(String softwareversion, InputStream bi, OutputStream bo, boolean clientMode) + throws IOException { + String localIdentifier = String.format("SSH-2.0-%s", softwareversion); + bo.write(StringEncoder.GetBytes(String.format("%s\r\n", localIdentifier))); + bo.flush(); + // Expect SSH-protoversion-softwareversion SP comments CR LF + byte[] serverVersion = new byte[512]; + String remoteIdentifier = null; + for (int i = 0; i < 50; i++) { + int len = readLineRN(bi, serverVersion); + remoteIdentifier = new String(serverVersion, 0, len, "ISO-8859-1"); + if (remoteIdentifier.startsWith("SSH-")) break; + } + + if (remoteIdentifier.equals("")) { + throw new IOException("Premature connection close"); + } + + if (!remoteIdentifier.startsWith("SSH-")) { + throw new IOException(String.format("Malformed SSH identification %s", remoteIdentifier)); + } + + if (!remoteIdentifier.startsWith("SSH-1.99-") + && !remoteIdentifier.startsWith("SSH-2.0-")) { + throw new IOException(String.format("Incompatible remote protocol version %s", remoteIdentifier)); + } + + if (clientMode) { + return new ClientServerHello(localIdentifier, remoteIdentifier); + } + else { + return new ClientServerHello(remoteIdentifier, localIdentifier); + } + } + + /** + * @return Returns the client_versioncomment. + */ + public byte[] getClientString() { + return StringEncoder.GetBytes(client_line); + } + + /** + * @return Returns the server_versioncomment. + */ + public byte[] getServerString() { + return StringEncoder.GetBytes(server_line); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/ClientTransportManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +package ch.ethz.ssh2.transport; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.security.SecureRandom; + +import ch.ethz.ssh2.DHGexParameters; +import ch.ethz.ssh2.ServerHostKeyVerifier; +import ch.ethz.ssh2.crypto.CryptoWishList; + +/** + * @version $Id: ClientTransportManager.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class ClientTransportManager extends TransportManager { + + private final Socket sock; + + public ClientTransportManager(final Socket socket) { + super(socket); + this.sock = socket; + } + + public void setTcpNoDelay(boolean state) throws IOException { + sock.setTcpNoDelay(state); + } + + public void setSoTimeout(int timeout) throws IOException { + sock.setSoTimeout(timeout); + } + + public void connect(String hostname, int port, String softwareversion, CryptoWishList cwl, + ServerHostKeyVerifier verifier, DHGexParameters dhgex, int connectTimeout, SecureRandom rnd) + throws IOException { + // Establish the TCP connection to the SSH-2 server + this.connect(hostname, port, connectTimeout); + // Parse the server line and say hello - important: this information is later needed for the + // key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object + // for later use. + ClientServerHello csh = ClientServerHello.clientHello(softwareversion, sock.getInputStream(), + sock.getOutputStream()); + TransportConnection tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), rnd); + KexManager km = new ClientKexManager(this, csh, cwl, hostname, port, verifier, rnd); + super.init(tc, km); + km.initiateKEX(cwl, dhgex, null, null, null); + this.startReceiver(); + } + + protected void connect(String hostname, int port, int connectTimeout) throws IOException { + log.debug(String.format("client transport manager connecting to %s:%d", hostname, port)); + sock.connect(new InetSocketAddress(hostname, port), connectTimeout); + log.debug(String.format("client transport manager connected to %s:%d", hostname, port)); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/DisconnectException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,22 @@ +package ch.ethz.ssh2.transport; + +import java.io.IOException; + +import ch.ethz.ssh2.packets.PacketDisconnect; + +/** + * @version $Id: DisconnectException.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public class DisconnectException extends IOException { + + private PacketDisconnect.Reason reason; + + public DisconnectException(final PacketDisconnect.Reason reason, final String message) { + super(message); + this.reason = reason; + } + + public PacketDisconnect.Reason getReason() { + return reason; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/HTTPProxyClientTransportManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,103 @@ +package ch.ethz.ssh2.transport; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Socket; + +import ch.ethz.ssh2.HTTPProxyData; +import ch.ethz.ssh2.HTTPProxyException; +import ch.ethz.ssh2.crypto.Base64; +import ch.ethz.ssh2.util.StringEncoder; + +/** + * @version $Id: HTTPProxyClientTransportManager.java 155 2014-04-28 12:01:19Z dkocher@sudo.ch $ + */ +public class HTTPProxyClientTransportManager extends ClientTransportManager { + + /** + * Used to tell the library that the connection shall be established through a proxy server. + */ + + private HTTPProxyData pd; + + private final Socket sock; + + public HTTPProxyClientTransportManager(final Socket socket, final HTTPProxyData pd) { + super(socket); + this.sock = socket; + this.pd = pd; + } + + @Override + protected void connect(final String hostname, final int port, final int connectTimeout) throws IOException { + sock.connect(new InetSocketAddress(pd.proxyHost, pd.proxyPort), connectTimeout); + // Tell the proxy where we actually want to connect to + StringBuilder sb = new StringBuilder(); + sb.append("CONNECT "); + sb.append(hostname); + sb.append(':'); + sb.append(port); + sb.append(" HTTP/1.0\r\n"); + + if ((pd.proxyUser != null) && (pd.proxyPass != null)) { + String credentials = pd.proxyUser + ":" + pd.proxyPass; + char[] encoded = Base64.encode(StringEncoder.GetBytes(credentials)); + sb.append("Proxy-Authorization: Basic "); + sb.append(encoded); + sb.append("\r\n"); + } + + if (pd.requestHeaderLines != null) { + for (int i = 0; i < pd.requestHeaderLines.length; i++) { + if (pd.requestHeaderLines[i] != null) { + sb.append(pd.requestHeaderLines[i]); + sb.append("\r\n"); + } + } + } + + sb.append("\r\n"); + OutputStream out = sock.getOutputStream(); + out.write(StringEncoder.GetBytes(sb.toString())); + out.flush(); + // Parse the HTTP response + InputStream in = sock.getInputStream(); + final LineNumberReader reader = new LineNumberReader(new InputStreamReader(in)); + String httpReponse = reader.readLine(); + + if (!httpReponse.startsWith("HTTP/")) { + throw new IOException("The proxy did not send back a valid HTTP response."); + } + + // "HTTP/1.X XYZ X" => 14 characters minimum + + if ((httpReponse.length() < 14) || (httpReponse.charAt(8) != ' ') || (httpReponse.charAt(12) != ' ')) { + throw new IOException("The proxy did not send back a valid HTTP response."); + } + + int errorCode; + + try { + errorCode = Integer.parseInt(httpReponse.substring(9, 12)); + } + catch (NumberFormatException ignore) { + throw new IOException("The proxy did not send back a valid HTTP response."); + } + + if ((errorCode < 0) || (errorCode > 999)) { + throw new IOException("The proxy did not send back a valid HTTP response."); + } + + if (errorCode != 200) { + throw new HTTPProxyException(httpReponse.substring(13), errorCode); + } + + while (reader.readLine() != null) { + // Read until empty line + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/KexManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.transport; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.security.DigestException; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.ECPrivateKey; +import java.util.Arrays; +import java.util.ArrayList; + +import ch.ethz.ssh2.ConnectionInfo; +import ch.ethz.ssh2.DHGexParameters; +import ch.ethz.ssh2.compression.CompressionFactory; +import ch.ethz.ssh2.compression.Compressor; +import ch.ethz.ssh2.crypto.CryptoWishList; +import ch.ethz.ssh2.crypto.KeyMaterial; +import ch.ethz.ssh2.crypto.cipher.BlockCipher; +import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; +import ch.ethz.ssh2.crypto.digest.MAC; +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.PacketKexInit; +import ch.ethz.ssh2.packets.PacketNewKeys; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.ECPrivateKey; + +/** + * @version $Id: KexManager.java 152 2014-04-28 11:02:23Z dkocher@sudo.ch $ + */ +public abstract class KexManager implements MessageHandler { + protected static final Logger log = Logger.getLogger(KexManager.class); + + private static final ArrayList<String> HOSTKEY_ALGS = new ArrayList<String>(); + static { + HOSTKEY_ALGS.add("ssh-rsa"); + HOSTKEY_ALGS.add("ssh-dss"); + HOSTKEY_ALGS.add("ecdsa-sha2-nistp256"); + HOSTKEY_ALGS.add("ecdsa-sha2-nistp384"); + HOSTKEY_ALGS.add("ecdsa-sha2-nistp521"); + } + + private static final ArrayList<String> KEX_ALGS = new ArrayList<String>(); + static { + KEX_ALGS.add("diffie-hellman-group-exchange-sha256"); + KEX_ALGS.add("diffie-hellman-group-exchange-sha1"); + KEX_ALGS.add("diffie-hellman-group14-sha1"); + KEX_ALGS.add("diffie-hellman-group1-sha1"); + KEX_ALGS.add("ecdh-sha2-nistp256"); + KEX_ALGS.add("ecdh-sha2-nistp384"); + KEX_ALGS.add("ecdh-sha2-nistp521"); + } + + KexState kxs; + int kexCount = 0; + KeyMaterial km; + byte[] sessionId; + ClientServerHello csh; + + final Object accessLock = new Object(); + ConnectionInfo lastConnInfo = null; + + boolean connectionClosed = false; + + boolean ignore_next_kex_packet = false; + + final TransportManager tm; + + CryptoWishList nextKEXcryptoWishList; + DHGexParameters nextKEXdhgexParameters; + KeyPair nextKEXdsakey; + KeyPair nextKEXrsakey; + KeyPair nextKEXeckey; + + final SecureRandom rnd; + + public KexManager(TransportManager tm, ClientServerHello csh, CryptoWishList initialCwl, SecureRandom rnd) { + this.tm = tm; + this.csh = csh; + this.nextKEXcryptoWishList = initialCwl; + this.nextKEXdhgexParameters = new DHGexParameters(); + this.rnd = rnd; + } + + public ConnectionInfo getOrWaitForConnectionInfo(int minKexCount) throws IOException { + synchronized (accessLock) { + while (true) { + if ((lastConnInfo != null) && (lastConnInfo.keyExchangeCounter >= minKexCount)) { + return lastConnInfo; + } + + if (connectionClosed) { + throw(IOException) new IOException("Key exchange was not finished, connection is closed.").initCause(tm.getReasonClosedCause()); + } + + try { + accessLock.wait(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(e.getMessage()); + } + } + } + } + + private String getFirstMatch(String[] client, String[] server) throws NegotiateException { + if (client == null || server == null) { + throw new IllegalArgumentException(); + } + + for (String c : client) { + for (String s : server) { + if (c.equals(s)) { + return c; + } + } + } + + throw new NegotiateException(String.format("Negotiation failed for %s", Arrays.toString(server))); + } + + private boolean compareFirstOfNameList(String[] a, String[] b) { + if (a == null || b == null) { + throw new IllegalArgumentException(); + } + + if ((a.length == 0) && (b.length == 0)) { + return true; + } + + if ((a.length == 0) || (b.length == 0)) { + return false; + } + + return (a[0].equals(b[0])); + } + + private boolean isGuessOK(KexParameters cpar, KexParameters spar) { + if (cpar == null || spar == null) { + throw new IllegalArgumentException(); + } + + if (!compareFirstOfNameList(cpar.kex_algorithms, spar.kex_algorithms)) { + return false; + } + + if (!compareFirstOfNameList(cpar.server_host_key_algorithms, spar.server_host_key_algorithms)) { + return false; + } + + /* + * We do NOT check here if the other algorithms can be agreed on, this + * is just a check if kex_algorithms and server_host_key_algorithms were + * guessed right! + */ + return true; + } + + protected NegotiatedParameters mergeKexParameters(KexParameters client, KexParameters server) + throws NegotiateException { + NegotiatedParameters np = new NegotiatedParameters(); + np.kex_algo = getFirstMatch(client.kex_algorithms, server.kex_algorithms); + log.info("kex_algo=" + np.kex_algo); + np.server_host_key_algo = getFirstMatch(client.server_host_key_algorithms, + server.server_host_key_algorithms); + log.info("server_host_key_algo=" + np.server_host_key_algo); + np.enc_algo_client_to_server = getFirstMatch(client.encryption_algorithms_client_to_server, + server.encryption_algorithms_client_to_server); + np.enc_algo_server_to_client = getFirstMatch(client.encryption_algorithms_server_to_client, + server.encryption_algorithms_server_to_client); + log.info("enc_algo_client_to_server=" + np.enc_algo_client_to_server); + log.info("enc_algo_server_to_client=" + np.enc_algo_server_to_client); + np.mac_algo_client_to_server = getFirstMatch(client.mac_algorithms_client_to_server, + server.mac_algorithms_client_to_server); + np.mac_algo_server_to_client = getFirstMatch(client.mac_algorithms_server_to_client, + server.mac_algorithms_server_to_client); + log.info("mac_algo_client_to_server=" + np.mac_algo_client_to_server); + log.info("mac_algo_server_to_client=" + np.mac_algo_server_to_client); + np.comp_algo_client_to_server = getFirstMatch(client.compression_algorithms_client_to_server, + server.compression_algorithms_client_to_server); + np.comp_algo_server_to_client = getFirstMatch(client.compression_algorithms_server_to_client, + server.compression_algorithms_server_to_client); + log.info("comp_algo_client_to_server=" + np.comp_algo_client_to_server); + log.info("comp_algo_server_to_client=" + np.comp_algo_server_to_client); + np.lang_client_to_server = getFirstMatch(client.languages_client_to_server, + server.languages_client_to_server); + np.lang_server_to_client = getFirstMatch(client.languages_server_to_client, + server.languages_server_to_client); + + if (isGuessOK(client, server)) { + np.guessOK = true; + } + + return np; + } + + public synchronized void initiateKEX(CryptoWishList cwl, DHGexParameters dhgex, KeyPair dsa, KeyPair rsa, KeyPair ec) + throws IOException { + nextKEXcryptoWishList = cwl; + nextKEXdhgexParameters = dhgex; + nextKEXdsakey = dsa; + nextKEXrsakey = rsa; + nextKEXeckey = ec; + + if (kxs == null) { + kxs = new KexState(); + kxs.local_dsa_key = dsa; + kxs.local_rsa_key = rsa; + kxs.local_ec_key = ec; + kxs.dhgexParameters = nextKEXdhgexParameters; + kxs.localKEX = new PacketKexInit(nextKEXcryptoWishList, rnd); + tm.sendKexMessage(kxs.localKEX.getPayload()); + } + } + + private boolean establishKeyMaterial() throws IOException { + try { + int mac_cs_key_len = MAC.getKeyLen(kxs.np.mac_algo_client_to_server); + int enc_cs_key_len = BlockCipherFactory.getKeySize(kxs.np.enc_algo_client_to_server); + int enc_cs_block_len = BlockCipherFactory.getBlockSize(kxs.np.enc_algo_client_to_server); + int mac_sc_key_len = MAC.getKeyLen(kxs.np.mac_algo_server_to_client); + int enc_sc_key_len = BlockCipherFactory.getKeySize(kxs.np.enc_algo_server_to_client); + int enc_sc_block_len = BlockCipherFactory.getBlockSize(kxs.np.enc_algo_server_to_client); + km = KeyMaterial.create(kxs.hashAlgo, kxs.H, kxs.K, sessionId, enc_cs_key_len, enc_cs_block_len, mac_cs_key_len, + enc_sc_key_len, enc_sc_block_len, mac_sc_key_len); + } + catch (IllegalArgumentException e) { + return false; + } + + return true; + } + + protected void finishKex(boolean clientMode) throws IOException { + if (sessionId == null) { + sessionId = kxs.H; + } + + establishKeyMaterial(); + /* Tell the other side that we start using the new material */ + PacketNewKeys ign = new PacketNewKeys(); + tm.sendKexMessage(ign.getPayload()); + BlockCipher cbc; + MAC mac; + Compressor comp; + + try { + cbc = BlockCipherFactory.createCipher(clientMode ? kxs.np.enc_algo_client_to_server + : kxs.np.enc_algo_server_to_client, true, clientMode ? km.enc_key_client_to_server + : km.enc_key_server_to_client, clientMode ? km.initial_iv_client_to_server + : km.initial_iv_server_to_client); + + try { + mac = new MAC(clientMode ? kxs.np.mac_algo_client_to_server : kxs.np.mac_algo_server_to_client, clientMode + ? km.integrity_key_client_to_server : km.integrity_key_server_to_client); + } + catch (DigestException e) { + throw new IOException(e); + } + + comp = CompressionFactory.createCompressor(kxs.np.comp_algo_client_to_server); + } + catch (IllegalArgumentException f) { + throw new IOException(String.format("Fatal error initializing ciphers. %s", f.getMessage())); + } + + tm.changeSendCipher(cbc, mac); + tm.changeSendCompression(comp); + tm.kexFinished(); + } + + public static String[] getDefaultServerHostkeyAlgorithmList() { + return HOSTKEY_ALGS.toArray(new String[HOSTKEY_ALGS.size()]); + } + + public static void checkServerHostkeyAlgorithmsList(String[] algos) { + for (final String algo : algos) { + if (!HOSTKEY_ALGS.contains(algo)) + throw new IllegalArgumentException("Unknown server host key algorithm '" + algo + "'"); + } + } + + public static String[] getDefaultClientKexAlgorithmList() { + return KEX_ALGS.toArray(new String[KEX_ALGS.size()]); + } + + public static String[] getDefaultServerKexAlgorithmList() { + return KEX_ALGS.toArray(new String[KEX_ALGS.size()]); + } + + public static void checkKexAlgorithmList(String[] algos) { + for (final String algo : algos) { + if (!KEX_ALGS.contains(algo)) + throw new IllegalArgumentException("Unknown kex algorithm '" + algo + "'"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/KexParameters.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.transport; + +import java.util.Arrays; + +/** + * @author Christian Plattner + * @version $Id: KexParameters.java 159 2014-05-01 14:12:34Z dkocher@sudo.ch $ + */ +public class KexParameters { + public byte[] cookie; + public String[] kex_algorithms; + public String[] server_host_key_algorithms; + public String[] encryption_algorithms_client_to_server; + public String[] encryption_algorithms_server_to_client; + public String[] mac_algorithms_client_to_server; + public String[] mac_algorithms_server_to_client; + public String[] compression_algorithms_client_to_server; + public String[] compression_algorithms_server_to_client; + public String[] languages_client_to_server; + public String[] languages_server_to_client; + public boolean first_kex_packet_follows; + public int reserved_field1; + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("KexParameters{"); + sb.append("cookie=").append(Arrays.toString(cookie)); + sb.append(", kex_algorithms=").append(Arrays.toString(kex_algorithms)); + sb.append(", server_host_key_algorithms=").append(Arrays.toString(server_host_key_algorithms)); + sb.append(", encryption_algorithms_client_to_server=").append(Arrays.toString(encryption_algorithms_client_to_server)); + sb.append(", encryption_algorithms_server_to_client=").append(Arrays.toString(encryption_algorithms_server_to_client)); + sb.append(", mac_algorithms_client_to_server=").append(Arrays.toString(mac_algorithms_client_to_server)); + sb.append(", mac_algorithms_server_to_client=").append(Arrays.toString(mac_algorithms_server_to_client)); + sb.append(", compression_algorithms_client_to_server=").append(Arrays.toString(compression_algorithms_client_to_server)); + sb.append(", compression_algorithms_server_to_client=").append(Arrays.toString(compression_algorithms_server_to_client)); + sb.append(", languages_client_to_server=").append(Arrays.toString(languages_client_to_server)); + sb.append(", languages_server_to_client=").append(Arrays.toString(languages_server_to_client)); + sb.append(", first_kex_packet_follows=").append(first_kex_packet_follows); + sb.append(", reserved_field1=").append(reserved_field1); + sb.append('}'); + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/KexState.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.transport; + +import ch.ethz.ssh2.DHGexParameters; +import ch.ethz.ssh2.crypto.dh.GenericDhExchange; +import ch.ethz.ssh2.crypto.dh.DhGroupExchange; +import java.math.BigInteger; +import ch.ethz.ssh2.packets.PacketKexInit; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.ECPrivateKey; + +/** + * KexState. + * + * @author Christian Plattner + * @version 2.50, 03/15/10 + */ +public class KexState { + public PacketKexInit localKEX; + public PacketKexInit remoteKEX; + public NegotiatedParameters np; + public int state = 0; + + public BigInteger K; + public byte[] H; + + public byte[] remote_hostkey; + + public String hashAlgo; + public GenericDhExchange dhx; + public DhGroupExchange dhgx; + public DHGexParameters dhgexParameters; + + public KeyPair local_dsa_key; + public KeyPair local_rsa_key; + public KeyPair local_ec_key; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/MessageHandler.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.transport; + +import java.io.IOException; + +/** + * @author Christian Plattner + * @version $Id: MessageHandler.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public interface MessageHandler { + public void handleMessage(byte[] msg) throws IOException; + + public void handleFailure(IOException failure); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/NegotiateException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.transport; + +import java.io.IOException; + +/** + * @version $Id: NegotiateException.java 149 2014-04-28 09:18:35Z dkocher@sudo.ch $ + */ +public class NegotiateException extends IOException { + private static final long serialVersionUID = 3689910669428143157L; + + public NegotiateException() { + // + } + + public NegotiateException(String message) { + super(message); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/NegotiatedParameters.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.transport; + +/** + * @author Christian Plattner + * @version $Id: NegotiatedParameters.java 159 2014-05-01 14:12:34Z dkocher@sudo.ch $ + */ +public class NegotiatedParameters { + public boolean guessOK; + public String kex_algo; + public String server_host_key_algo; + public String enc_algo_client_to_server; + public String enc_algo_server_to_client; + public String mac_algo_client_to_server; + public String mac_algo_server_to_client; + public String comp_algo_client_to_server; + public String comp_algo_server_to_client; + public String lang_client_to_server; + public String lang_server_to_client; + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("NegotiatedParameters{"); + sb.append("guessOK=").append(guessOK); + sb.append(", kex_algo='").append(kex_algo).append('\''); + sb.append(", server_host_key_algo='").append(server_host_key_algo).append('\''); + sb.append(", enc_algo_client_to_server='").append(enc_algo_client_to_server).append('\''); + sb.append(", enc_algo_server_to_client='").append(enc_algo_server_to_client).append('\''); + sb.append(", mac_algo_client_to_server='").append(mac_algo_client_to_server).append('\''); + sb.append(", mac_algo_server_to_client='").append(mac_algo_server_to_client).append('\''); + sb.append(", comp_algo_client_to_server='").append(comp_algo_client_to_server).append('\''); + sb.append(", comp_algo_server_to_client='").append(comp_algo_server_to_client).append('\''); + sb.append(", lang_client_to_server='").append(lang_client_to_server).append('\''); + sb.append(", lang_server_to_client='").append(lang_server_to_client).append('\''); + sb.append('}'); + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/ServerKexManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.transport; + +import java.io.IOException; +import java.security.DigestException; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.math.BigInteger; + +import ch.ethz.ssh2.ConnectionInfo; +import ch.ethz.ssh2.PacketTypeException; +import ch.ethz.ssh2.auth.ServerAuthenticationManager; +import ch.ethz.ssh2.crypto.cipher.BlockCipher; +import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; +import ch.ethz.ssh2.crypto.dh.GenericDhExchange; +import ch.ethz.ssh2.crypto.digest.MAC; +import ch.ethz.ssh2.packets.PacketKexDHInit; +import ch.ethz.ssh2.packets.PacketKexDHReply; +import ch.ethz.ssh2.packets.PacketKexInit; +import ch.ethz.ssh2.packets.Packets; +import ch.ethz.ssh2.server.ServerConnectionState; +import ch.ethz.ssh2.signature.DSASHA1Verify; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; +import ch.ethz.ssh2.signature.RSASHA1Verify; + +/** + * @version $Id: ServerKexManager.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ + */ +public class ServerKexManager extends KexManager { + + private final ServerConnectionState state; + + private boolean authenticationStarted = false; + + public ServerKexManager(ServerConnectionState state) { + super(state.tm, state.csh, state.next_cryptoWishList, state.generator); + this.state = state; + } + + public void handleFailure(final IOException failure) { + synchronized (accessLock) { + connectionClosed = true; + accessLock.notifyAll(); + } + } + + public void handleMessage(byte[] msg) throws IOException { + PacketKexInit kip; + + if (msg == null) { + synchronized (accessLock) { + connectionClosed = true; + accessLock.notifyAll(); + return; + } + } + + if ((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) { + throw new PacketTypeException(msg[0]); + } + + if (ignore_next_kex_packet) { + ignore_next_kex_packet = false; + return; + } + + if (msg[0] == Packets.SSH_MSG_KEXINIT) { + if ((kxs != null) && (kxs.state != 0)) { + throw new PacketTypeException(msg[0]); + } + + if (kxs == null) { + /* + * Ah, OK, peer wants to do KEX. Let's be nice and play + * together. + */ + kxs = new KexState(); + kxs.local_dsa_key = nextKEXdsakey; + kxs.local_rsa_key = nextKEXrsakey; + kxs.local_ec_key = nextKEXeckey; + kxs.dhgexParameters = nextKEXdhgexParameters; + kip = new PacketKexInit(nextKEXcryptoWishList, rnd); + kxs.localKEX = kip; + tm.sendKexMessage(kip.getPayload()); + } + + kip = new PacketKexInit(msg); + kxs.remoteKEX = kip; + kxs.np = mergeKexParameters(kxs.remoteKEX.getKexParameters(), kxs.localKEX.getKexParameters()); + + if (kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) { + // Guess was wrong, we need to ignore the next kex packet. + ignore_next_kex_packet = true; + } + + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || + kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp256") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp384") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) { + kxs.dhx = GenericDhExchange.getInstance(kxs.np.kex_algo); + kxs.dhx.init(kxs.np.kex_algo); + kxs.state = 1; + return; + } + + throw new IllegalStateException("Unkown KEX method!"); + } + + if (msg[0] == Packets.SSH_MSG_NEWKEYS) { + if (km == null) { + throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!"); + } + + BlockCipher cbc; + MAC mac; + + try { + cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_client_to_server, false, + km.enc_key_client_to_server, km.initial_iv_client_to_server); + + try { + mac = new MAC(kxs.np.mac_algo_client_to_server, km.integrity_key_client_to_server); + } + catch (DigestException e) { + throw new IOException(e); + } + } + catch (IllegalArgumentException e) { + throw new IOException(e); + } + + tm.changeRecvCipher(cbc, mac); + ConnectionInfo sci = new ConnectionInfo(); + kexCount++; + sci.keyExchangeAlgorithm = kxs.np.kex_algo; + sci.keyExchangeCounter = kexCount; + sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server; + sci.serverToClientCryptoAlgorithm = kxs.np.enc_algo_server_to_client; + sci.clientToServerMACAlgorithm = kxs.np.mac_algo_client_to_server; + sci.serverToClientMACAlgorithm = kxs.np.mac_algo_server_to_client; + sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo; + sci.serverHostKey = kxs.remote_hostkey; + + synchronized (accessLock) { + lastConnInfo = sci; + accessLock.notifyAll(); + } + + kxs = null; + return; + } + + if ((kxs == null) || (kxs.state == 0)) { + throw new IOException("Unexpected Kex submessage!"); + } + + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || + kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp256") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp384") || + kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) { + if (kxs.state == 1) { + PacketKexDHInit dhi = new PacketKexDHInit(msg); + kxs.dhx.setE(dhi.getE()); + byte[] hostKey = null; + + if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) { + hostKey = ECDSASHA2Verify.encodeSSHECDSAPublicKey((ECPublicKey)kxs.local_ec_key.getPublic()); + } + + if (kxs.np.server_host_key_algo.equals("ssh-rsa")) { + hostKey = RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey)kxs.local_rsa_key.getPublic()); + } + + if (kxs.np.server_host_key_algo.equals("ssh-dss")) { + hostKey = DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey)kxs.local_dsa_key.getPublic()); + } + + try { + kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(), + kxs.remoteKEX.getPayload(), kxs.localKEX.getPayload(), hostKey); + } + catch (IllegalArgumentException e) { + throw new IOException("KEX error.", e); + } + + kxs.K = kxs.dhx.getK(); + byte[] signature = null; + + if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) { + ECPrivateKey pk = (ECPrivateKey)kxs.local_ec_key.getPrivate(); + byte[] es = ECDSASHA2Verify.generateSignature(kxs.H, pk); + signature = ECDSASHA2Verify.encodeSSHECDSASignature(es, pk.getParams()); + } + + if (kxs.np.server_host_key_algo.equals("ssh-rsa")) { + byte[] rs = RSASHA1Verify.generateSignature(kxs.H, (RSAPrivateKey)kxs.local_rsa_key.getPrivate()); + signature = RSASHA1Verify.encodeSSHRSASignature(rs); + } + + if (kxs.np.server_host_key_algo.equals("ssh-dss")) { + byte[] ds = DSASHA1Verify.generateSignature(kxs.H, (DSAPrivateKey)kxs.local_dsa_key.getPrivate(), rnd); + signature = DSASHA1Verify.encodeSSHDSASignature(ds); + } + + PacketKexDHReply dhr = new PacketKexDHReply(hostKey, new BigInteger(kxs.dhx.getF()), signature); + tm.sendKexMessage(dhr.getPayload()); + finishKex(false); + kxs.state = -1; + + if (authenticationStarted == false) { + authenticationStarted = true; + state.am = new ServerAuthenticationManager(state); + } + + return; + } + } + + throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/ServerTransportManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,34 @@ +package ch.ethz.ssh2.transport; + +import java.io.IOException; +import java.net.Socket; + +import ch.ethz.ssh2.server.ServerConnectionState; + +/** + * @version $Id: ServerTransportManager.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ + */ +public class ServerTransportManager extends TransportManager { + + private final Socket sock; + + public ServerTransportManager(final Socket socket) { + super(socket); + // TCP connection is already established + this.sock = socket; + } + + public void connect(ServerConnectionState state) throws IOException { + /* Parse the client lin + e and say hello - important: this information is later needed for the + * key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object + * for later use. + */ + state.csh = ClientServerHello.serverHello(state.softwareversion, sock.getInputStream(), sock.getOutputStream()); + TransportConnection tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), state.generator); + KexManager km = new ServerKexManager(state); + super.init(tc, km); + km.initiateKEX(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + this.startReceiver(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/TransportConnection.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.transport; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.SecureRandom; + +import ch.ethz.ssh2.PacketFormatException; +import ch.ethz.ssh2.compression.Compressor; +import ch.ethz.ssh2.crypto.cipher.BlockCipher; +import ch.ethz.ssh2.crypto.cipher.CipherInputStream; +import ch.ethz.ssh2.crypto.cipher.CipherOutputStream; +import ch.ethz.ssh2.crypto.cipher.NullCipher; +import ch.ethz.ssh2.crypto.digest.MAC; +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.Packets; + +/** + * TransportConnection. + * + * @author Christian Plattner + * @version $Id: TransportConnection.java 144 2014-04-25 12:48:25Z dkocher@sudo.ch $ + */ +public class TransportConnection { + private static final Logger log = Logger.getLogger(TransportConnection.class); + + int send_seq_number = 0; + + int recv_seq_number = 0; + + CipherInputStream cis; + + CipherOutputStream cos; + + boolean useRandomPadding; + + /* Depends on current MAC and CIPHER */ + + MAC send_mac; + + byte[] send_mac_buffer; + + int send_padd_blocksize = 8; + + MAC recv_mac; + + byte[] recv_mac_buffer; + + byte[] recv_mac_buffer_cmp; + + int recv_padd_blocksize = 8; + + Compressor recv_comp; + + Compressor send_comp; + + boolean can_compress; + + byte[] recv_comp_buffer; + + byte[] send_comp_buffer; + + /* won't change */ + + final byte[] send_padding_buffer = new byte[256]; + + final byte[] send_packet_header_buffer = new byte[5]; + + final byte[] recv_padding_buffer = new byte[256]; + + final byte[] recv_packet_header_buffer = new byte[5]; + + boolean recv_packet_header_present = false; + + ClientServerHello csh; + + final SecureRandom rnd; + + public TransportConnection(InputStream is, OutputStream os, SecureRandom rnd) { + this.cis = new CipherInputStream(new NullCipher(), is); + this.cos = new CipherOutputStream(new NullCipher(), os); + this.rnd = rnd; + } + + public void changeRecvCipher(BlockCipher bc, MAC mac) { + cis.changeCipher(bc); + recv_mac = mac; + recv_mac_buffer = (mac != null) ? new byte[mac.size()] : null; + recv_mac_buffer_cmp = (mac != null) ? new byte[mac.size()] : null; + recv_padd_blocksize = bc.getBlockSize(); + + if (recv_padd_blocksize < 8) { + recv_padd_blocksize = 8; + } + } + + public void changeSendCipher(BlockCipher bc, MAC mac) { + if ((bc instanceof NullCipher) == false) { + /* Only use zero byte padding for the first few packets */ + useRandomPadding = true; + /* Once we start encrypting, there is no way back */ + } + + cos.changeCipher(bc); + send_mac = mac; + send_mac_buffer = (mac != null) ? new byte[mac.size()] : null; + send_padd_blocksize = bc.getBlockSize(); + + if (send_padd_blocksize < 8) { + send_padd_blocksize = 8; + } + } + + public void changeRecvCompression(Compressor comp) { + recv_comp = comp; + + if (comp != null) { + recv_comp_buffer = new byte[comp.getBufferSize()]; + } + } + + public void changeSendCompression(Compressor comp) { + send_comp = comp; + + if (comp != null) { + send_comp_buffer = new byte[comp.getBufferSize()]; + } + } + + public void sendMessage(byte[] message) throws IOException { + sendMessage(message, 0, message.length, 0); + } + + public void sendMessage(byte[] message, int off, int len) throws IOException { + sendMessage(message, off, len, 0); + } + + public int getPacketOverheadEstimate() { + // return an estimate for the paket overhead (for send operations) + return 5 + 4 + (send_padd_blocksize - 1) + send_mac_buffer.length; + } + + public void sendMessage(byte[] message, int off, int len, int padd) throws IOException { + if (padd < 4) { + padd = 4; + } + else if (padd > 64) { + padd = 64; + } + + if (send_comp != null && can_compress) { + len = send_comp.compress(message, off, len, send_comp_buffer); + message = send_comp_buffer; + } + + int packet_len = 5 + len + padd; /* Minimum allowed padding is 4 */ + int slack = packet_len % send_padd_blocksize; + + if (slack != 0) { + packet_len += (send_padd_blocksize - slack); + } + + if (packet_len < 16) { + packet_len = 16; + } + + int padd_len = packet_len - (5 + len); + + if (useRandomPadding) { + for (int i = 0; i < padd_len; i = i + 4) { + /* + * don't waste calls to rnd.nextInt() (by using only 8bit of the + * output). just believe me: even though we may write here up to 3 + * bytes which won't be used, there is no "buffer overflow" (i.e., + * arrayindexoutofbounds). the padding buffer is big enough =) (256 + * bytes, and that is bigger than any current cipher block size + 64). + */ + int r = rnd.nextInt(); + send_padding_buffer[i] = (byte) r; + send_padding_buffer[i + 1] = (byte)(r >> 8); + send_padding_buffer[i + 2] = (byte)(r >> 16); + send_padding_buffer[i + 3] = (byte)(r >> 24); + } + } + else { + /* use zero padding for unencrypted traffic */ + for (int i = 0; i < padd_len; i++) { + send_padding_buffer[i] = 0; + } + + /* Actually this code is paranoid: we never filled any + * bytes into the padding buffer so far, therefore it should + * consist of zeros only. + */ + } + + send_packet_header_buffer[0] = (byte)((packet_len - 4) >> 24); + send_packet_header_buffer[1] = (byte)((packet_len - 4) >> 16); + send_packet_header_buffer[2] = (byte)((packet_len - 4) >> 8); + send_packet_header_buffer[3] = (byte)((packet_len - 4)); + send_packet_header_buffer[4] = (byte) padd_len; + cos.write(send_packet_header_buffer, 0, 5); + cos.write(message, off, len); + cos.write(send_padding_buffer, 0, padd_len); + + if (send_mac != null) { + send_mac.initMac(send_seq_number); + send_mac.update(send_packet_header_buffer, 0, 5); + send_mac.update(message, off, len); + send_mac.update(send_padding_buffer, 0, padd_len); + send_mac.getMac(send_mac_buffer, 0); + cos.writePlain(send_mac_buffer, 0, send_mac_buffer.length); + } + + cos.flush(); + + if (log.isDebugEnabled()) { + log.debug("Sent " + Packets.getMessageName(message[off] & 0xff) + " " + len + " bytes payload"); + } + + send_seq_number++; + } + + public int peekNextMessageLength() throws IOException { + if (recv_packet_header_present == false) { + cis.read(recv_packet_header_buffer, 0, 5); + recv_packet_header_present = true; + } + + int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24) | + ((recv_packet_header_buffer[1] & 0xff) << 16) | + ((recv_packet_header_buffer[2] & 0xff) << 8) | + ((recv_packet_header_buffer[3] & 0xff)); + int padding_length = recv_packet_header_buffer[4] & 0xff; + + if (packet_length > TransportManager.MAX_PACKET_SIZE || packet_length < 12) { + throw new PacketFormatException(String.format("Illegal packet size (%d)", packet_length)); + } + + int payload_length = packet_length - padding_length - 1; + + if (payload_length < 0) { + throw new PacketFormatException(String.format("Illegal padding_length in packet from remote (%d)", padding_length)); + } + + return payload_length; + } + + public int receiveMessage(byte buffer[], int off, int len) throws IOException { + if (recv_packet_header_present == false) { + cis.read(recv_packet_header_buffer, 0, 5); + } + else { + recv_packet_header_present = false; + } + + int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24) | + ((recv_packet_header_buffer[1] & 0xff) << 16) | + ((recv_packet_header_buffer[2] & 0xff) << 8) | + ((recv_packet_header_buffer[3] & 0xff)); + int padding_length = recv_packet_header_buffer[4] & 0xff; + + if (packet_length > TransportManager.MAX_PACKET_SIZE || packet_length < 12) { + throw new PacketFormatException(String.format("Illegal packet size (%d)", packet_length)); + } + + int payload_length = packet_length - padding_length - 1; + + if (payload_length < 0) { + throw new PacketFormatException(String.format("Illegal padding_length in packet from remote (%d)", padding_length)); + } + + if (payload_length >= len) { + throw new IOException("Receive buffer too small (" + len + ", need " + payload_length + ")"); + } + + cis.read(buffer, off, payload_length); + cis.read(recv_padding_buffer, 0, padding_length); + + if (recv_mac != null) { + cis.readPlain(recv_mac_buffer, 0, recv_mac_buffer.length); + recv_mac.initMac(recv_seq_number); + recv_mac.update(recv_packet_header_buffer, 0, 5); + recv_mac.update(buffer, off, payload_length); + recv_mac.update(recv_padding_buffer, 0, padding_length); + recv_mac.getMac(recv_mac_buffer_cmp, 0); + + for (int i = 0; i < recv_mac_buffer.length; i++) { + if (recv_mac_buffer[i] != recv_mac_buffer_cmp[i]) { + throw new IOException("Remote sent corrupt MAC."); + } + } + } + + recv_seq_number++; + + if (log.isDebugEnabled()) { + log.debug("Received " + Packets.getMessageName(buffer[off] & 0xff) + " " + payload_length + + " bytes payload"); + } + + if (recv_comp != null && can_compress) { + int[] uncomp_len = new int[] {payload_length}; + buffer = recv_comp.uncompress(buffer, off, uncomp_len); + return uncomp_len[0]; + } + else { + return payload_length; + } + } + + public void startCompression() { + can_compress = true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/transport/TransportManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2.transport; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.Socket; +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.List; + +import ch.ethz.ssh2.ConnectionInfo; +import ch.ethz.ssh2.ConnectionMonitor; +import ch.ethz.ssh2.DHGexParameters; +import ch.ethz.ssh2.PacketTypeException; +import ch.ethz.ssh2.compression.Compressor; +import ch.ethz.ssh2.crypto.CryptoWishList; +import ch.ethz.ssh2.crypto.cipher.BlockCipher; +import ch.ethz.ssh2.crypto.digest.MAC; +import ch.ethz.ssh2.log.Logger; +import ch.ethz.ssh2.packets.PacketDisconnect; +import ch.ethz.ssh2.packets.Packets; +import ch.ethz.ssh2.packets.TypesReader; + +/** + * Yes, the "standard" is a big mess. On one side, the say that arbitrary channel + * packets are allowed during kex exchange, on the other side we need to blindly + * ignore the next _packet_ if the KEX guess was wrong. Where do we know from that + * the next packet is not a channel data packet? Yes, we could check if it is in + * the KEX range. But the standard says nothing about this. The OpenSSH guys + * block local "normal" traffic during KEX. That's fine - however, they assume + * that the other side is doing the same. During re-key, if they receive traffic + * other than KEX, they become horribly irritated and kill the connection. Since + * we are very likely going to communicate with OpenSSH servers, we have to play + * the same game - even though we could do better. + * + * @author Christian Plattner + * @version $Id: TransportManager.java 161 2014-05-01 18:01:55Z dkocher@sudo.ch $ + */ +public abstract class TransportManager { + protected static final Logger log = Logger.getLogger(TransportManager.class); + + private static final class HandlerEntry { + MessageHandler mh; + int low; + int high; + } + + /** + * Advertised maximum SSH packet size that the other side can send to us. + */ + public static final int MAX_PACKET_SIZE = 64 * 1024; + + private final List<AsynchronousEntry> asynchronousQueue + = new ArrayList<AsynchronousEntry>(); + + private Thread asynchronousThread = null; + private boolean asynchronousPending = false; + + private Socket socket; + + protected TransportManager(final Socket socket) { + this.socket = socket; + } + + private static final class AsynchronousEntry { + public byte[] message; + + public AsynchronousEntry(byte[] message) { + this.message = message; + } + } + + private final class AsynchronousWorker implements Runnable { + public void run() { + while (true) { + final AsynchronousEntry item; + + synchronized (asynchronousQueue) { + if (asynchronousQueue.size() == 0) { + // Only now we may reset the flag, since we are sure that all queued items + // have been sent (there is a slight delay between de-queuing and sending, + // this is why we need this flag! See code below. Sending takes place outside + // of this lock, this is why a test for size()==0 (from another thread) does not ensure + // that all messages have been sent. + asynchronousPending = false; + // Notify any senders that they can proceed, all async messages have been delivered + asynchronousQueue.notifyAll(); + + // After the queue is empty for about 2 seconds, stop this thread + try { + asynchronousQueue.wait(2000); + } + catch (InterruptedException ignore) { + // + } + + if (asynchronousQueue.size() == 0) { + asynchronousThread = null; + return; + } + } + + item = asynchronousQueue.remove(0); + } + + try { + sendMessageImmediate(item.message); + } + catch (IOException e) { + // There is no point in handling it - it simply means that the connection has a problem and we should stop + // sending asynchronously messages. We do not need to signal that we have exited (asynchronousThread = null): + // further messages in the queue cannot be sent by this or any other thread. + // Other threads will sooner or later (when receiving or sending the next message) get the + // same IOException and get to the same conclusion. + log.warning(e.getMessage()); + return; + } + } + } + } + + private final Object connectionSemaphore = new Object(); + + private boolean flagKexOngoing; + + private boolean connectionClosed; + private Throwable reasonClosedCause; + + private TransportConnection tc; + private KexManager km; + + private final List<HandlerEntry> messageHandlers = new ArrayList<HandlerEntry>(); + + private List<ConnectionMonitor> connectionMonitors = new ArrayList<ConnectionMonitor>(); + boolean monitorsWereInformed = false; + + protected void init(TransportConnection tc, KexManager km) { + this.tc = tc; + this.km = km; + } + + public int getPacketOverheadEstimate() { + return tc.getPacketOverheadEstimate(); + } + + public ConnectionInfo getConnectionInfo(int kexNumber) throws IOException { + return km.getOrWaitForConnectionInfo(kexNumber); + } + + public Throwable getReasonClosedCause() { + synchronized (connectionSemaphore) { + return reasonClosedCause; + } + } + + public byte[] getSessionIdentifier() { + return km.sessionId; + } + + public void close(Throwable cause, boolean useDisconnectPacket) { + if (useDisconnectPacket == false) { + // OK, hard shutdown - do not acquire the semaphore, + // perhaps somebody is inside (and waits until + // the remote side is ready to accept new data). + try { + socket.close(); + } + catch (IOException ignore) { + } + + // OK, whoever tried to send data, should now agree that + // there is no point in further waiting =) + // It is safe now to acquire the semaphore. + } + + synchronized (connectionSemaphore) { + if (!connectionClosed) { + if (useDisconnectPacket == true) { + try { + if (tc != null) + tc.sendMessage(new PacketDisconnect(PacketDisconnect.Reason.SSH_DISCONNECT_BY_APPLICATION, "").getPayload()); + } + catch (IOException ignore) { + } + + try { + socket.close(); + } + catch (IOException ignore) { + } + } + + connectionClosed = true; + reasonClosedCause = cause; + } + + connectionSemaphore.notifyAll(); + } + + // check if we need to inform the monitors + List<ConnectionMonitor> monitors = null; + + synchronized (this) { + // Short term lock to protect "connectionMonitors" + // and "monitorsWereInformed" + // (they may be modified concurrently) + if (monitorsWereInformed == false) { + monitorsWereInformed = true; + monitors = new ArrayList<ConnectionMonitor>(connectionMonitors); + } + } + + if (monitors != null) { + for (ConnectionMonitor cmon : monitors) { + try { + cmon.connectionLost(reasonClosedCause); + } + catch (Exception ignore) { + } + } + } + } + + protected void startReceiver() throws IOException { + final Thread receiveThread = new Thread(new Runnable() { + public void run() { + try { + receiveLoop(); + // Can only exit with exception + } + catch (IOException e) { + close(e, false); + log.warning(e.getMessage()); + + // Tell all handlers that it is time to say goodbye + if (km != null) { + km.handleFailure(e); + } + + for (HandlerEntry he : messageHandlers) { + he.mh.handleFailure(e); + } + } + + if (log.isDebugEnabled()) { + log.debug("Receive thread: back from receiveLoop"); + } + } + }); + receiveThread.setName("Transport Manager"); + receiveThread.setDaemon(true); + receiveThread.start(); + } + + public void registerMessageHandler(MessageHandler mh, int low, int high) { + HandlerEntry he = new HandlerEntry(); + he.mh = mh; + he.low = low; + he.high = high; + + synchronized (messageHandlers) { + messageHandlers.add(he); + } + } + + public void removeMessageHandler(MessageHandler handler) { + synchronized (messageHandlers) { + for (int i = 0; i < messageHandlers.size(); i++) { + HandlerEntry he = messageHandlers.get(i); + + if (he.mh == handler) { + messageHandlers.remove(i); + break; + } + } + } + } + + public void sendKexMessage(byte[] msg) throws IOException { + synchronized (connectionSemaphore) { + if (connectionClosed) { + throw(IOException) new IOException("Sorry, this connection is closed.").initCause(reasonClosedCause); + } + + flagKexOngoing = true; + + try { + tc.sendMessage(msg); + } + catch (IOException e) { + close(e, false); + throw e; + } + } + } + + public void kexFinished() throws IOException { + synchronized (connectionSemaphore) { + flagKexOngoing = false; + connectionSemaphore.notifyAll(); + } + } + + /** + * @param cwl Crypto wishlist + * @param dhgex Diffie-hellman group exchange + * @param dsa may be null if this is a client connection + * @param rsa may be null if this is a client connection + * @throws IOException + */ + public void forceKeyExchange(CryptoWishList cwl, DHGexParameters dhgex, KeyPair dsa, KeyPair rsa, KeyPair ec) + throws IOException { + synchronized (connectionSemaphore) { + if (connectionClosed) { + throw(IOException) new IOException("Sorry, this connection is closed.").initCause(reasonClosedCause); + } + } + + km.initiateKEX(cwl, dhgex, dsa, rsa, ec); + } + + public void changeRecvCipher(BlockCipher bc, MAC mac) { + tc.changeRecvCipher(bc, mac); + } + + public void changeSendCipher(BlockCipher bc, MAC mac) { + tc.changeSendCipher(bc, mac); + } + + public void changeRecvCompression(Compressor comp) { + tc.changeRecvCompression(comp); + } + + public void changeSendCompression(Compressor comp) { + tc.changeSendCompression(comp); + } + + public void sendAsynchronousMessage(byte[] msg) throws IOException { + synchronized (asynchronousQueue) { + asynchronousQueue.add(new AsynchronousEntry(msg)); + asynchronousPending = true; + + /* This limit should be flexible enough. We need this, otherwise the peer + * can flood us with global requests (and other stuff where we have to reply + * with an asynchronous message) and (if the server just sends data and does not + * read what we send) this will probably put us in a low memory situation + * (our send queue would grow and grow and...) */ + + if (asynchronousQueue.size() > 100) { + throw new IOException("The peer is not consuming our asynchronous replies."); + } + + // Check if we have an asynchronous sending thread + if (asynchronousThread == null) { + asynchronousThread = new Thread(new AsynchronousWorker()); + asynchronousThread.setDaemon(true); + asynchronousThread.start(); + // The thread will stop after 2 seconds of inactivity (i.e., empty queue) + } + + asynchronousQueue.notifyAll(); + } + } + + public void setConnectionMonitors(List<ConnectionMonitor> monitors) { + synchronized (this) { + connectionMonitors = new ArrayList<ConnectionMonitor>(monitors); + } + } + + /** + * Send a message but ensure that all queued messages are being sent first. + * + * @param msg Message + * @throws IOException + */ + public void sendMessage(byte[] msg) throws IOException { + synchronized (asynchronousQueue) { + while (asynchronousPending) { + try { + asynchronousQueue.wait(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(e.getMessage()); + } + } + } + + sendMessageImmediate(msg); + } + + /** + * Send message, ignore queued async messages that have not been delivered yet. + * Will be called directly from the asynchronousThread thread. + * + * @param msg Message + * @throws IOException + */ + public void sendMessageImmediate(byte[] msg) throws IOException { + synchronized (connectionSemaphore) { + while (true) { + if (connectionClosed) { + throw(IOException) new IOException("Sorry, this connection is closed.").initCause(reasonClosedCause); + } + + if (!flagKexOngoing) { + break; + } + + try { + connectionSemaphore.wait(); + } + catch (InterruptedException e) { + throw new InterruptedIOException(e.getMessage()); + } + } + + try { + tc.sendMessage(msg); + } + catch (IOException e) { + close(e, false); + throw e; + } + } + } + + private void receiveLoop() throws IOException { + while (true) { + final byte[] buffer = new byte[MAX_PACKET_SIZE]; + final int length = tc.receiveMessage(buffer, 0, buffer.length); + final byte[] packet = new byte[length]; + System.arraycopy(buffer, 0, packet, 0, length); + final int type = packet[0] & 0xff; + log.debug(String.format("transport manager receive loop type %d", type)); + + switch (type) { + case Packets.SSH_MSG_IGNORE: + break; + + case Packets.SSH_MSG_DEBUG: { + TypesReader tr = new TypesReader(packet); + tr.readByte(); + // always_display + tr.readBoolean(); + String message = tr.readString(); + + if (log.isDebugEnabled()) { + log.debug(String.format("Debug message from remote: '%s'", message)); + } + + break; + } + + case Packets.SSH_MSG_UNIMPLEMENTED: + throw new PacketTypeException(type); + + case Packets.SSH_MSG_DISCONNECT: { + final PacketDisconnect disconnect = new PacketDisconnect(packet); + throw new DisconnectException(disconnect.getReason(), disconnect.getMessage()); + } + + case Packets.SSH_MSG_KEXINIT: + case Packets.SSH_MSG_NEWKEYS: + case Packets.SSH_MSG_KEXDH_INIT: + case Packets.SSH_MSG_KEXDH_REPLY: + case Packets.SSH_MSG_KEX_DH_GEX_REQUEST: + case Packets.SSH_MSG_KEX_DH_GEX_INIT: + case Packets.SSH_MSG_KEX_DH_GEX_REPLY: + // Is it a KEX Packet + km.handleMessage(packet); + break; + + case Packets.SSH_MSG_USERAUTH_SUCCESS: + tc.startCompression(); + + // Continue with message handlers + default: + boolean handled = false; + + for (HandlerEntry handler : messageHandlers) { + if ((handler.low <= type) && (type <= handler.high)) { + handler.mh.handleMessage(packet); + handled = true; + break; + } + } + + if (!handled) { + throw new PacketTypeException(type); + } + + break; + } + + if (log.isDebugEnabled()) { + log.debug(String.format("Handled packet %d", type)); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/util/StringEncoder.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. + * All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ +package ch.ethz.ssh2.util; + +import java.io.UnsupportedEncodingException; + +/** + * @author Christian Plattner + * @version $Id: StringEncoder.java 43 2011-06-21 18:34:06Z dkocher@sudo.ch $ + */ +public class StringEncoder { + public static byte[] GetBytes(String data) { + try { + return data.getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public static String GetString(byte[] data) { + return GetString(data, 0, data.length); + } + + public static String GetString(byte[] data, int off, int len) { + try { + return new String(data, off, len, "UTF-8"); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/util/TimeoutService.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. + * Please refer to the LICENSE.txt for licensing details. + */ + +package ch.ethz.ssh2.util; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; + +import ch.ethz.ssh2.log.Logger; + +/** + * TimeoutService (beta). Here you can register a timeout. + * <p> + * Implemented having large scale programs in mind: if you open many concurrent SSH connections + * that rely on timeouts, then there will be only one timeout thread. Once all timeouts + * have expired/are cancelled, the thread will (sooner or later) exit. + * Only after new timeouts arrive a new thread (singleton) will be instantiated. + * + * @author Christian Plattner + * @version $Id: TimeoutService.java 89 2014-04-07 14:36:24Z dkocher@sudo.ch $ + */ +public class TimeoutService { + private static final Logger log = Logger.getLogger(TimeoutService.class); + + public static class TimeoutToken { + private long runTime; + private Runnable handler; + + private TimeoutToken(long runTime, Runnable handler) { + this.runTime = runTime; + this.handler = handler; + } + } + + private static class TimeoutThread extends Thread { + @Override + public void run() { + synchronized (todolist) { + while (true) { + if (todolist.size() == 0) { + timeoutThread = null; + return; + } + + long now = System.currentTimeMillis(); + TimeoutToken tt = todolist.getFirst(); + + if (tt.runTime > now) { + /* Not ready yet, sleep a little bit */ + try { + todolist.wait(tt.runTime - now); + } + catch (InterruptedException ignored) { + } + + /* We cannot simply go on, since it could be that the token + * was removed (cancelled) or another one has been inserted in + * the meantime. + */ + continue; + } + + todolist.removeFirst(); + + try { + tt.handler.run(); + } + catch (Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + log.warning("Exeception in Timeout handler:" + e.getMessage() + "(" + sw.toString() + ")"); + } + } + } + } + } + + /* The list object is also used for locking purposes */ + private static final LinkedList<TimeoutToken> todolist = new LinkedList<TimeoutService.TimeoutToken>(); + + private static Thread timeoutThread = null; + + /** + * It is assumed that the passed handler will not execute for a long time. + * + * @param runTime + * @param handler + * @return a TimeoutToken that can be used to cancel the timeout. + */ + public static TimeoutToken addTimeoutHandler(long runTime, Runnable handler) { + TimeoutToken token = new TimeoutToken(runTime, handler); + + synchronized (todolist) { + todolist.add(token); + Collections.sort(todolist, new Comparator<TimeoutToken>() { + public int compare(TimeoutToken o1, TimeoutToken o2) { + if (o1.runTime > o2.runTime) + return 1; + + if (o1.runTime == o2.runTime) + return 0; + + return -1; + } + }); + + if (timeoutThread != null) + timeoutThread.interrupt(); + else { + timeoutThread = new TimeoutThread(); + timeoutThread.setDaemon(true); + timeoutThread.start(); + } + } + + return token; + } + + public static void cancelTimeoutHandler(TimeoutToken token) { + synchronized (todolist) { + todolist.remove(token); + + if (timeoutThread != null) + timeoutThread.interrupt(); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/ActionBarWrapper.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,84 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import com.five_ten_sg.connectbot.util.PreferenceConstants; +import android.annotation.TargetApi; +import android.app.ActionBar; +import android.app.Activity; + +public abstract class ActionBarWrapper { + public interface OnMenuVisibilityListener { + public void onMenuVisibilityChanged(boolean isVisible); + } + + public static ActionBarWrapper getActionBar(Activity activity) { + if (PreferenceConstants.PRE_HONEYCOMB) + return new DummyActionBar(); + else + return new RealActionBar(activity); + } + + public void hide() { + } + + public void show() { + } + + public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { + } + + public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { + } + + private static class DummyActionBar extends ActionBarWrapper { + } + + @TargetApi(11) + private static class RealActionBar extends ActionBarWrapper { + private final ActionBar actionBar; + + public RealActionBar(Activity activity) { + actionBar = activity.getActionBar(); + } + + @Override + public void hide() { + actionBar.hide(); + } + + @Override + public void show() { + actionBar.show(); + } + + @Override + public void addOnMenuVisibilityListener(final OnMenuVisibilityListener listener) { + actionBar.addOnMenuVisibilityListener(new ActionBar.OnMenuVisibilityListener() { + public void onMenuVisibilityChanged(boolean isVisible) { + listener.onMenuVisibilityChanged(isVisible); + } + }); + } + + @Override + public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { + actionBar.setDisplayHomeAsUpEnabled(showHomeAsUp); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/ColorsActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,319 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import java.util.Arrays; +import java.util.List; + +import com.five_ten_sg.connectbot.util.Colors; +import com.five_ten_sg.connectbot.util.HostDatabase; +import com.five_ten_sg.connectbot.util.UberColorPickerDialog; +import com.five_ten_sg.connectbot.util.UberColorPickerDialog.OnColorChangedListener; +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.BaseAdapter; +import android.widget.GridView; +import android.widget.Spinner; + +/** + * @author Kenny Root + * + */ +public class ColorsActivity extends Activity implements OnItemClickListener, OnColorChangedListener, OnItemSelectedListener { + private GridView mColorGrid; + private Spinner mFgSpinner; + private Spinner mBgSpinner; + + private int mColorScheme; + + private List<Integer> mColorList; + private HostDatabase hostdb; + + private int mCurrentColor = 0; + + private int[] mDefaultColors; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.act_colors); + this.setTitle(String.format("%s: %s", + getResources().getText(R.string.app_name), + getResources().getText(R.string.title_colors))); + mColorScheme = HostDatabase.DEFAULT_COLOR_SCHEME; + hostdb = new HostDatabase(this); + mColorList = Arrays.asList(hostdb.getColorsForScheme(mColorScheme)); + mDefaultColors = hostdb.getDefaultColorsForScheme(mColorScheme); + mColorGrid = (GridView) findViewById(R.id.color_grid); + mColorGrid.setAdapter(new ColorsAdapter(true)); + mColorGrid.setOnItemClickListener(this); + mColorGrid.setSelection(0); + mFgSpinner = (Spinner) findViewById(R.id.fg); + mFgSpinner.setAdapter(new ColorsAdapter(false)); + mFgSpinner.setSelection(mDefaultColors[0]); + mFgSpinner.setOnItemSelectedListener(this); + mBgSpinner = (Spinner) findViewById(R.id.bg); + mBgSpinner.setAdapter(new ColorsAdapter(false)); + mBgSpinner.setSelection(mDefaultColors[1]); + mBgSpinner.setOnItemSelectedListener(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + if (hostdb != null) { + hostdb.close(); + hostdb = null; + } + } + + @Override + protected void onResume() { + super.onResume(); + + if (hostdb == null) + hostdb = new HostDatabase(this); + } + + private class ColorsAdapter extends BaseAdapter { + private boolean mSquareViews; + + public ColorsAdapter(boolean squareViews) { + mSquareViews = squareViews; + } + + public View getView(int position, View convertView, ViewGroup parent) { + ColorView c; + + if (convertView == null) { + c = new ColorView(ColorsActivity.this, mSquareViews); + } + else { + c = (ColorView) convertView; + } + + c.setColor(mColorList.get(position)); + c.setNumber(position + 1); + return c; + } + + public int getCount() { + return mColorList.size(); + } + + public Object getItem(int position) { + return mColorList.get(position); + } + + public long getItemId(int position) { + return position; + } + } + + private class ColorView extends View { + private boolean mSquare; + + private Paint mTextPaint; + private Paint mShadowPaint; + + // Things we paint + private int mBackgroundColor; + private String mText; + + private int mAscent; + private int mWidthCenter; + private int mHeightCenter; + + public ColorView(Context context, boolean square) { + super(context); + mSquare = square; + mTextPaint = new Paint(); + mTextPaint.setAntiAlias(true); + mTextPaint.setTextSize(16); + mTextPaint.setColor(0xFFFFFFFF); + mTextPaint.setTextAlign(Paint.Align.CENTER); + mShadowPaint = new Paint(mTextPaint); + mShadowPaint.setStyle(Paint.Style.STROKE); + mShadowPaint.setStrokeCap(Paint.Cap.ROUND); + mShadowPaint.setStrokeJoin(Paint.Join.ROUND); + mShadowPaint.setStrokeWidth(4f); + mShadowPaint.setColor(0xFF000000); + setPadding(10, 10, 10, 10); + } + + public void setColor(int color) { + mBackgroundColor = color; + } + + public void setNumber(int number) { + mText = Integer.toString(number); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = measureWidth(widthMeasureSpec); + int height; + + if (mSquare) + height = width; + else + height = measureHeight(heightMeasureSpec); + + mAscent = (int) mTextPaint.ascent(); + mWidthCenter = width / 2; + mHeightCenter = height / 2 - mAscent / 2; + setMeasuredDimension(width, height); + } + + private int measureWidth(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + // We were told how big to be + result = specSize; + } + else { + // Measure the text + result = (int) mTextPaint.measureText(mText) + getPaddingLeft() + + getPaddingRight(); + + if (specMode == MeasureSpec.AT_MOST) { + // Respect AT_MOST value if that was what is called for by + // measureSpec + result = Math.min(result, specSize); + } + } + + return result; + } + + private int measureHeight(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + mAscent = (int) mTextPaint.ascent(); + + if (specMode == MeasureSpec.EXACTLY) { + // We were told how big to be + result = specSize; + } + else { + // Measure the text (beware: ascent is a negative number) + result = (int)(-mAscent + mTextPaint.descent()) + + getPaddingTop() + getPaddingBottom(); + + if (specMode == MeasureSpec.AT_MOST) { + // Respect AT_MOST value if that was what is called for by + // measureSpec + result = Math.min(result, specSize); + } + } + + return result; + } + + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawColor(mBackgroundColor); + canvas.drawText(mText, mWidthCenter, mHeightCenter, mShadowPaint); + canvas.drawText(mText, mWidthCenter, mHeightCenter, mTextPaint); + } + } + + private void editColor(int colorNumber) { + mCurrentColor = colorNumber; + new UberColorPickerDialog(this, this, mColorList.get(colorNumber)).show(); + } + + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + editColor(position); + } + + public void onNothingSelected(AdapterView<?> arg0) { } + + public void colorChanged(int value) { + hostdb.setGlobalColor(mCurrentColor, value); + mColorList.set(mCurrentColor, value); + mColorGrid.invalidateViews(); + } + + public void onItemSelected(AdapterView<?> parent, View view, int position, + long id) { + boolean needUpdate = false; + + if (parent == mFgSpinner) { + if (position != mDefaultColors[0]) { + mDefaultColors[0] = position; + needUpdate = true; + } + } + else if (parent == mBgSpinner) { + if (position != mDefaultColors[1]) { + mDefaultColors[1] = position; + needUpdate = true; + } + } + + if (needUpdate) + hostdb.setDefaultColorsForScheme(mColorScheme, mDefaultColors[0], mDefaultColors[1]); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuItem reset = menu.add(R.string.menu_colors_reset); + reset.setAlphabeticShortcut('r'); + reset.setNumericShortcut('1'); + reset.setIcon(android.R.drawable.ic_menu_revert); + reset.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem arg0) { + // Reset each individual color to defaults. + for (int i = 0; i < Colors.defaults.length; i++) { + if (mColorList.get(i) != Colors.defaults[i]) { + hostdb.setGlobalColor(i, Colors.defaults[i]); + mColorList.set(i, Colors.defaults[i]); + } + } + + mColorGrid.invalidateViews(); + // Reset the default FG/BG colors as well. + mFgSpinner.setSelection(HostDatabase.DEFAULT_FG_COLOR); + mBgSpinner.setSelection(HostDatabase.DEFAULT_BG_COLOR); + hostdb.setDefaultColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME, + HostDatabase.DEFAULT_FG_COLOR, HostDatabase.DEFAULT_BG_COLOR); + return true; + } + }); + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/ConsoleActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1508 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import com.five_ten_sg.connectbot.bean.SelectionArea; +import com.five_ten_sg.connectbot.service.PromptHelper; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalKeyListener; +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.util.FileChooser; +import com.five_ten_sg.connectbot.util.FileChooserCallback; +import com.five_ten_sg.connectbot.util.PreferenceConstants; +import com.five_ten_sg.connectbot.util.TransferThread; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.media.AudioManager; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.preference.PreferenceManager; +import android.text.ClipboardManager; +import android.text.InputType; +import android.text.method.PasswordTransformationMethod; +import android.text.method.SingleLineTransformationMethod; +import android.util.FloatMath; +import android.util.Log; +import android.view.GestureDetector; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnKeyListener; +import android.view.View.OnLongClickListener; +import android.view.View.OnTouchListener; +import android.view.ViewConfiguration; +import android.view.WindowManager; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; +import android.widget.ViewFlipper; +import de.mud.terminal.vt320; + +public class ConsoleActivity extends Activity implements FileChooserCallback { + public final static String TAG = "ConnectBot.ConsoleActivity"; + + protected static final int REQUEST_EDIT = 1; + + private static final int CLICK_TIME = 400; + private static final float MAX_CLICK_DISTANCE = 25f; + private static final int KEYBOARD_DISPLAY_TIME = 1500; + + // Direction to shift the ViewFlipper + private static final int SHIFT_LEFT = 0; + private static final int SHIFT_RIGHT = 1; + + protected ViewFlipper flip = null; + protected TerminalManager bound = null; + protected LayoutInflater inflater = null; + + private SharedPreferences prefs = null; + + // determines whether or not menuitem accelerators are bound + // otherwise they collide with an external keyboard's CTRL-char + private boolean hardKeyboard = false; + + // determines whether we are in the fullscreen mode + private static final int FULLSCREEN_ON = 1; + private static final int FULLSCREEN_OFF = 2; + + private int fullScreen; + + protected Uri requested; + + protected ClipboardManager clipboard; + private RelativeLayout stringPromptGroup; + protected EditText stringPrompt; + private TextView stringPromptInstructions; + + private RelativeLayout booleanPromptGroup; + private TextView booleanPrompt; + private Button booleanYes, booleanNo; + + private RelativeLayout keyboardGroup; + private Runnable keyboardGroupHider; + + private TextView empty; + + private Animation slide_left_in, slide_left_out, slide_right_in, slide_right_out, fade_stay_hidden, fade_out_delayed; + + private Animation keyboard_fade_in, keyboard_fade_out; + private float lastX, lastY; + + private InputMethodManager inputManager; + + private MenuItem disconnect, copy, paste, portForward, resize, urlscan, screenCapture, download, upload; + + protected TerminalBridge copySource = null; + private int lastTouchRow, lastTouchCol; + + private boolean forcedOrientation; + + private Handler handler = new Handler(); + + private ImageView mKeyboardButton; + + private ActionBarWrapper actionBar; + private boolean inActionBarMenu = false; + + private ServiceConnection connection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + bound = ((TerminalManager.TerminalBinder) service).getService(); + // let manager know about our event handling services + bound.disconnectHandler = disconnectHandler; + Log.d(TAG, String.format("Connected to TerminalManager and found bridges.size=%d", bound.bridges.size())); + bound.setResizeAllowed(true); + bound.hardKeyboardHidden = (getResources().getConfiguration().hardKeyboardHidden == + Configuration.HARDKEYBOARDHIDDEN_YES); + + // set fullscreen value + if (bound.getFullScreen() == 0) { + setFullScreen(FULLSCREEN_OFF); + } + else if (fullScreen != bound.getFullScreen()) + setFullScreen(bound.getFullScreen()); + + // clear out any existing bridges and record requested index + flip.removeAllViews(); + final String requestedNickname = (requested != null) ? requested.getFragment() : null; + int requestedIndex = -1; + TerminalBridge requestedBridge = bound.getConnectedBridge(requestedNickname); + + // If we didn't find the requested connection, try opening it + if (requestedNickname != null && requestedBridge == null) { + try { + Log.d(TAG, String.format("We couldnt find an existing bridge with URI=%s (nickname=%s), so creating one now", requested.toString(), requestedNickname)); + requestedBridge = bound.openConnection(requested); + } + catch (Exception e) { + Log.e(TAG, "Problem while trying to create new requested bridge from URI", e); + } + } + + // create views for all bridges on this service + for (TerminalBridge bridge : bound.bridges) { + final int currentIndex = addNewTerminalView(bridge); + + // check to see if this bridge was requested + if (bridge == requestedBridge) { + requestedIndex = currentIndex; + // store this bridge as default bridge + bound.defaultBridge = bridge; + } + } + + // if no bridge was requested, try using default bridge + if (requestedIndex < 0) { + requestedIndex = getFlipIndex(bound.defaultBridge); + + if (requestedIndex < 0) + requestedIndex = 0; + } + + setDisplayedTerminal(requestedIndex); + } + public void onServiceDisconnected(ComponentName className) { + // tell each bridge to forget about our prompt handler + synchronized (bound.bridges) { + for (TerminalBridge bridge : bound.bridges) + bridge.promptHelper.setHandler(null); + } + + flip.removeAllViews(); + updateEmptyVisible(); + bound = null; + } + }; + + protected Handler promptHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + // someone below us requested to display a prompt + updatePromptVisible(); + } + }; + + protected Handler disconnectHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + Log.d(TAG, "Someone sending HANDLE_DISCONNECT to parentHandler"); + // someone below us requested to display a password dialog + // they are sending nickname and requested + TerminalBridge bridge = (TerminalBridge)msg.obj; + + if (bridge.isAwaitingClose()) + closeBridge(bridge); + } + }; + + /** + * @param bridge + */ + private void closeBridge(final TerminalBridge bridge) { + synchronized (flip) { + final int flipIndex = getFlipIndex(bridge); + + if (flipIndex >= 0) { + if (flip.getDisplayedChild() == flipIndex) { + shiftCurrentTerminal(SHIFT_LEFT); + } + + flip.removeViewAt(flipIndex); + /* TODO Remove this workaround when ViewFlipper is fixed to listen + * to view removals. Android Issue 1784 + */ + final int numChildren = flip.getChildCount(); + + if (flip.getDisplayedChild() >= numChildren && + numChildren > 0) { + flip.setDisplayedChild(numChildren - 1); + } + + updateEmptyVisible(); + } + + // If we just closed the last bridge, go back to the previous activity. + if (flip.getChildCount() == 0) { + finish(); + } + } + } + + protected View findCurrentView(int id) { + View view = flip.getCurrentView(); + + if (view == null) return null; + + return view.findViewById(id); + } + + protected PromptHelper getCurrentPromptHelper() { + View view = findCurrentView(R.id.console_flip); + + if (!(view instanceof TerminalView)) return null; + + return ((TerminalView)view).bridge.promptHelper; + } + + protected void hideAllPrompts() { + stringPromptGroup.setVisibility(View.GONE); + booleanPromptGroup.setVisibility(View.GONE); + // adjust window back if size was changed during prompt input + View view = findCurrentView(R.id.console_flip); + + if (!(view instanceof TerminalView)) return; + + ((TerminalView)view).bridge.parentChanged((TerminalView)view); + } + + private void showEmulatedKeys() { + keyboardGroup.startAnimation(keyboard_fade_in); + keyboardGroup.setVisibility(View.VISIBLE); + actionBar.show(); + + if (keyboardGroupHider != null) + handler.removeCallbacks(keyboardGroupHider); + + keyboardGroupHider = new Runnable() { + public void run() { + if (keyboardGroup.getVisibility() == View.GONE || inActionBarMenu) + return; + + keyboardGroup.startAnimation(keyboard_fade_out); + keyboardGroup.setVisibility(View.GONE); + actionBar.hide(); + keyboardGroupHider = null; + } + }; + handler.postDelayed(keyboardGroupHider, KEYBOARD_DISPLAY_TIME); + } + + private void hideEmulatedKeys() { + if (keyboardGroupHider != null) + handler.removeCallbacks(keyboardGroupHider); + + keyboardGroup.setVisibility(View.GONE); + actionBar.hide(); + } + + // more like configureLaxMode -- enable network IO on UI thread + private void configureStrictMode() { + try { + Class.forName("android.os.StrictMode"); + StrictModeSetup.run(); + } + catch (ClassNotFoundException e) { + } + } + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + configureStrictMode(); + hardKeyboard = getResources().getConfiguration().keyboard == + Configuration.KEYBOARD_QWERTY; + this.setContentView(R.layout.act_console); + clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE); + prefs = PreferenceManager.getDefaultSharedPreferences(this); + // TODO find proper way to disable volume key beep if it exists. + setVolumeControlStream(AudioManager.STREAM_MUSIC); + // handle requested console from incoming intent + requested = getIntent().getData(); + inflater = LayoutInflater.from(this); + flip = (ViewFlipper)findViewById(R.id.console_flip); + empty = (TextView)findViewById(android.R.id.empty); + stringPromptGroup = (RelativeLayout) findViewById(R.id.console_password_group); + stringPromptInstructions = (TextView) findViewById(R.id.console_password_instructions); + stringPrompt = (EditText)findViewById(R.id.console_password); + stringPrompt.setOnKeyListener(new OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_UP) return false; + + if (keyCode != KeyEvent.KEYCODE_ENTER) return false; + + // pass collected password down to current terminal + String value = stringPrompt.getText().toString(); + PromptHelper helper = getCurrentPromptHelper(); + + if (helper == null) return false; + + helper.setResponse(value); + // finally clear password for next user + stringPrompt.setText(""); + updatePromptVisible(); + return true; + } + }); + booleanPromptGroup = (RelativeLayout) findViewById(R.id.console_boolean_group); + booleanPrompt = (TextView)findViewById(R.id.console_prompt); + booleanYes = (Button)findViewById(R.id.console_prompt_yes); + booleanYes.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + PromptHelper helper = getCurrentPromptHelper(); + + if (helper == null) return; + + helper.setResponse(Boolean.TRUE); + updatePromptVisible(); + } + }); + booleanNo = (Button)findViewById(R.id.console_prompt_no); + booleanNo.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + PromptHelper helper = getCurrentPromptHelper(); + + if (helper == null) return; + + helper.setResponse(Boolean.FALSE); + updatePromptVisible(); + } + }); + // preload animations for terminal switching + slide_left_in = AnimationUtils.loadAnimation(this, R.anim.slide_left_in); + slide_left_out = AnimationUtils.loadAnimation(this, R.anim.slide_left_out); + slide_right_in = AnimationUtils.loadAnimation(this, R.anim.slide_right_in); + slide_right_out = AnimationUtils.loadAnimation(this, R.anim.slide_right_out); + fade_out_delayed = AnimationUtils.loadAnimation(this, R.anim.fade_out_delayed); + fade_stay_hidden = AnimationUtils.loadAnimation(this, R.anim.fade_stay_hidden); + // Preload animation for keyboard button + keyboard_fade_in = AnimationUtils.loadAnimation(this, R.anim.keyboard_fade_in); + keyboard_fade_out = AnimationUtils.loadAnimation(this, R.anim.keyboard_fade_out); + inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + keyboardGroup = (RelativeLayout) findViewById(R.id.keyboard_group); + mKeyboardButton = (ImageView) findViewById(R.id.button_keyboard); + mKeyboardButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) + return; + + inputManager.showSoftInput(flip, InputMethodManager.SHOW_FORCED); + hideEmulatedKeys(); + } + }); + final ImageView symButton = (ImageView) findViewById(R.id.button_sym); + symButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) return; + + TerminalView terminal = (TerminalView)flip; + terminal.bridge.showCharPickerDialog(); + keyboardGroup.setVisibility(View.GONE); + } + }); + symButton.setOnLongClickListener(new OnLongClickListener() { + public boolean onLongClick(View view) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) return false; + + TerminalView terminal = (TerminalView)flip; + terminal.bridge.showArrowsDialog(); + return true; + } + }); + final ImageView mInputButton = (ImageView) findViewById(R.id.button_input); + mInputButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) return; + + final TerminalView terminal = (TerminalView)flip; + Thread promptThread = new Thread(new Runnable() { + public void run() { + String inj = getCurrentPromptHelper().requestStringPrompt(null, ""); + terminal.bridge.injectString(inj); + } + }); + promptThread.setName("Prompt"); + promptThread.setDaemon(true); + promptThread.start(); + keyboardGroup.setVisibility(View.GONE); + } + }); + final ImageView ctrlButton = (ImageView) findViewById(R.id.button_ctrl); + ctrlButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) return; + + TerminalView terminal = (TerminalView)flip; + TerminalKeyListener handler = terminal.bridge.getKeyHandler(); + handler.metaPress(TerminalKeyListener.META_CTRL_ON); + hideEmulatedKeys(); + } + }); + ctrlButton.setOnLongClickListener(new OnLongClickListener() { + public boolean onLongClick(View view) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) return false; + + TerminalView terminal = (TerminalView)flip; + terminal.bridge.showCtrlDialog(); + return true; + } + }); + final ImageView escButton = (ImageView) findViewById(R.id.button_esc); + escButton.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) return; + + TerminalView terminal = (TerminalView)flip; + TerminalKeyListener handler = terminal.bridge.getKeyHandler(); + handler.sendEscape(); + hideEmulatedKeys(); + } + }); + escButton.setOnLongClickListener(new OnLongClickListener() { + public boolean onLongClick(View view) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) return false; + + TerminalView terminal = (TerminalView)flip; + terminal.bridge.showFKeysDialog(); + return true; + } + }); + actionBar = ActionBarWrapper.getActionBar(this); + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.hide(); + actionBar.addOnMenuVisibilityListener(new ActionBarWrapper.OnMenuVisibilityListener() { + public void onMenuVisibilityChanged(boolean isVisible) { + inActionBarMenu = isVisible; + + if (isVisible == false) { + hideEmulatedKeys(); + } + } + }); + // detect fling gestures to switch between terminals + final GestureDetector gestDetect = new GestureDetector(new GestureDetector.SimpleOnGestureListener() { + private float totalY = 0; + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + final float distx = e2.getRawX() - e1.getRawX(); + final float disty = e2.getRawY() - e1.getRawY(); + final int goalwidth = flip.getWidth() / 2; + + // need to slide across half of display to trigger console change + // make sure user kept a steady hand horizontally + if (Math.abs(disty) < (flip.getHeight() / 4)) { + if (distx > goalwidth) { + shiftCurrentTerminal(SHIFT_RIGHT); + return true; + } + + if (distx < -goalwidth) { + shiftCurrentTerminal(SHIFT_LEFT); + return true; + } + } + + return false; + } + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + // if copying, then ignore + if (copySource != null && copySource.isSelectingForCopy()) + return false; + + if (e1 == null || e2 == null) + return false; + + // if releasing then reset total scroll + if (e2.getAction() == MotionEvent.ACTION_UP) { + totalY = 0; + } + + // activate consider if within x tolerance + if (Math.abs(e1.getX() - e2.getX()) < ViewConfiguration.getTouchSlop() * 4) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) return false; + + TerminalView terminal = (TerminalView)flip; + // estimate how many rows we have scrolled through + // accumulate distance that doesn't trigger immediate scroll + totalY += distanceY; + final int moved = (int)(totalY / terminal.bridge.charHeight); + + // consume as scrollback only if towards right half of screen + if (e2.getX() > flip.getWidth() / 2) { + if (moved != 0) { + int base = terminal.bridge.buffer.getWindowBase(); + terminal.bridge.buffer.setWindowBase(base + moved); + totalY = 0; + return true; + } + } + else { + // otherwise consume as pgup/pgdown for every 5 lines + if (moved > 5) { + ((vt320)terminal.bridge.buffer).keyPressed(vt320.KEY_PAGE_DOWN, ' ', 0); + terminal.bridge.tryKeyVibrate(); + totalY = 0; + return true; + } + else if (moved < -5) { + ((vt320)terminal.bridge.buffer).keyPressed(vt320.KEY_PAGE_UP, ' ', 0); + terminal.bridge.tryKeyVibrate(); + totalY = 0; + return true; + } + } + } + + return false; + } + /* + * Enables longpress and popups menu + * + * @see + * android.view.GestureDetector.SimpleOnGestureListener# + * onLongPress(android.view.MotionEvent) + * + * @return void + */ + @Override + public void onLongPress(MotionEvent e) { + List<String> itemList = new ArrayList<String>(); + final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + + if (terminalView == null) return; + + final TerminalBridge bridge = terminalView.bridge; + + if (fullScreen == FULLSCREEN_ON) + itemList.add(ConsoleActivity.this + .getResources().getString(R.string.longpress_disable_full_screen_mode)); + else + itemList.add(ConsoleActivity.this + .getResources().getString(R.string.longpress_enable_full_screen_mode)); + + itemList.add(ConsoleActivity.this + .getResources().getString(R.string.longpress_change_font_size)); + + if (prefs.getBoolean(PreferenceConstants.EXTENDED_LONGPRESS, false)) { + itemList.add(ConsoleActivity.this + .getResources().getString(R.string.longpress_arrows_dialog)); + itemList.add(ConsoleActivity.this + .getResources().getString(R.string.longpress_fkeys_dialog)); + itemList.add(ConsoleActivity.this + .getResources().getString(R.string.longpress_ctrl_dialog)); + itemList.add(ConsoleActivity.this + .getResources().getString(R.string.longpress_sym_dialog)); + } + + if (itemList.size() > 0) { + AlertDialog.Builder builder = new AlertDialog.Builder(ConsoleActivity.this); + builder.setTitle(R.string.longpress_select_action); + builder.setItems(itemList.toArray(new CharSequence[itemList.size()]), + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + switch (item) { + case 0: + if (fullScreen == FULLSCREEN_ON) { + setFullScreen(FULLSCREEN_OFF); + } + else + setFullScreen(FULLSCREEN_ON); + + break; + + case 1: + bridge.showFontSizeDialog(); + break; + + case 2: + bridge.showArrowsDialog(); + break; + + case 3: + bridge.showFKeysDialog(); + break; + + case 4: + bridge.showCtrlDialog(); + break; + + case 5: + bridge.showCharPickerDialog(); + } + } + }); + AlertDialog alert = builder.create(); + alert.show(); + } + } + }); + flip.setLongClickable(true); + flip.setOnTouchListener(new OnTouchListener() { + public boolean onTouch(View v, MotionEvent event) { + // when copying, highlight the area + if (copySource != null && copySource.isSelectingForCopy()) { + int row = (int)FloatMath.floor(event.getY() / copySource.charHeight); + int col = (int)FloatMath.floor(event.getX() / copySource.charWidth); + SelectionArea area = copySource.getSelectionArea(); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + + // recording starting area + if (area.isSelectingOrigin()) { + area.setRow(row); + area.setColumn(col); + lastTouchRow = row; + lastTouchCol = col; + copySource.redraw(); + } + + return true; + + case MotionEvent.ACTION_MOVE: + + /* ignore when user hasn't moved since last time so + * we can fine-tune with directional pad + */ + if (row == lastTouchRow && col == lastTouchCol) + return true; + + // if the user moves, start the selection for other corner + area.finishSelectingOrigin(); + // update selected area + area.setRow(row); + area.setColumn(col); + lastTouchRow = row; + lastTouchCol = col; + copySource.redraw(); + return true; + + case MotionEvent.ACTION_UP: + + /* If they didn't move their finger, maybe they meant to + * select the rest of the text with the directional pad. + */ + if (area.getLeft() == area.getRight() && + area.getTop() == area.getBottom()) { + return true; + } + + // copy selected area to clipboard + String copiedText = area.copyFrom(copySource.buffer); + clipboard.setText(copiedText); + Toast.makeText(ConsoleActivity.this, getString(R.string.console_copy_done, copiedText.length()), Toast.LENGTH_LONG).show(); + + // fall through to clear state + case MotionEvent.ACTION_CANCEL: + // make sure we clear any highlighted area + area.reset(); + copySource.setSelectingForCopy(false); + copySource.redraw(); + return true; + } + } + + Configuration config = getResources().getConfiguration(); + + if (event.getAction() == MotionEvent.ACTION_DOWN) { + lastX = event.getX(); + lastY = event.getY(); + } + else if (event.getAction() == MotionEvent.ACTION_UP + && keyboardGroup.getVisibility() == View.GONE + && event.getEventTime() - event.getDownTime() < CLICK_TIME + && Math.abs(event.getX() - lastX) < MAX_CLICK_DISTANCE + && Math.abs(event.getY() - lastY) < MAX_CLICK_DISTANCE) { + showEmulatedKeys(); + } + + // pass any touch events back to BOTH detectors + TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + boolean rc = false; + if ((terminalView != null) && terminalView.mScaleDetector.onTouchEvent(event)) rc = true; + if (gestDetect.onTouchEvent(event)) rc = true; + return rc; + } + }); + } + + /** + * + */ + private void configureOrientation() { + String rotateDefault; + + if (getResources().getConfiguration().keyboard == Configuration.KEYBOARD_NOKEYS) + rotateDefault = PreferenceConstants.ROTATION_PORTRAIT; + else + rotateDefault = PreferenceConstants.ROTATION_LANDSCAPE; + + String rotate = prefs.getString(PreferenceConstants.ROTATION, rotateDefault); + + if (PreferenceConstants.ROTATION_DEFAULT.equals(rotate)) + rotate = rotateDefault; + + // request a forced orientation if requested by user + if (PreferenceConstants.ROTATION_LANDSCAPE.equals(rotate)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + forcedOrientation = true; + } + else if (PreferenceConstants.ROTATION_PORTRAIT.equals(rotate)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + forcedOrientation = true; + } + else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + forcedOrientation = false; + } + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + View view = findCurrentView(R.id.console_flip); + final boolean activeTerminal = (view instanceof TerminalView); + boolean sessionOpen = false; + boolean disconnected = false; + boolean canForwardPorts = false; + boolean canTransferFiles = false; + + if (activeTerminal) { + TerminalBridge bridge = ((TerminalView) view).bridge; + sessionOpen = bridge.isSessionOpen(); + disconnected = bridge.isDisconnected(); + canForwardPorts = bridge.canFowardPorts(); + canTransferFiles = bridge.canTransferFiles(); + } + + menu.setQwertyMode(true); + + if (!PreferenceConstants.PRE_HONEYCOMB) { + MenuItem ctrlKey = menu.add(getString(R.string.fullscreen)); + ctrlKey.setEnabled(activeTerminal); + ctrlKey.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + ctrlKey.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem menuItem) { + if (fullScreen == FULLSCREEN_ON) { + setFullScreen(FULLSCREEN_OFF); + } + else + setFullScreen(FULLSCREEN_ON); + + return true; + } + }); + } + + disconnect = menu.add(R.string.list_host_disconnect); + + if (hardKeyboard) + disconnect.setAlphabeticShortcut('w'); + + if (!sessionOpen && disconnected) + disconnect.setTitle(R.string.console_menu_close); + + disconnect.setEnabled(activeTerminal); + disconnect.setIcon(android.R.drawable.ic_menu_close_clear_cancel); + disconnect.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // disconnect or close the currently visible session + TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + TerminalBridge bridge = terminalView.bridge; + bridge.dispatchDisconnect(true); + return true; + } + }); + copy = menu.add(R.string.console_menu_copy); + + if (hardKeyboard) + copy.setAlphabeticShortcut('c'); + + copy.setIcon(android.R.drawable.ic_menu_set_as); + copy.setEnabled(activeTerminal); + copy.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // mark as copying and reset any previous bounds + TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + copySource = terminalView.bridge; + SelectionArea area = copySource.getSelectionArea(); + area.reset(); + area.setBounds(copySource.buffer.getColumns(), copySource.buffer.getRows()); + copySource.setSelectingForCopy(true); + // Make sure we show the initial selection + copySource.redraw(); + Toast.makeText(ConsoleActivity.this, getString(R.string.console_copy_start), Toast.LENGTH_LONG).show(); + return true; + } + }); + paste = menu.add(R.string.console_menu_paste); + + if (hardKeyboard) + paste.setAlphabeticShortcut('v'); + + paste.setIcon(android.R.drawable.ic_menu_edit); + paste.setEnabled(clipboard.hasText() && sessionOpen); + paste.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // force insert of clipboard text into current console + TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + TerminalBridge bridge = terminalView.bridge; + // pull string from clipboard and generate all events to force down + String clip = clipboard.getText().toString(); + bridge.injectString(clip); + return true; + } + }); + resize = menu.add(R.string.console_menu_resize); + + if (hardKeyboard) + resize.setAlphabeticShortcut('r'); + + resize.setIcon(android.R.drawable.ic_menu_crop); + resize.setEnabled(activeTerminal); + resize.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + final View resizeView = inflater.inflate(R.layout.dia_resize, null, false); + ((EditText) resizeView.findViewById(R.id.width)).setText("80"); + ((EditText) resizeView.findViewById(R.id.height)).setText("25"); + new AlertDialog.Builder(ConsoleActivity.this) + .setView(resizeView) + .setPositiveButton(R.string.button_resize, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + int width, height; + + try { + width = Integer.parseInt(((EditText) resizeView + .findViewById(R.id.width)) + .getText().toString()); + height = Integer.parseInt(((EditText) resizeView + .findViewById(R.id.height)) + .getText().toString()); + } + catch (NumberFormatException nfe) { + // TODO change this to a real dialog where we can + // make the input boxes turn red to indicate an error. + return; + } + + if (width > 0 && height > 0) { + terminalView.forceSize(width, height); + } + else { + new AlertDialog.Builder(ConsoleActivity.this) + .setTitle(R.string.resize_error_title) + .setMessage(R.string.resize_error_width_height) + .setNegativeButton(R.string.button_close, null) + .show(); + } + } + }).setNeutralButton(R.string.button_resize_reset, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + terminalView.bridge.resetSize(terminalView); + } + }).setNegativeButton(android.R.string.cancel, null) + .create().show(); + return true; + } + }); + screenCapture = menu.add(R.string.console_menu_screencapture); + + if (hardKeyboard) + screenCapture.setAlphabeticShortcut('s'); + + screenCapture.setIcon(android.R.drawable.ic_menu_camera); + screenCapture.setEnabled(activeTerminal); + screenCapture.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + terminalView.bridge.captureScreen(); + return true; + } + }); + portForward = menu.add(R.string.console_menu_portforwards); + + if (hardKeyboard) + portForward.setAlphabeticShortcut('f'); + + portForward.setIcon(android.R.drawable.ic_menu_manage); + portForward.setEnabled(sessionOpen && canForwardPorts); + portForward.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + TerminalBridge bridge = terminalView.bridge; + Intent intent = new Intent(ConsoleActivity.this, PortForwardListActivity.class); + intent.putExtra(Intent.EXTRA_TITLE, bridge.host.getId()); + ConsoleActivity.this.startActivityForResult(intent, REQUEST_EDIT); + return true; + } + }); + urlscan = menu.add(R.string.console_menu_urlscan); + + if (hardKeyboard) + urlscan.setAlphabeticShortcut('l'); + + urlscan.setIcon(android.R.drawable.ic_menu_search); + urlscan.setEnabled(activeTerminal); + urlscan.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + View flip = findCurrentView(R.id.console_flip); + + if (flip == null) return true; + + TerminalView terminal = (TerminalView)flip; + TerminalKeyListener handler = terminal.bridge.getKeyHandler(); + handler.urlScan(terminal); + return true; + } + }); + download = menu.add(R.string.console_menu_download); + download.setAlphabeticShortcut('d'); + download.setEnabled(sessionOpen && canTransferFiles); + download.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + final String downloadFolder = prefs.getString(PreferenceConstants.DOWNLOAD_FOLDER, ""); + final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + final TerminalBridge bridge = terminalView.bridge; + final EditText textField = new EditText(ConsoleActivity.this); + new AlertDialog.Builder(ConsoleActivity.this) + .setTitle(R.string.transfer_select_remote_download_title) + .setMessage(R.string.transfer_select_remote_download_desc) + .setView(textField) + .setPositiveButton(R.string.transfer_button_download, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + TransferThread transfer = new TransferThread(ConsoleActivity.this, handler); + + if (!prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) + transfer.setProgressDialogMessage(getString(R.string.transfer_downloading)); + + transfer.download(bridge, textField.getText().toString(), null, downloadFolder); + } + }).setNegativeButton(android.R.string.cancel, null).create().show(); + return true; + } + }); + upload = menu.add(R.string.console_menu_upload); + upload.setAlphabeticShortcut('u'); + upload.setEnabled(sessionOpen && canTransferFiles); + upload.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + FileChooser.selectFile(ConsoleActivity.this, ConsoleActivity.this, + FileChooser.REQUEST_CODE_SELECT_FILE, + getString(R.string.file_chooser_select_file, getString(R.string.select_for_upload))); + return true; + } + }); + return true; + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent intent) { + super.onActivityResult(requestCode, resultCode, intent); + + switch (requestCode) { + case FileChooser.REQUEST_CODE_SELECT_FILE: + if (resultCode == RESULT_OK && intent != null) { + Uri uri = intent.getData(); + + try { + if (uri != null) { + fileSelected(new File(URI.create(uri.toString()))); + } + else { + String filename = intent.getDataString(); + + if (filename != null) { + fileSelected(new File(URI.create(filename))); + } + } + } + catch (IllegalArgumentException e) { + Log.e(TAG, "Couldn't read from selected file", e); + } + } + + break; + } + } + + public void fileSelected(final File f) { + String destFileName; + String uploadFolder = prefs.getString(PreferenceConstants.REMOTE_UPLOAD_FOLDER, null); + final TransferThread transfer = new TransferThread(ConsoleActivity.this, handler); + Log.d(TAG, "File chooser returned " + f); + + if (uploadFolder == null) + uploadFolder = ""; + + if (!uploadFolder.equals("") && uploadFolder.charAt(uploadFolder.length() - 1) != '/') + destFileName = uploadFolder + "/" + f.getName(); + else + destFileName = uploadFolder + f.getName(); + + if (prefs.getBoolean(PreferenceConstants.UPLOAD_DESTINATION_PROMPT, true)) { + final EditText fileDest = new EditText(ConsoleActivity.this); + fileDest.setSingleLine(); + fileDest.setText(destFileName); + new AlertDialog.Builder(ConsoleActivity.this) + .setTitle(R.string.transfer_select_remote_upload_dest_title) + .setMessage(getResources().getString(R.string.transfer_select_remote_upload_dest_desc) + "\n" + f.getPath()) + .setView(fileDest) + .setPositiveButton(R.string.transfer_button_upload, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + if (!prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) + transfer.setProgressDialogMessage(getString(R.string.transfer_uploading)); + + TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + TerminalBridge bridge = terminalView.bridge; + File uf = new File(fileDest.getText().toString()); + String name = "", parent = ""; + + if (uf.getParent() != null) + parent = uf.getParent().toString(); + + if (uf.getName() != null) + name = uf.getName().toString(); + + transfer.upload(bridge, f.toString(), name, parent); + } + }).setNegativeButton(android.R.string.cancel, null).create().show(); + } + else { + if (!prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) + transfer.setProgressDialogMessage(getString(R.string.transfer_uploading)); + + TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + TerminalBridge bridge = terminalView.bridge; + transfer.upload(bridge, f.toString(), null, uploadFolder); + } + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + setVolumeControlStream(AudioManager.STREAM_NOTIFICATION); + final View view = findCurrentView(R.id.console_flip); + boolean activeTerminal = (view instanceof TerminalView); + boolean sessionOpen = false; + boolean disconnected = false; + boolean canForwardPorts = false; + boolean canTransferFiles = false; + + if (activeTerminal) { + TerminalBridge bridge = ((TerminalView) view).bridge; + sessionOpen = bridge.isSessionOpen(); + disconnected = bridge.isDisconnected(); + canForwardPorts = bridge.canFowardPorts(); + canTransferFiles = bridge.canTransferFiles(); + } + + disconnect.setEnabled(activeTerminal); + + if (sessionOpen || !disconnected) + disconnect.setTitle(R.string.list_host_disconnect); + else + disconnect.setTitle(R.string.console_menu_close); + + copy.setEnabled(activeTerminal); + paste.setEnabled(clipboard.hasText() && sessionOpen); + portForward.setEnabled(sessionOpen && canForwardPorts); + urlscan.setEnabled(activeTerminal); + resize.setEnabled(activeTerminal); + download.setEnabled(sessionOpen && canTransferFiles); + upload.setEnabled(sessionOpen && canTransferFiles); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + Intent intent = new Intent(this, HostListActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + return true; + + default: + return super.onOptionsItemSelected(item); + } + } + + @Override + public void onOptionsMenuClosed(Menu menu) { + super.onOptionsMenuClosed(menu); + setVolumeControlStream(AudioManager.STREAM_MUSIC); + } + + @Override + public void onStart() { + super.onStart(); + // connect with manager service to find all bridges + // when connected it will insert all views + bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); + + if (getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) { + this.mKeyboardButton.setVisibility(View.GONE); + } + } + + @Override + public void onPause() { + super.onPause(); + Log.d(TAG, "onPause called"); + + if (forcedOrientation && bound != null) + bound.setResizeAllowed(false); + } + + @Override + public void onResume() { + super.onResume(); + Log.d(TAG, "onResume called"); + + // Make sure we don't let the screen fall asleep. + // This also keeps the Wi-Fi chipset from disconnecting us. + if (prefs.getBoolean(PreferenceConstants.KEEP_ALIVE, true)) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + else { + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + + configureOrientation(); + + if (forcedOrientation && bound != null) + bound.setResizeAllowed(true); + } + + /* (non-Javadoc) + * @see android.app.Activity#onNewIntent(android.content.Intent) + */ + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + Log.d(TAG, "onNewIntent called"); + requested = intent.getData(); + + if (requested == null) { + Log.e(TAG, "Got null intent data in onNewIntent()"); + return; + } + + if (bound == null) { + Log.e(TAG, "We're not bound in onNewIntent()"); + return; + } + + TerminalBridge requestedBridge = bound.getConnectedBridge(requested.getFragment()); + int requestedIndex = 0; + + synchronized (flip) { + if (requestedBridge == null) { + // If we didn't find the requested connection, try opening it + try { + Log.d(TAG, String.format("We couldnt find an existing bridge with URI=%s (nickname=%s)," + + "so creating one now", requested.toString(), requested.getFragment())); + requestedBridge = bound.openConnection(requested); + } + catch (Exception e) { + Log.e(TAG, "Problem while trying to create new requested bridge from URI", e); + // TODO: We should display an error dialog here. + return; + } + + requestedIndex = addNewTerminalView(requestedBridge); + } + else { + final int flipIndex = getFlipIndex(requestedBridge); + + if (flipIndex > requestedIndex) { + requestedIndex = flipIndex; + } + } + + setDisplayedTerminal(requestedIndex); + } + } + + @Override + public void onStop() { + super.onStop(); + unbindService(connection); + } + + protected void shiftCurrentTerminal(final int direction) { + View overlay; + + synchronized (flip) { + boolean shouldAnimate = flip.getChildCount() > 1; + + // Only show animation if there is something else to go to. + if (shouldAnimate) { + // keep current overlay from popping up again + overlay = findCurrentView(R.id.terminal_overlay); + + if (overlay != null) + overlay.startAnimation(fade_stay_hidden); + + if (direction == SHIFT_LEFT) { + flip.setInAnimation(slide_left_in); + flip.setOutAnimation(slide_left_out); + flip.showNext(); + } + else if (direction == SHIFT_RIGHT) { + flip.setInAnimation(slide_right_in); + flip.setOutAnimation(slide_right_out); + flip.showPrevious(); + } + } + + updateDefault(); + + if (shouldAnimate) { + // show overlay on new slide and start fade + overlay = findCurrentView(R.id.terminal_overlay); + + if (overlay != null) + overlay.startAnimation(fade_out_delayed); + } + + updatePromptVisible(); + } + } + + /** + * Save the currently shown {@link TerminalView} as the default. This is + * saved back down into {@link TerminalManager} where we can read it again + * later. + */ + private void updateDefault() { + // update the current default terminal + View view = findCurrentView(R.id.console_flip); + + if (!(view instanceof TerminalView)) return; + + TerminalView terminal = (TerminalView)view; + + if (bound != null) bound.defaultBridge = terminal.bridge; + + // tell the bridge monitor it has the topmost visible window now. + if (terminal.bridge.monitor != null) terminal.bridge.monitor.activate(); + } + + protected void updateEmptyVisible() { + // update visibility of empty status message + empty.setVisibility((flip.getChildCount() == 0) ? View.VISIBLE : View.GONE); + } + + /** + * Show any prompts requested by the currently visible {@link TerminalView}. + */ + protected void updatePromptVisible() { + // check if our currently-visible terminalbridge is requesting any prompt services + View view = findCurrentView(R.id.console_flip); + // Hide all the prompts in case a prompt request was canceled + hideAllPrompts(); + + if (!(view instanceof TerminalView)) { + // we dont have an active view, so hide any prompts + return; + } + + PromptHelper prompt = ((TerminalView)view).bridge.promptHelper; + + if (String.class.equals(prompt.promptRequested)) { + stringPromptGroup.setVisibility(View.VISIBLE); + String instructions = prompt.promptInstructions; + boolean password = prompt.passwordRequested; + + if (instructions != null && instructions.length() > 0) { + stringPromptInstructions.setVisibility(View.VISIBLE); + stringPromptInstructions.setText(instructions); + } + else + stringPromptInstructions.setVisibility(View.GONE); + + if (password) { + stringPrompt.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_PASSWORD); + stringPrompt.setTransformationMethod(PasswordTransformationMethod.getInstance()); + } + else { + stringPrompt.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); + stringPrompt.setTransformationMethod(SingleLineTransformationMethod.getInstance()); + } + + stringPrompt.setText(""); + stringPrompt.setHint(prompt.promptHint); + stringPrompt.requestFocus(); + } + else if (Boolean.class.equals(prompt.promptRequested)) { + booleanPromptGroup.setVisibility(View.VISIBLE); + booleanPrompt.setText(prompt.promptHint); + booleanYes.requestFocus(); + } + else { + hideAllPrompts(); + view.requestFocus(); + } + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + Log.d(TAG, String.format("onConfigurationChanged; requestedOrientation=%d, newConfig.orientation=%d", getRequestedOrientation(), newConfig.orientation)); + + if (bound != null) { + if (forcedOrientation && + (newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE && + getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) || + (newConfig.orientation != Configuration.ORIENTATION_PORTRAIT && + getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)) + bound.setResizeAllowed(false); + else + bound.setResizeAllowed(true); + + bound.hardKeyboardHidden = (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES); + mKeyboardButton.setVisibility(bound.hardKeyboardHidden ? View.VISIBLE : View.GONE); + } + } + + /** + * Adds a new TerminalBridge to the current set of views in our ViewFlipper. + * + * @param bridge TerminalBridge to add to our ViewFlipper + * @return the child index of the new view in the ViewFlipper + */ + private int addNewTerminalView(TerminalBridge bridge) { + // let them know about our prompt handler services + bridge.promptHelper.setHandler(promptHandler); + // inflate each terminal view + RelativeLayout view = (RelativeLayout)inflater.inflate(R.layout.item_terminal, flip, false); + // set the terminal overlay text + TextView overlay = (TextView)view.findViewById(R.id.terminal_overlay); + overlay.setText(bridge.host.getNickname()); + // and add our terminal view control, using index to place behind overlay + TerminalView terminal = new TerminalView(ConsoleActivity.this, bridge); + terminal.setId(R.id.console_flip); + view.addView(terminal, 0); + + synchronized (flip) { + // finally attach to the flipper + flip.addView(view); + return flip.getChildCount() - 1; + } + } + + private int getFlipIndex(TerminalBridge bridge) { + synchronized (flip) { + final int children = flip.getChildCount(); + + for (int i = 0; i < children; i++) { + final View view = flip.getChildAt(i).findViewById(R.id.console_flip); + + if (view == null || !(view instanceof TerminalView)) { + // How did that happen? + continue; + } + + final TerminalView tv = (TerminalView) view; + + if (tv.bridge == bridge) { + return i; + } + } + } + + return -1; + } + + /** + * Displays the child in the ViewFlipper at the requestedIndex and updates the prompts. + * + * @param requestedIndex the index of the terminal view to display + */ + private void setDisplayedTerminal(int requestedIndex) { + synchronized (flip) { + try { + // show the requested bridge if found, also fade out overlay + flip.setDisplayedChild(requestedIndex); + flip.getCurrentView().findViewById(R.id.terminal_overlay) + .startAnimation(fade_out_delayed); + } + catch (NullPointerException npe) { + Log.d(TAG, "View went away when we were about to display it", npe); + } + + updatePromptVisible(); + updateEmptyVisible(); + } + } + + private void setFullScreen(int fullScreen) { + if (fullScreen != this.fullScreen) { + if (fullScreen == FULLSCREEN_ON) { + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + else { + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + this.fullScreen = fullScreen; + + if (bound != null) + bound.setFullScreen(this.fullScreen); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/GeneratePubkeyActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,321 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; + +import com.five_ten_sg.connectbot.bean.PubkeyBean; +import com.five_ten_sg.connectbot.util.EntropyDialog; +import com.five_ten_sg.connectbot.util.EntropyView; +import com.five_ten_sg.connectbot.util.OnEntropyGatheredListener; +import com.five_ten_sg.connectbot.util.PubkeyDatabase; +import com.five_ten_sg.connectbot.util.PubkeyUtils; +import android.app.Activity; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnFocusChangeListener; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.RadioGroup; +import android.widget.RadioGroup.OnCheckedChangeListener; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; + +import ch.ethz.ssh2.crypto.SecureRandomFix; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; + +public class GeneratePubkeyActivity extends Activity implements OnEntropyGatheredListener { + public final static String TAG = "ConnectBot.GeneratePubkeyActivity"; + + private static final int RSA_MINIMUM_BITS = 768; + final static int DEFAULT_BITS = 2048; + final static int DSA_BITS = 1024; + final static int[] ECDSA_SIZES = ECDSASHA2Verify.getCurveSizes(); + final static int ECDSA_DEFAULT_BITS = ECDSA_SIZES[0]; + + private LayoutInflater inflater = null; + + private EditText nickname; + private RadioGroup keyTypeGroup; + private SeekBar bitsSlider; + private EditText bitsText; + private CheckBox unlockAtStartup; + private CheckBox confirmUse; + private Button save; + private Dialog entropyDialog; + private ProgressDialog progress; + + private EditText password1, password2; + + private String keyType = PubkeyDatabase.KEY_TYPE_RSA; + private int minBits = RSA_MINIMUM_BITS; + private int bits = DEFAULT_BITS; + + private byte[] entropy; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.act_generatepubkey); + nickname = (EditText) findViewById(R.id.nickname); + keyTypeGroup = (RadioGroup) findViewById(R.id.key_type); + bitsText = (EditText) findViewById(R.id.bits); + bitsSlider = (SeekBar) findViewById(R.id.bits_slider); + password1 = (EditText) findViewById(R.id.password1); + password2 = (EditText) findViewById(R.id.password2); + unlockAtStartup = (CheckBox) findViewById(R.id.unlock_at_startup); + confirmUse = (CheckBox) findViewById(R.id.confirm_use); + save = (Button) findViewById(R.id.save); + inflater = LayoutInflater.from(this); + nickname.addTextChangedListener(textChecker); + password1.addTextChangedListener(textChecker); + password2.addTextChangedListener(textChecker); + keyTypeGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() { + public void onCheckedChanged(RadioGroup group, int checkedId) { + if (checkedId == R.id.rsa) { + minBits = RSA_MINIMUM_BITS; + bitsSlider.setEnabled(true); + bitsSlider.setProgress(DEFAULT_BITS - minBits); + bitsText.setText(String.valueOf(DEFAULT_BITS)); + bitsText.setEnabled(true); + keyType = PubkeyDatabase.KEY_TYPE_RSA; + } + else if (checkedId == R.id.dsa) { + // DSA keys can only be 1024 bits + bitsSlider.setEnabled(false); + bitsSlider.setProgress(DSA_BITS - minBits); + bitsText.setText(String.valueOf(DSA_BITS)); + bitsText.setEnabled(false); + keyType = PubkeyDatabase.KEY_TYPE_DSA; + } + else if (checkedId == R.id.ec) { + minBits = ECDSA_DEFAULT_BITS; + bitsSlider.setEnabled(true); + bitsSlider.setProgress(ECDSA_DEFAULT_BITS - minBits); + bitsText.setText(String.valueOf(ECDSA_DEFAULT_BITS)); + bitsText.setEnabled(true); + keyType = PubkeyDatabase.KEY_TYPE_EC; + } + } + }); + bitsSlider.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { + public void onProgressChanged(SeekBar seekBar, int progress, + boolean fromTouch) { + if (PubkeyDatabase.KEY_TYPE_EC.equals(keyType)) { + bits = getClosestFieldSize(progress + minBits); + seekBar.setProgress(bits - minBits); + } + else { + // Stay evenly divisible by 8 because it looks nicer to have + // 2048 than 2043 bits. + final int ourProgress = progress - (progress % 8); + bits = minBits + ourProgress; + } + + bitsText.setText(String.valueOf(bits)); + } + public void onStartTrackingTouch(SeekBar seekBar) { + // We don't care about the start. + } + public void onStopTrackingTouch(SeekBar seekBar) { + // We don't care about the stop. + } + }); + bitsText.setOnFocusChangeListener(new OnFocusChangeListener() { + public void onFocusChange(View v, boolean hasFocus) { + if (!hasFocus) { + final boolean isEc = PubkeyDatabase.KEY_TYPE_EC.equals(keyType); + + try { + bits = Integer.parseInt(bitsText.getText().toString()); + + if (bits < minBits) { + bits = minBits; + bitsText.setText(String.valueOf(bits)); + } + + if (isEc) { + bits = getClosestFieldSize(bits); + } + } + catch (NumberFormatException nfe) { + bits = isEc ? ECDSA_DEFAULT_BITS : DEFAULT_BITS; + bitsText.setText(String.valueOf(bits)); + } + + bitsSlider.setProgress(bits - minBits); + } + } + }); + save.setOnClickListener(new OnClickListener() { + public void onClick(View view) { + GeneratePubkeyActivity.this.save.setEnabled(false); + GeneratePubkeyActivity.this.startEntropyGather(); + } + }); + } + + private void checkEntries() { + boolean allowSave = true; + + if (!password1.getText().toString().equals(password2.getText().toString())) + allowSave = false; + + if (nickname.getText().length() == 0) + allowSave = false; + + save.setEnabled(allowSave); + } + + private void startEntropyGather() { + final View entropyView = inflater.inflate(R.layout.dia_gatherentropy, null, false); + ((EntropyView)entropyView.findViewById(R.id.entropy)).addOnEntropyGatheredListener(GeneratePubkeyActivity.this); + entropyDialog = new EntropyDialog(GeneratePubkeyActivity.this, entropyView); + entropyDialog.show(); + } + + public void onEntropyGathered(byte[] entropy) { + // For some reason the entropy dialog was aborted, exit activity + if (entropy == null) { + finish(); + return; + } + + this.entropy = entropy.clone(); + int numSetBits = 0; + + for (int i = 0; i < 20; i++) + numSetBits += measureNumberOfSetBits(this.entropy[i]); + + Log.d(TAG, "Entropy distribution=" + (int)(100.0 * numSetBits / 160.0) + "%"); + Log.d(TAG, "entropy gathered; attemping to generate key..."); + startKeyGen(); + } + + private void startKeyGen() { + progress = new ProgressDialog(GeneratePubkeyActivity.this); + progress.setMessage(GeneratePubkeyActivity.this.getResources().getText(R.string.pubkey_generating)); + progress.setIndeterminate(true); + progress.setCancelable(false); + progress.show(); + Thread keyGenThread = new Thread(mKeyGen); + keyGenThread.setName("KeyGen"); + keyGenThread.start(); + } + + final private Runnable mKeyGen = new Runnable() { + public void run() { + try { + boolean encrypted = false; + int tmpbits = bits; + + if (keyType == PubkeyDatabase.KEY_TYPE_DSA) + tmpbits = DSA_BITS; + + SecureRandomFix random = new SecureRandomFix(); + // Work around JVM bug + random.nextInt(); + random.setSeed(entropy); + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(keyType); + keyPairGen.initialize(tmpbits, random); + KeyPair pair = keyPairGen.generateKeyPair(); + PrivateKey priv = pair.getPrivate(); + PublicKey pub = pair.getPublic(); + String secret = password1.getText().toString(); + + if (secret.length() > 0) + encrypted = true; + + Log.d(TAG, "private: " + PubkeyUtils.formatKey(priv)); + Log.d(TAG, "public: " + PubkeyUtils.formatKey(pub)); + PubkeyBean pubkey = new PubkeyBean(); + pubkey.setNickname(nickname.getText().toString()); + pubkey.setType(keyType); + pubkey.setPrivateKey(PubkeyUtils.getEncodedPrivate(priv, secret)); + pubkey.setPublicKey(pub.getEncoded()); + pubkey.setEncrypted(encrypted); + pubkey.setStartup(unlockAtStartup.isChecked()); + pubkey.setConfirmUse(confirmUse.isChecked()); + PubkeyDatabase pubkeydb = new PubkeyDatabase(GeneratePubkeyActivity.this); + pubkeydb.savePubkey(pubkey); + pubkeydb.close(); + } + catch (Exception e) { + Log.e(TAG, "Could not generate key pair"); + e.printStackTrace(); + } + + GeneratePubkeyActivity.this.runOnUiThread(new Runnable() { + public void run() { + progress.dismiss(); + GeneratePubkeyActivity.this.finish(); + } + }); + } + }; + + final private TextWatcher textChecker = new TextWatcher() { + public void afterTextChanged(Editable s) {} + public void beforeTextChanged(CharSequence s, int start, int count, + int after) {} + public void onTextChanged(CharSequence s, int start, int before, + int count) { + checkEntries(); + } + }; + + private int measureNumberOfSetBits(byte b) { + int numSetBits = 0; + + for (int i = 0; i < 8; i++) { + if ((b & 1) == 1) + numSetBits++; + + b >>= 1; + } + + return numSetBits; + } + + private int getClosestFieldSize(int bits) { + int outBits = ECDSA_DEFAULT_BITS; + int distance = Math.abs(bits - ECDSA_DEFAULT_BITS); + + for (int i = 1; i < ECDSA_SIZES.length; i++) { + int thisDistance = Math.abs(bits - ECDSA_SIZES[i]); + + if (thisDistance < distance) { + distance = thisDistance; + outBits = ECDSA_SIZES[i]; + } + } + + return outBits; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/HelpActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,63 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import java.io.IOException; + +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +/** + * @author Kenny Root + * + */ +public class HelpActivity extends Activity { + public final static String TAG = "ConnectBot.HelpActivity"; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.act_help); + this.setTitle(String.format("%s: %s", + getResources().getText(R.string.app_name), + getResources().getText(R.string.title_help))); + LinearLayout content = (LinearLayout)this.findViewById(R.id.topics); + + String[] topics = getResources().getStringArray(R.array.list_wizard_topics); + for (final String topic : topics) { + Button button = new Button(this); + button.setText(topic); + button.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + Intent intent = new Intent(HelpActivity.this, HelpTopicActivity.class); + intent.putExtra(Intent.EXTRA_TITLE, topic); + HelpActivity.this.startActivity(intent); + } + }); + content.addView(button); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/HelpTopicActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,44 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import com.five_ten_sg.connectbot.util.HelpTopicView; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +/** + * @author Kenny Root + * + */ +public class HelpTopicActivity extends Activity { + public final static String TAG = "ConnectBot.HelpActivity"; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.act_help_topic); + String topic = getIntent().getStringExtra(Intent.EXTRA_TITLE); + this.setTitle(String.format("%s: %s - %s", + getResources().getText(R.string.app_name), + getResources().getText(R.string.title_help), + topic)); + HelpTopicView helpTopic = (HelpTopicView) findViewById(R.id.topic_text); + helpTopic.setTopic(topic); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/HostEditorActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,445 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.util.HostDatabase; +import com.five_ten_sg.connectbot.util.PubkeyDatabase; +import android.content.ComponentName; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.os.Bundle; +import android.os.IBinder; +import android.preference.CheckBoxPreference; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; +import android.util.Log; + +public class HostEditorActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener { + public class CursorPreferenceHack implements SharedPreferences { + protected final String table; + protected final long id; + + protected Map<String, String> values = new HashMap<String, String>(); + + public CursorPreferenceHack(String table, long id) { + this.table = table; + this.id = id; + cacheValues(); + } + + protected final void cacheValues() { + // fill a cursor and cache the values locally + // this makes sure we dont have any floating cursor to dispose later + SQLiteDatabase db = hostdb.getReadableDatabase(); + Cursor cursor = db.query(table, null, "_id = ?", + new String[] { String.valueOf(id) }, null, null, null); + + if (cursor.moveToFirst()) { + for (int i = 0; i < cursor.getColumnCount(); i++) { + String key = cursor.getColumnName(i); + + if (key.equals(HostDatabase.FIELD_HOST_HOSTKEY)) continue; + + String value = cursor.getString(i); + values.put(key, value); + } + } + + cursor.close(); + db.close(); + } + + public boolean contains(String key) { + return values.containsKey(key); + } + + public class Editor implements SharedPreferences.Editor { + + private ContentValues update = new ContentValues(); + + public SharedPreferences.Editor clear() { + Log.d(this.getClass().toString(), "clear()"); + update = new ContentValues(); + return this; + } + + public boolean commit() { + //Log.d(this.getClass().toString(), "commit() changes back to database"); + SQLiteDatabase db = hostdb.getWritableDatabase(); + db.update(table, update, "_id = ?", new String[] { String.valueOf(id) }); + db.close(); + // make sure we refresh the parent cached values + cacheValues(); + + // and update any listeners + for (OnSharedPreferenceChangeListener listener : listeners) { + listener.onSharedPreferenceChanged(CursorPreferenceHack.this, null); + } + + return true; + } + + // Gingerbread compatibility + public void apply() { + commit(); + } + + public android.content.SharedPreferences.Editor putBoolean(String key, boolean value) { + return this.putString(key, Boolean.toString(value)); + } + + public android.content.SharedPreferences.Editor putFloat(String key, float value) { + return this.putString(key, Float.toString(value)); + } + + public android.content.SharedPreferences.Editor putInt(String key, int value) { + return this.putString(key, Integer.toString(value)); + } + + public android.content.SharedPreferences.Editor putLong(String key, long value) { + return this.putString(key, Long.toString(value)); + } + + public android.content.SharedPreferences.Editor putString(String key, String value) { + //Log.d(this.getClass().toString(), String.format("Editor.putString(key=%s, value=%s)", key, value)); + update.put(key, value); + return this; + } + + public android.content.SharedPreferences.Editor remove(String key) { + //Log.d(this.getClass().toString(), String.format("Editor.remove(key=%s)", key)); + update.remove(key); + return this; + } + + public android.content.SharedPreferences.Editor putStringSet(String key, Set<String> value) { + throw new UnsupportedOperationException("HostEditor Prefs do not support Set<String>"); + } + } + + + public Editor edit() { + //Log.d(this.getClass().toString(), "edit()"); + return new Editor(); + } + + public Map<String, ?> getAll() { + return values; + } + + public boolean getBoolean(String key, boolean defValue) { + return Boolean.valueOf(this.getString(key, Boolean.toString(defValue))); + } + + public float getFloat(String key, float defValue) { + return Float.valueOf(this.getString(key, Float.toString(defValue))); + } + + public int getInt(String key, int defValue) { + return Integer.valueOf(this.getString(key, Integer.toString(defValue))); + } + + public long getLong(String key, long defValue) { + return Long.valueOf(this.getString(key, Long.toString(defValue))); + } + + public String getString(String key, String defValue) { + //Log.d(this.getClass().toString(), String.format("getString(key=%s, defValue=%s)", key, defValue)); + if (!values.containsKey(key)) return defValue; + + return values.get(key); + } + + public Set<String> getStringSet(String key, Set<String> defValue) { + throw new ClassCastException("HostEditor Prefs do not support Set<String>"); + } + + protected List<OnSharedPreferenceChangeListener> listeners = new LinkedList<OnSharedPreferenceChangeListener>(); + + public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { + listeners.add(listener); + } + + public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { + listeners.remove(listener); + } + + } + + @Override + public SharedPreferences getSharedPreferences(String name, int mode) { + //Log.d(this.getClass().toString(), String.format("getSharedPreferences(name=%s)", name)); + return this.pref; + } + + protected static final String TAG = "ConnectBot.HostEditorActivity"; + + protected HostDatabase hostdb = null; + private PubkeyDatabase pubkeydb = null; + + private CursorPreferenceHack pref; + private ServiceConnection connection; + private Map<String, CharSequence> summaries = new HashMap<String, CharSequence>(); + + private HostBean host; + private boolean enableSSHFeatures; + private boolean enable5250Features; + private boolean enableAsyncFeatures; + + protected TerminalBridge hostBridge; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + long hostId = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1); + // TODO: we could pass through a specific ContentProvider uri here + //this.getPreferenceManager().setSharedPreferencesName(uri); + this.hostdb = new HostDatabase(this); + this.pubkeydb = new PubkeyDatabase(this); + host = hostdb.findHostById(hostId); + enableSSHFeatures = host.isSSH(); + enable5250Features = host.is5250(); + enableAsyncFeatures = host.isAsync(); + connection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService(); + hostBridge = bound.getConnectedBridge(host); + } + public void onServiceDisconnected(ComponentName name) { + hostBridge = null; + } + }; + this.pref = new CursorPreferenceHack(HostDatabase.TABLE_HOSTS, hostId); + this.pref.registerOnSharedPreferenceChangeListener(this); + this.addPreferencesFromResource(R.xml.host_prefs); + // get all the text summaries + getSummaries(); + // disable all preferences that are not applicable to this host + findPreference(HostDatabase.FIELD_HOST_PUBKEYID).setEnabled(enableSSHFeatures); + findPreference(HostDatabase.FIELD_HOST_USEAUTHAGENT).setEnabled(enableSSHFeatures); + findPreference(HostDatabase.FIELD_HOST_POSTLOGIN).setEnabled(!enable5250Features); + findPreference(HostDatabase.FIELD_HOST_COMPRESSION).setEnabled(enableSSHFeatures); + findPreference(HostDatabase.FIELD_HOST_HTTPPROXY).setEnabled(enableAsyncFeatures); + findPreference(HostDatabase.FIELD_HOST_WANTSESSION).setEnabled(enableSSHFeatures); + findPreference(HostDatabase.FIELD_HOST_USERNAME).setEnabled(enableSSHFeatures || enable5250Features); + findPreference(HostDatabase.FIELD_HOST_EMULATION).setEnabled(!enable5250Features); + findPreference(HostDatabase.CATEGORY_5250).setEnabled(enable5250Features); + findPreference(HostDatabase.CATEGORY_X11).setEnabled(enableSSHFeatures); + // add all existing pubkeys to our listpreference for user to choose from + // TODO: may be an issue here when this activity is recycled after adding a new pubkey + // TODO: should consider moving into onStart, but we dont have a good way of resetting the listpref after filling once + ListPreference pubkeyPref = (ListPreference)findPreference(HostDatabase.FIELD_HOST_PUBKEYID); + List<CharSequence> pubkeyNicks = new LinkedList<CharSequence> (Arrays.asList(pubkeyPref.getEntries())); + pubkeyNicks.addAll(pubkeydb.allValues(PubkeyDatabase.FIELD_PUBKEY_NICKNAME)); + pubkeyPref.setEntries(pubkeyNicks.toArray(new CharSequence[pubkeyNicks.size()])); + List<CharSequence> pubkeyIds = new LinkedList<CharSequence> (Arrays.asList(pubkeyPref.getEntryValues())); + pubkeyIds.addAll(pubkeydb.allValues("_id")); + pubkeyPref.setEntryValues(pubkeyIds.toArray(new CharSequence[pubkeyIds.size()])); + // Populate the character set encoding list with all available + final ListPreference charsetPref = (ListPreference)findPreference(HostDatabase.FIELD_HOST_ENCODING); + + if (CharsetHolder.isInitialized()) { + initCharsetPref(charsetPref); + } + else { + String[] currentCharsetPref = new String[1]; + currentCharsetPref[0] = charsetPref.getValue(); + charsetPref.setEntryValues(currentCharsetPref); + charsetPref.setEntries(currentCharsetPref); + new Thread(new Runnable() { + public void run() { + initCharsetPref(charsetPref); + } + }).start(); + } + + this.updateSummaries(); + } + + @Override + public void onStart() { + super.onStart(); + bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); + + if (this.hostdb == null) + this.hostdb = new HostDatabase(this); + + if (this.pubkeydb == null) + this.pubkeydb = new PubkeyDatabase(this); + } + + @Override + public void onStop() { + super.onStop(); + unbindService(connection); + + if (this.hostdb != null) { + this.hostdb.close(); + this.hostdb = null; + } + + if (this.pubkeydb != null) { + this.pubkeydb.close(); + this.pubkeydb = null; + } + } + + private void getSummaries() { + // get all the original text summaries + for (String key : this.pref.values.keySet()) { + Preference pref = this.findPreference(key); + + if (pref == null) continue; + + if (pref instanceof CheckBoxPreference) continue; + + CharSequence value = pref.getSummary(); + summaries.put(key, value); + } + } + + private void updateSummaries() { + // for all text preferences, set hint as current database value if it is non-empty + for (String key : this.pref.values.keySet()) { + Preference pref = this.findPreference(key); + + if (pref == null) continue; + + if (pref instanceof CheckBoxPreference) continue; + + CharSequence value = this.pref.getString(key, ""); + + if (key.equals(HostDatabase.FIELD_HOST_PUBKEYID)) { + try { + int pubkeyId = Integer.parseInt(value.toString()); + + if (pubkeyId >= 0) + pref.setSummary(pubkeydb.getNickname(pubkeyId)); + else if (pubkeyId == HostDatabase.PUBKEYID_ANY) + pref.setSummary(R.string.list_pubkeyids_any); + else if (pubkeyId == HostDatabase.PUBKEYID_NEVER) + pref.setSummary(R.string.list_pubkeyids_none); + + continue; + } + catch (NumberFormatException nfe) { + // Fall through. + } + } + else if ((pref instanceof ListPreference) && (value != null)) { + ListPreference listPref = (ListPreference) pref; + int entryIndex = listPref.findIndexOfValue(value.toString()); + + if (entryIndex >= 0) value = listPref.getEntries()[entryIndex]; + } + + if ((value == null) || (value.length() == 0)) value = summaries.get(key); + + pref.setSummary(value); + } + } + + private void initCharsetPref(final ListPreference charsetPref) { + charsetPref.setEntryValues(CharsetHolder.getCharsetIds()); + charsetPref.setEntries(CharsetHolder.getCharsetNames()); + } + + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + // update values on changed preference + this.updateSummaries(); + + // Our CursorPreferenceHack always send null keys, so try to set charset anyway + if (hostBridge != null) + hostBridge.setCharset(sharedPreferences + .getString(HostDatabase.FIELD_HOST_ENCODING, HostDatabase.ENCODING_DEFAULT)); + } + + public static class CharsetHolder { + private static boolean initialized = false; + + private static CharSequence[] charsetIds; + private static CharSequence[] charsetNames; + + public static CharSequence[] getCharsetNames() { + if (charsetNames == null) + initialize(); + + return charsetNames; + } + + public static CharSequence[] getCharsetIds() { + if (charsetIds == null) + initialize(); + + return charsetIds; + } + + private synchronized static void initialize() { + if (initialized) + return; + + List<CharSequence> charsetIdsList = new LinkedList<CharSequence>(); + List<CharSequence> charsetNamesList = new LinkedList<CharSequence>(); + + for (Entry<String, Charset> entry : Charset.availableCharsets().entrySet()) { + Charset c = entry.getValue(); + + if (c.canEncode() && c.isRegistered()) { + String key = entry.getKey(); + + if (key.startsWith("cp")) { + // Custom CP437 charset changes + charsetIdsList.add("CP437"); + charsetNamesList.add("CP437"); + } + + charsetIdsList.add(entry.getKey()); + charsetNamesList.add(c.displayName()); + } + } + + charsetIds = charsetIdsList.toArray(new CharSequence[charsetIdsList.size()]); + charsetNames = charsetNamesList.toArray(new CharSequence[charsetNamesList.size()]); + initialized = true; + } + + public static boolean isInitialized() { + return initialized; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/HostListActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,665 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + + +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.transport.TransportFactory; +import com.five_ten_sg.connectbot.util.HostDatabase; +import com.five_ten_sg.connectbot.util.PreferenceConstants; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.File; +import java.util.HashMap; +import java.util.List; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ListActivity; +import android.content.ComponentName; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.Intent.ShortcutIconResource; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.content.res.ColorStateList; +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.ContextMenu; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.View; +import android.view.View.OnKeyListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.Spinner; +import android.widget.TextView; + +public class HostListActivity extends ListActivity { + protected static final String TAG = "ConnectBot.HostListActivity"; + public final static int REQUEST_EDIT = 1; + public final static int REQUEST_EULA = 2; + + protected TerminalManager bound = null; + + protected HostDatabase hostdb; + private List<HostBean> hosts; + protected LayoutInflater inflater = null; + + protected boolean sortedByColor = false; + + private MenuItem sortcolor; + + private MenuItem sortlast; + + private Spinner transportSpinner; + private TextView quickconnect; + + private SharedPreferences prefs = null; + + protected boolean makingShortcut = false; + + protected Handler updateHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + HostListActivity.this.updateList(); + } + }; + + private ServiceConnection connection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + bound = ((TerminalManager.TerminalBinder) service).getService(); + // update our listview binder to find the service + updateList(); + } + public void onServiceDisconnected(ComponentName className) { + bound = null; + updateList(); + } + }; + + @Override + public void onStart() { + super.onStart(); + // start the terminal manager service + this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); + + if (this.hostdb == null) + this.hostdb = new HostDatabase(this); + } + + @Override + public void onStop() { + super.onStop(); + this.unbindService(connection); + + if (this.hostdb != null) { + this.hostdb.close(); + this.hostdb = null; + } + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_EULA) { + if (resultCode == Activity.RESULT_OK) { + // yay they agreed, so store that info + Editor editor = prefs.edit(); + editor.putBoolean(PreferenceConstants.EULA, true); + editor.commit(); + } + else { + // user didnt agree, so close + this.finish(); + } + } + else if (requestCode == REQUEST_EDIT) { + updateList(); + } + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.act_hostlist); + this.setTitle(String.format("%s: %s", + getResources().getText(R.string.app_name), + getResources().getText(R.string.title_hosts_list))); + this.prefs = PreferenceManager.getDefaultSharedPreferences(this); + + // detect HTC Dream and apply special preferences + if (Build.MANUFACTURER.equals("HTC") && Build.DEVICE.equals("dream")) { + if (!prefs.contains(PreferenceConstants.SHIFT_FKEYS) && + !prefs.contains(PreferenceConstants.CTRL_FKEYS)) { + Editor editor = prefs.edit(); + editor.putBoolean(PreferenceConstants.SHIFT_FKEYS, true); + editor.putBoolean(PreferenceConstants.CTRL_FKEYS, true); + editor.commit(); + } + } + + makingShortcut = Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction()) + || Intent.ACTION_PICK.equals(getIntent().getAction()); + + // connect with hosts database, read deployment file, and populate list + hostdb = new HostDatabase(this); + createDeploymentHosts(); // build hosts from a deployment text file + updateList(); + + // check for eula agreement, which might be set from the deployment file + boolean agreed = prefs.getBoolean(PreferenceConstants.EULA, false); + if (!agreed) { + startActivityForResult(new Intent(this, WizardActivity.class), REQUEST_EULA); + } + + // show the list + sortedByColor = prefs.getBoolean(PreferenceConstants.SORT_BY_COLOR, false); + registerForContextMenu(getListView()); + getListView().setOnItemClickListener(new OnItemClickListener() { + + public synchronized void onItemClick(AdapterView<?> parent, View view, int position, long id) { + // launch off to console details + HostBean host = (HostBean) getListView().getItemAtPosition(position); + Uri uri = host.getUri(); + Intent contents = new Intent(Intent.ACTION_VIEW, uri); + contents.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + + if (makingShortcut) { + // create shortcut if requested + ShortcutIconResource icon = Intent.ShortcutIconResource.fromContext(HostListActivity.this, R.drawable.icon); + Intent intent = new Intent(); + intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, contents); + intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, host.getNickname()); + intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon); + setResult(RESULT_OK, intent); + finish(); + } + else { + // otherwise just launch activity to show this host + startActivity(contents); + } + } + }); + quickconnect = (TextView) this.findViewById(R.id.front_quickconnect); + quickconnect.setVisibility(makingShortcut ? View.GONE : View.VISIBLE); + quickconnect.setOnKeyListener(new OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_UP) return false; + + if (keyCode != KeyEvent.KEYCODE_ENTER) return false; + + return startConsoleActivity(); + } + }); + transportSpinner = (Spinner)findViewById(R.id.transport_selection); + transportSpinner.setVisibility(makingShortcut ? View.GONE : View.VISIBLE); + ArrayAdapter<String> transportSelection = new ArrayAdapter<String> (this, + android.R.layout.simple_spinner_item, TransportFactory.getTransportNames()); + transportSelection.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + transportSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView<?> arg0, View view, int position, long id) { + String formatHint = TransportFactory.getFormatHint( + (String) transportSpinner.getSelectedItem(), + HostListActivity.this); + quickconnect.setHint(formatHint); + quickconnect.setError(null); + quickconnect.requestFocus(); + } + public void onNothingSelected(AdapterView<?> arg0) { } + }); + transportSpinner.setAdapter(transportSelection); + this.inflater = LayoutInflater.from(this); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + + // don't offer menus when creating shortcut + if (makingShortcut) return true; + + sortcolor.setVisible(!sortedByColor); + sortlast.setVisible(sortedByColor); + return true; + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + + // don't offer menus when creating shortcut + if (makingShortcut) return true; + + // add host, ssh keys, about + sortcolor = menu.add(R.string.list_menu_sortcolor); + sortcolor.setIcon(android.R.drawable.ic_menu_share); + sortcolor.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + sortedByColor = true; + updateList(); + return true; + } + }); + sortlast = menu.add(R.string.list_menu_sortname); + sortlast.setIcon(android.R.drawable.ic_menu_share); + sortlast.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + sortedByColor = false; + updateList(); + return true; + } + }); + MenuItem keys = menu.add(R.string.list_menu_pubkeys); + keys.setIcon(android.R.drawable.ic_lock_lock); + keys.setIntent(new Intent(HostListActivity.this, PubkeyListActivity.class)); + MenuItem colors = menu.add(R.string.title_colors); + colors.setIcon(android.R.drawable.ic_menu_slideshow); + colors.setIntent(new Intent(HostListActivity.this, ColorsActivity.class)); + MenuItem settings = menu.add(R.string.list_menu_settings); + settings.setIcon(android.R.drawable.ic_menu_preferences); + settings.setIntent(new Intent(HostListActivity.this, SettingsActivity.class)); + MenuItem help = menu.add(R.string.title_help); + help.setIcon(android.R.drawable.ic_menu_help); + help.setIntent(new Intent(HostListActivity.this, HelpActivity.class)); + return true; + } + + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + // create menu to handle hosts + // create menu to handle deleting and sharing lists + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; + final HostBean host = (HostBean) this.getListView().getItemAtPosition(info.position); + menu.setHeaderTitle(host.getNickname()); + // edit, disconnect, delete + MenuItem connect = menu.add(R.string.list_host_disconnect); + final TerminalBridge bridge = bound.getConnectedBridge(host); + connect.setEnabled((bridge != null)); + connect.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + bridge.dispatchDisconnect(true); + updateHandler.sendEmptyMessage(-1); + return true; + } + }); + MenuItem edit = menu.add(R.string.list_host_edit); + edit.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + Intent intent = new Intent(HostListActivity.this, HostEditorActivity.class); + intent.putExtra(Intent.EXTRA_TITLE, host.getId()); + HostListActivity.this.startActivityForResult(intent, REQUEST_EDIT); + return true; + } + }); + MenuItem portForwards = menu.add(R.string.list_host_portforwards); + portForwards.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + Intent intent = new Intent(HostListActivity.this, PortForwardListActivity.class); + intent.putExtra(Intent.EXTRA_TITLE, host.getId()); + HostListActivity.this.startActivityForResult(intent, REQUEST_EDIT); + return true; + } + }); + + if (!TransportFactory.canForwardPorts(host.getProtocol())) + portForwards.setEnabled(false); + + MenuItem delete = menu.add(R.string.list_host_delete); + delete.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // prompt user to make sure they really want this + new AlertDialog.Builder(HostListActivity.this) + .setMessage(getString(R.string.delete_message, host.getNickname())) + .setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // make sure we disconnect + if (bridge != null) + bridge.dispatchDisconnect(true); + + hostdb.deleteHost(host); + updateHandler.sendEmptyMessage(-1); + } + }) + .setNegativeButton(R.string.delete_neg, null).create().show(); + return true; + } + }); + } + + /** + * @param text + * @return + */ + private boolean startConsoleActivity() { + Uri uri = TransportFactory.getUri((String) transportSpinner + .getSelectedItem(), quickconnect.getText().toString()); + + if (uri == null) { + quickconnect.setError(getString(R.string.list_format_error, + TransportFactory.getFormatHint( + (String) transportSpinner.getSelectedItem(), + HostListActivity.this))); + return false; + } + + HostBean host = TransportFactory.findHost(hostdb, uri); + + if (host == null) { + host = TransportFactory.getTransport(uri.getScheme()).createHost(uri); + host.setColor(HostDatabase.COLOR_GRAY); + host.setPubkeyId(HostDatabase.PUBKEYID_ANY); + hostdb.saveHost(host); + } + + Intent intent = new Intent(HostListActivity.this, ConsoleActivity.class); + intent.setData(uri); + startActivity(intent); + return true; + } + + private void createDeploymentHosts() { + try { + String fn = Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "deployment.connections"; + BufferedReader reader = new BufferedReader(new FileReader(fn)); + String line = null; + + while ((line = reader.readLine()) != null) { + if (line.length() == 0) continue; // empty + + if (line.substring(0, 1).equals("#")) continue; // comment + + if (!line.contains("://")) continue; // invalid uri + + Uri uri = Uri.parse(line); + ContentValues values = null; + + while ((line = reader.readLine()).length() > 0) { + String [] parts = line.split("="); + + if (parts.length != 2) continue; + + if (values == null) values = new ContentValues(); + + values.put(parts[0].trim(), parts[1].trim()); + } + + if (uri.getScheme().equals("global")) { + Editor editor = prefs.edit(); + HashMap<String, String> types = new HashMap<String, String>(); + types.put("memkeys", "boolean"); + types.put("connPersist", "boolean"); + types.put("emulation", "string"); + types.put("scrollback", "string"); + types.put("rotation", "string"); + types.put("shiftfkeys", "boolean"); + types.put("ctrlfkeys", "boolean"); + types.put("keymode", "string"); + types.put("camera", "string"); + types.put("volup", "string"); + types.put("voldn", "string"); + types.put("search", "string"); + types.put("ptt", "string"); + types.put("keepalive", "boolean"); + types.put("wifilock", "boolean"); + types.put("bumpyarrows", "boolean"); + types.put("eula", "boolean"); + types.put("extended_longpress", "boolean"); + types.put("ctrl_string", "string"); + types.put("picker_string", "string"); + types.put("picker_keep_open", "boolean"); + types.put("list_custom_keymap", "string"); + types.put("bell", "boolean"); + types.put("bellVolume", "float"); + types.put("bellVibrate", "boolean"); + types.put("bellNotification", "boolean"); + types.put("screen_capture_folder", "string"); + types.put("screen_capture_popup", "boolean"); + types.put("file_dialog", "string"); + types.put("download_folder", "string"); + types.put("remote_upload_folder", "string"); + types.put("upload_dest_prompt", "boolean"); + types.put("background_file_transfer", "boolean"); + types.put("debug_keycodes", "boolean"); + + for (String key : values.keySet()) { + if (types.containsKey(key)) { + String t = types.get(key); + String sv = values.getAsString(key); + if (t.equals("float")) { + editor.putFloat(key, Float.parseFloat(sv)); + } + else if (t.equals("boolean")) { + editor.putBoolean(key, Boolean.parseBoolean(sv)); + } + else if (t.equals("string")) { + editor.putString(key, sv); + } + } + } + + editor.commit(); + } + else { + HostBean host = TransportFactory.findHost(hostdb, uri); + + if (host == null) { + host = TransportFactory.getTransport(uri.getScheme()).createHost(uri); + host.setColor(HostDatabase.COLOR_GRAY); + host.setPubkeyId(HostDatabase.PUBKEYID_ANY); + hostdb.saveHost(host); + } + + host = TransportFactory.findHost(hostdb, uri); + + if (host == null) continue; + + if (values == null) continue; + + SQLiteDatabase db = hostdb.getWritableDatabase(); + db.update(HostDatabase.TABLE_HOSTS, values, "_id = ?", new String[] { String.valueOf(host.getId()) }); + db.close(); + } + } + + reader.close(); + (new File(fn)).delete(); + } + catch (Exception e) { + Log.d(TAG, "Deployment scan failed.", e); + } + } + + protected void updateList() { + if (prefs.getBoolean(PreferenceConstants.SORT_BY_COLOR, false) != sortedByColor) { + Editor editor = prefs.edit(); + editor.putBoolean(PreferenceConstants.SORT_BY_COLOR, sortedByColor); + editor.commit(); + } + + if (hostdb == null) + hostdb = new HostDatabase(this); + + hosts = hostdb.getHosts(sortedByColor); + + // Don't lose hosts that are connected via shortcuts but not in the database. + if (bound != null) { + for (TerminalBridge bridge : bound.bridges) { + if (!hosts.contains(bridge.host)) + hosts.add(0, bridge.host); + } + } + + HostAdapter adapter = new HostAdapter(this, hosts, bound); + this.setListAdapter(adapter); + } + + class HostAdapter extends ArrayAdapter<HostBean> { + private List<HostBean> hosts; + private final TerminalManager manager; + private final ColorStateList red, green, blue; + + public final static int STATE_UNKNOWN = 1, STATE_CONNECTED = 2, STATE_DISCONNECTED = 3; + + class ViewHolder { + public TextView nickname; + public TextView caption; + public ImageView icon; + } + + public HostAdapter(Context context, List<HostBean> hosts, TerminalManager manager) { + super(context, R.layout.item_host, hosts); + this.hosts = hosts; + this.manager = manager; + red = context.getResources().getColorStateList(R.color.red); + green = context.getResources().getColorStateList(R.color.green); + blue = context.getResources().getColorStateList(R.color.blue); + } + + /** + * Check if we're connected to a terminal with the given host. + */ + private int getConnectedState(HostBean host) { + // always disconnected if we dont have backend service + if (this.manager == null) + return STATE_UNKNOWN; + + if (manager.getConnectedBridge(host) != null) + return STATE_CONNECTED; + + if (manager.disconnected.contains(host)) + return STATE_DISCONNECTED; + + return STATE_UNKNOWN; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + + if (convertView == null) { + convertView = inflater.inflate(R.layout.item_host, null, false); + holder = new ViewHolder(); + holder.nickname = (TextView)convertView.findViewById(android.R.id.text1); + holder.caption = (TextView)convertView.findViewById(android.R.id.text2); + holder.icon = (ImageView)convertView.findViewById(android.R.id.icon); + convertView.setTag(holder); + } + else + holder = (ViewHolder) convertView.getTag(); + + HostBean host = hosts.get(position); + + if (host == null) { + // Well, something bad happened. We can't continue. + Log.e("HostAdapter", "Host bean is null!"); + holder.nickname.setText("Error during lookup"); + holder.caption.setText("see 'adb logcat' for more"); + return convertView; + } + + holder.nickname.setText(host.getNickname()); + + switch (this.getConnectedState(host)) { + case STATE_UNKNOWN: + holder.icon.setImageState(new int[] { }, true); + break; + + case STATE_CONNECTED: + holder.icon.setImageState(new int[] { android.R.attr.state_checked }, true); + break; + + case STATE_DISCONNECTED: + holder.icon.setImageState(new int[] { android.R.attr.state_expanded }, true); + break; + } + + ColorStateList chosen = null; + + if (HostDatabase.COLOR_RED.equals(host.getColor())) + chosen = this.red; + else if (HostDatabase.COLOR_GREEN.equals(host.getColor())) + chosen = this.green; + else if (HostDatabase.COLOR_BLUE.equals(host.getColor())) + chosen = this.blue; + + Context context = convertView.getContext(); + + if (chosen != null) { + // set color normally if not selected + holder.nickname.setTextColor(chosen); + holder.caption.setTextColor(chosen); + } + else { + // selected, so revert back to default black text + holder.nickname.setTextAppearance(context, android.R.attr.textAppearanceLarge); + holder.caption.setTextAppearance(context, android.R.attr.textAppearanceSmall); + } + + long now = System.currentTimeMillis() / 1000; + String nice = context.getString(R.string.bind_never); + + if (host.getLastConnect() > 0) { + int minutes = (int)((now - host.getLastConnect()) / 60); + + if (minutes >= 60) { + int hours = (minutes / 60); + + if (hours >= 24) { + int days = (hours / 24); + nice = context.getString(R.string.bind_days, days); + } + else + nice = context.getString(R.string.bind_hours, hours); + } + else + nice = context.getString(R.string.bind_minutes, minutes); + } + + holder.caption.setText(nice); + return convertView; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/PortForwardListActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,406 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import java.util.List; + +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.bean.PortForwardBean; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.util.HostDatabase; +import android.app.AlertDialog; +import android.app.ListActivity; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.res.Resources; +import android.database.SQLException; +import android.graphics.Paint; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.util.Log; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +/** + * List all portForwards for a particular host and provide a way for users to add more portForwards, + * edit existing portForwards, and delete portForwards. + * + * @author Kenny Root + */ +public class PortForwardListActivity extends ListActivity { + public final static String TAG = "ConnectBot.PortForwardListActivity"; + + private static final int LISTENER_CYCLE_TIME = 500; + + protected HostDatabase hostdb; + + private List<PortForwardBean> portForwards; + + private ServiceConnection connection = null; + protected TerminalBridge hostBridge = null; + protected LayoutInflater inflater = null; + + private HostBean host; + + @Override + public void onStart() { + super.onStart(); + this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); + + if (this.hostdb == null) + this.hostdb = new HostDatabase(this); + } + + @Override + public void onStop() { + super.onStop(); + this.unbindService(connection); + + if (this.hostdb != null) { + this.hostdb.close(); + this.hostdb = null; + } + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + long hostId = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1); + setContentView(R.layout.act_portforwardlist); + // connect with hosts database and populate list + this.hostdb = new HostDatabase(this); + host = hostdb.findHostById(hostId); + { + final String nickname = host != null ? host.getNickname() : null; + final Resources resources = getResources(); + + if (nickname != null) { + this.setTitle(String.format("%s: %s (%s)", + resources.getText(R.string.app_name), + resources.getText(R.string.title_port_forwards_list), + nickname)); + } + else { + this.setTitle(String.format("%s: %s", + resources.getText(R.string.app_name), + resources.getText(R.string.title_port_forwards_list))); + } + } + connection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService(); + hostBridge = bound.getConnectedBridge(host); + updateHandler.sendEmptyMessage(-1); + } + public void onServiceDisconnected(ComponentName name) { + hostBridge = null; + } + }; + this.updateList(); + this.registerForContextMenu(this.getListView()); + this.getListView().setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { + ListView lv = PortForwardListActivity.this.getListView(); + PortForwardBean pfb = (PortForwardBean) lv.getItemAtPosition(position); + + if (hostBridge != null) { + if (pfb.isEnabled()) + hostBridge.disablePortForward(pfb); + else { + if (!hostBridge.enablePortForward(pfb)) + Toast.makeText(PortForwardListActivity.this, getString(R.string.portforward_problem), Toast.LENGTH_LONG).show(); + } + + updateHandler.sendEmptyMessage(-1); + } + } + }); + this.inflater = LayoutInflater.from(this); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuItem add = menu.add(R.string.portforward_menu_add); + add.setIcon(android.R.drawable.ic_menu_add); + add.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // build dialog to prompt user about updating + final View portForwardView = inflater.inflate(R.layout.dia_portforward, null, false); + final EditText destEdit = (EditText) portForwardView.findViewById(R.id.portforward_destination); + final Spinner typeSpinner = (Spinner)portForwardView.findViewById(R.id.portforward_type); + typeSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { + public void onItemSelected(AdapterView<?> value, View view, + int position, long id) { + destEdit.setEnabled(position != 2); + } + public void onNothingSelected(AdapterView<?> arg0) { + } + }); + new AlertDialog.Builder(PortForwardListActivity.this) + .setView(portForwardView) + .setPositiveButton(R.string.portforward_pos, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + try { + final EditText nicknameEdit = (EditText) portForwardView.findViewById(R.id.nickname); + final EditText sourcePortEdit = (EditText) portForwardView.findViewById(R.id.portforward_source); + String type = HostDatabase.PORTFORWARD_LOCAL; + + switch (typeSpinner.getSelectedItemPosition()) { + case 0: + type = HostDatabase.PORTFORWARD_LOCAL; + break; + + case 1: + type = HostDatabase.PORTFORWARD_REMOTE; + break; + + case 2: + type = HostDatabase.PORTFORWARD_DYNAMIC5; + break; + } + + PortForwardBean pfb = new PortForwardBean( + host != null ? host.getId() : -1, + nicknameEdit.getText().toString(), type, + sourcePortEdit.getText().toString(), + destEdit.getText().toString()); + + if (hostBridge != null) { + hostBridge.addPortForward(pfb); + hostBridge.enablePortForward(pfb); + } + + if (host != null && !hostdb.savePortForward(pfb)) + throw new SQLException("Could not save port forward"); + + updateHandler.sendEmptyMessage(-1); + } + catch (Exception e) { + Log.e(TAG, "Could not update port forward", e); + // TODO Show failure dialog. + } + } + }) + .setNegativeButton(R.string.delete_neg, null).create().show(); + return true; + } + }); + return true; + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + // Create menu to handle deleting and editing port forward + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; + final PortForwardBean pfb = (PortForwardBean) this.getListView().getItemAtPosition(info.position); + menu.setHeaderTitle(pfb.getNickname()); + MenuItem edit = menu.add(R.string.portforward_edit); + edit.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + final View editTunnelView = inflater.inflate(R.layout.dia_portforward, null, false); + final Spinner typeSpinner = (Spinner) editTunnelView.findViewById(R.id.portforward_type); + + if (HostDatabase.PORTFORWARD_LOCAL.equals(pfb.getType())) + typeSpinner.setSelection(0); + else if (HostDatabase.PORTFORWARD_REMOTE.equals(pfb.getType())) + typeSpinner.setSelection(1); + else + typeSpinner.setSelection(2); + + final EditText nicknameEdit = (EditText) editTunnelView.findViewById(R.id.nickname); + nicknameEdit.setText(pfb.getNickname()); + final EditText sourcePortEdit = (EditText) editTunnelView.findViewById(R.id.portforward_source); + sourcePortEdit.setText(String.valueOf(pfb.getSourcePort())); + final EditText destEdit = (EditText) editTunnelView.findViewById(R.id.portforward_destination); + + if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(pfb.getType())) { + destEdit.setEnabled(false); + } + else { + destEdit.setText(String.format("%s:%d", pfb.getDestAddr(), pfb.getDestPort())); + } + + typeSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { + public void onItemSelected(AdapterView<?> value, View view, + int position, long id) { + destEdit.setEnabled(position != 2); + } + public void onNothingSelected(AdapterView<?> arg0) { + } + }); + new AlertDialog.Builder(PortForwardListActivity.this) + .setView(editTunnelView) + .setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + try { + if (hostBridge != null) + hostBridge.disablePortForward(pfb); + + pfb.setNickname(nicknameEdit.getText().toString()); + + switch (typeSpinner.getSelectedItemPosition()) { + case 0: + pfb.setType(HostDatabase.PORTFORWARD_LOCAL); + break; + + case 1: + pfb.setType(HostDatabase.PORTFORWARD_REMOTE); + break; + + case 2: + pfb.setType(HostDatabase.PORTFORWARD_DYNAMIC5); + break; + } + + pfb.setSourcePort(Integer.parseInt(sourcePortEdit.getText().toString())); + pfb.setDest(destEdit.getText().toString()); + + // Use the new settings for the existing connection. + if (hostBridge != null) + updateHandler.postDelayed(new Runnable() { + public void run() { + hostBridge.enablePortForward(pfb); + updateHandler.sendEmptyMessage(-1); + } + }, LISTENER_CYCLE_TIME); + + if (!hostdb.savePortForward(pfb)) + throw new SQLException("Could not save port forward"); + + updateHandler.sendEmptyMessage(-1); + } + catch (Exception e) { + Log.e(TAG, "Could not update port forward", e); + // TODO Show failure dialog. + } + } + }) + .setNegativeButton(android.R.string.cancel, null).create().show(); + return true; + } + }); + MenuItem delete = menu.add(R.string.portforward_delete); + delete.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // prompt user to make sure they really want this + new AlertDialog.Builder(PortForwardListActivity.this) + .setMessage(getString(R.string.delete_message, pfb.getNickname())) + .setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + try { + // Delete the port forward from the host if needed. + if (hostBridge != null) + hostBridge.removePortForward(pfb); + + hostdb.deletePortForward(pfb); + } + catch (Exception e) { + Log.e(TAG, "Could not delete port forward", e); + } + + updateHandler.sendEmptyMessage(-1); + } + }) + .setNegativeButton(R.string.delete_neg, null).create().show(); + return true; + } + }); + } + + protected Handler updateHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + PortForwardListActivity.this.updateList(); + } + }; + + protected void updateList() { + if (hostBridge != null) { + this.portForwards = hostBridge.getPortForwards(); + } + else { + if (this.hostdb == null) return; + + this.portForwards = this.hostdb.getPortForwardsForHost(host); + } + + PortForwardAdapter adapter = new PortForwardAdapter(this, portForwards); + this.setListAdapter(adapter); + } + + class PortForwardAdapter extends ArrayAdapter<PortForwardBean> { + class ViewHolder { + public TextView nickname; + public TextView caption; + } + + private List<PortForwardBean> portForwards; + + public PortForwardAdapter(Context context, List<PortForwardBean> portForwards) { + super(context, R.layout.item_portforward, portForwards); + this.portForwards = portForwards; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + + if (convertView == null) { + convertView = inflater.inflate(R.layout.item_portforward, null, false); + holder = new ViewHolder(); + holder.nickname = (TextView)convertView.findViewById(android.R.id.text1); + holder.caption = (TextView)convertView.findViewById(android.R.id.text2); + convertView.setTag(holder); + } + else + holder = (ViewHolder) convertView.getTag(); + + PortForwardBean pfb = portForwards.get(position); + holder.nickname.setText(pfb.getNickname()); + holder.caption.setText(pfb.getDescription()); + + if (hostBridge != null && !pfb.isEnabled()) { + holder.nickname.setPaintFlags(holder.nickname.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + holder.caption.setPaintFlags(holder.caption.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + } + + return convertView; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/PubkeyListActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,674 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.EventListener; +import java.util.List; + +import com.five_ten_sg.connectbot.bean.PubkeyBean; +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.util.FileChooser; +import com.five_ten_sg.connectbot.util.FileChooserCallback; +import com.five_ten_sg.connectbot.util.PubkeyDatabase; +import com.five_ten_sg.connectbot.util.PubkeyUtils; +import android.app.AlertDialog; +import android.app.ListActivity; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.Environment; +import android.os.IBinder; +import android.text.ClipboardManager; +import android.util.Log; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TableRow; +import android.widget.TextView; +import android.widget.Toast; + +import ch.ethz.ssh2.crypto.Base64; +import ch.ethz.ssh2.crypto.PEMDecoder; +import ch.ethz.ssh2.crypto.PEMStructure; + +/** + * List public keys in database by nickname and describe their properties. Allow users to import, + * generate, rename, and delete key pairs. + * + * @author Kenny Root + */ +public class PubkeyListActivity extends ListActivity implements EventListener, FileChooserCallback { + + public final static String TAG = "ConnectBot.PubkeyListActivity"; + + private static final int MAX_KEYFILE_SIZE = 8192; + private static final int KEYTYPE_PUBLIC = 0; + private static final int KEYTYPE_PRIVATE = 1; + + protected PubkeyDatabase pubkeydb; + private List<PubkeyBean> pubkeys; + + protected ClipboardManager clipboard; + + protected LayoutInflater inflater = null; + + protected TerminalManager bound = null; + + private MenuItem onstartToggle = null; + private MenuItem confirmUse = null; + + private ServiceConnection connection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + bound = ((TerminalManager.TerminalBinder) service).getService(); + // update our listview binder to find the service + updateList(); + } + public void onServiceDisconnected(ComponentName className) { + bound = null; + updateList(); + } + }; + + @Override + public void onStart() { + super.onStart(); + bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); + + if (pubkeydb == null) + pubkeydb = new PubkeyDatabase(this); + } + + @Override + public void onStop() { + super.onStop(); + unbindService(connection); + + if (pubkeydb != null) { + pubkeydb.close(); + pubkeydb = null; + } + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.act_pubkeylist); + this.setTitle(String.format("%s: %s", + getResources().getText(R.string.app_name), + getResources().getText(R.string.title_pubkey_list))); + // connect with hosts database and populate list + pubkeydb = new PubkeyDatabase(this); + updateList(); + registerForContextMenu(getListView()); + getListView().setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { + PubkeyBean pubkey = (PubkeyBean) getListView().getItemAtPosition(position); + boolean loaded = bound.isKeyLoaded(pubkey.getNickname()); + + // handle toggling key in-memory on/off + if (loaded) { + bound.removeKey(pubkey.getNickname()); + updateList(); + } + else { + handleAddKey(pubkey); + } + } + }); + clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE); + inflater = LayoutInflater.from(this); + } + + /** + * Read given file into memory as <code>byte[]</code>. + */ + protected static byte[] readRaw(File file) throws Exception { + InputStream is = new FileInputStream(file); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + int bytesRead; + byte[] buffer = new byte[1024]; + + while ((bytesRead = is.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + + os.flush(); + os.close(); + is.close(); + return os.toByteArray(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuItem generatekey = menu.add(R.string.pubkey_generate); + generatekey.setIcon(android.R.drawable.ic_menu_manage); + generatekey.setIntent(new Intent(PubkeyListActivity.this, GeneratePubkeyActivity.class)); + MenuItem importkey = menu.add(R.string.pubkey_import); + importkey.setIcon(android.R.drawable.ic_menu_upload); + importkey.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + FileChooser.selectFile(PubkeyListActivity.this, PubkeyListActivity.this, + FileChooser.REQUEST_CODE_SELECT_FILE, + getString(R.string.file_chooser_select_file, getString(R.string.select_for_key_import))); + return true; + } + }); + return true; + } + + protected void handleAddKey(final PubkeyBean pubkey) { + if (pubkey.isEncrypted()) { + final View view = inflater.inflate(R.layout.dia_password, null); + final EditText passwordField = (EditText)view.findViewById(android.R.id.text1); + new AlertDialog.Builder(PubkeyListActivity.this) + .setView(view) + .setPositiveButton(R.string.pubkey_unlock, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + handleAddKey(pubkey, passwordField.getText().toString()); + } + }) + .setNegativeButton(android.R.string.cancel, null).create().show(); + } + else { + handleAddKey(pubkey, null); + } + } + + protected void handleAddKey(PubkeyBean keybean, String password) { + KeyPair pair = null; + + if (PubkeyDatabase.KEY_TYPE_IMPORTED.equals(keybean.getType())) { + // load specific key using pem format + try { + pair = PEMDecoder.decode(new String(keybean.getPrivateKey()).toCharArray(), password); + } + catch (Exception e) { + String message = getResources().getString(R.string.pubkey_failed_add, keybean.getNickname()); + Log.e(TAG, message, e); + Toast.makeText(PubkeyListActivity.this, message, Toast.LENGTH_LONG).show(); + } + } + else { + // load using internal generated format + try { + PrivateKey privKey = PubkeyUtils.decodePrivate(keybean.getPrivateKey(), keybean.getType(), password); + PublicKey pubKey = PubkeyUtils.decodePublic(keybean.getPublicKey(), keybean.getType()); + Log.d(TAG, "Unlocked key " + PubkeyUtils.formatKey(pubKey)); + pair = new KeyPair(pubKey, privKey); + } + catch (Exception e) { + String message = getResources().getString(R.string.pubkey_failed_add, keybean.getNickname()); + Log.e(TAG, message, e); + Toast.makeText(PubkeyListActivity.this, message, Toast.LENGTH_LONG).show(); + return; + } + } + + if (pair == null) return; + + Log.d(TAG, String.format("Unlocked key '%s'", keybean.getNickname())); + // save this key in memory + bound.addKey(keybean, pair, true); + updateList(); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + // Create menu to handle deleting and editing pubkey + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; + final PubkeyBean pubkey = (PubkeyBean) getListView().getItemAtPosition(info.position); + menu.setHeaderTitle(pubkey.getNickname()); + // TODO: option load/unload key from in-memory list + // prompt for password as needed for passworded keys + // cant change password or clipboard imported keys + final boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType()); + final boolean loaded = bound.isKeyLoaded(pubkey.getNickname()); + MenuItem load = menu.add(loaded ? R.string.pubkey_memory_unload : R.string.pubkey_memory_load); + load.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + if (loaded) { + bound.removeKey(pubkey.getNickname()); + updateList(); + } + else { + handleAddKey(pubkey); + //bound.addKey(nickname, trileadKey); + } + + return true; + } + }); + onstartToggle = menu.add(R.string.pubkey_load_on_start); + onstartToggle.setVisible(!pubkey.isEncrypted()); + onstartToggle.setCheckable(true); + onstartToggle.setChecked(pubkey.isStartup()); + onstartToggle.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // toggle onstart status + pubkey.setStartup(!pubkey.isStartup()); + pubkeydb.savePubkey(pubkey); + updateList(); + return true; + } + }); + MenuItem changePassword = menu.add(R.string.pubkey_change_password); + changePassword.setVisible(!imported); + changePassword.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + final View changePasswordView = inflater.inflate(R.layout.dia_changepassword, null, false); + ((TableRow)changePasswordView.findViewById(R.id.old_password_prompt)) + .setVisibility(pubkey.isEncrypted() ? View.VISIBLE : View.GONE); + new AlertDialog.Builder(PubkeyListActivity.this) + .setView(changePasswordView) + .setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + String oldPassword = ((EditText)changePasswordView.findViewById(R.id.old_password)).getText().toString(); + String password1 = ((EditText)changePasswordView.findViewById(R.id.password1)).getText().toString(); + String password2 = ((EditText)changePasswordView.findViewById(R.id.password2)).getText().toString(); + + if (!password1.equals(password2)) { + new AlertDialog.Builder(PubkeyListActivity.this) + .setMessage(R.string.alert_passwords_do_not_match_msg) + .setPositiveButton(android.R.string.ok, null) + .create().show(); + return; + } + + try { + if (!pubkey.changePassword(oldPassword, password1)) + new AlertDialog.Builder(PubkeyListActivity.this) + .setMessage(R.string.alert_wrong_password_msg) + .setPositiveButton(android.R.string.ok, null) + .create().show(); + else { + pubkeydb.savePubkey(pubkey); + updateList(); + } + } + catch (Exception e) { + Log.e(TAG, "Could not change private key password", e); + new AlertDialog.Builder(PubkeyListActivity.this) + .setMessage(R.string.alert_key_corrupted_msg) + .setPositiveButton(android.R.string.ok, null) + .create().show(); + } + } + }) + .setNegativeButton(android.R.string.cancel, null).create().show(); + return true; + } + }); + confirmUse = menu.add(R.string.pubkey_confirm_use); + confirmUse.setCheckable(true); + confirmUse.setChecked(pubkey.isConfirmUse()); + confirmUse.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // toggle confirm use + pubkey.setConfirmUse(!pubkey.isConfirmUse()); + pubkeydb.savePubkey(pubkey); + updateList(); + return true; + } + }); + MenuItem copyPublicToClipboard = menu.add(R.string.pubkey_copy_public); + copyPublicToClipboard.setVisible(!imported); + copyPublicToClipboard.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + try { + PublicKey pk = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); + String openSSHPubkey = PubkeyUtils.convertToOpenSSHFormat(pk, pubkey.getNickname()); + clipboard.setText(openSSHPubkey); + } + catch (Exception e) { + e.printStackTrace(); + } + + return true; + } + }); + MenuItem exportPublic = menu.add(R.string.pubkey_export_public); + exportPublic.setVisible(!imported); + exportPublic.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + String keyString = PubkeyUtils.getPubkeyString(pubkey); + + if (keyString != null) + saveKeyToFile(keyString, pubkey.getNickname(), KEYTYPE_PUBLIC); + + return true; + } + }); + MenuItem copyPrivateToClipboard = menu.add(R.string.pubkey_copy_private); + copyPrivateToClipboard.setVisible(!pubkey.isEncrypted() || imported); + copyPrivateToClipboard.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + String keyString = PubkeyUtils.getPrivkeyString(pubkey, null); + + if (keyString != null) + clipboard.setText(keyString); + + return true; + } + }); + MenuItem exportPrivate = menu.add(R.string.pubkey_export_private); + exportPrivate.setVisible(!pubkey.isEncrypted() || imported); + exportPrivate.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + /* if (pubkey.isEncrypted()) { + final View view = inflater.inflate(R.layout.dia_password, null); + final EditText passwordField = (EditText)view.findViewById(android.R.id.text1); + + new AlertDialog.Builder(PubkeyListActivity.this) + .setView(view) + .setPositiveButton(R.string.pubkey_unlock, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + String keyString = PubkeyUtils.getPrivkeyString(pubkey, passwordField.getText().toString()); + if (keyString != null) + saveKeyToFile(keyString, pubkey.getNickname(), KEYTYPE_PRIVATE); + } + }) + .setNegativeButton(android.R.string.cancel, null).create().show(); + } else { */ + String keyString = PubkeyUtils.getPrivkeyString(pubkey, null); + + if (keyString != null) + saveKeyToFile(keyString, pubkey.getNickname(), KEYTYPE_PRIVATE); + +// } + return true; + } + }); + MenuItem delete = menu.add(R.string.pubkey_delete); + delete.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // prompt user to make sure they really want this + new AlertDialog.Builder(PubkeyListActivity.this) + .setMessage(getString(R.string.delete_message, pubkey.getNickname())) + .setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // dont forget to remove from in-memory + if (loaded) + bound.removeKey(pubkey.getNickname()); + + // delete from backend database and update gui + pubkeydb.deletePubkey(pubkey); + updateList(); + } + }) + .setNegativeButton(R.string.delete_neg, null).create().show(); + return true; + } + }); + } + + protected void updateList() { + if (pubkeydb == null) return; + + pubkeys = pubkeydb.allPubkeys(); + PubkeyAdapter adapter = new PubkeyAdapter(this, pubkeys); + this.setListAdapter(adapter); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent intent) { + super.onActivityResult(requestCode, resultCode, intent); + + switch (requestCode) { + case FileChooser.REQUEST_CODE_SELECT_FILE: + if (resultCode == RESULT_OK && intent != null) { + File file = FileChooser.getSelectedFile(intent); + + if (file != null) + readKeyFromFile(file); + } + + break; + } + } + + /** + * @param name + */ + private void readKeyFromFile(File file) { + PubkeyBean pubkey = new PubkeyBean(); + // find the exact file selected + pubkey.setNickname(file.getName()); + + if (file.length() > MAX_KEYFILE_SIZE) { + Toast.makeText(PubkeyListActivity.this, + R.string.pubkey_import_parse_problem, + Toast.LENGTH_LONG).show(); + return; + } + + // parse the actual key once to check if its encrypted + // then save original file contents into our database + try { + byte[] raw = readRaw(file); + String data = new String(raw); + + if (data.startsWith(PubkeyUtils.PKCS8_START)) { + int start = data.indexOf(PubkeyUtils.PKCS8_START) + PubkeyUtils.PKCS8_START.length(); + int end = data.indexOf(PubkeyUtils.PKCS8_END); + + if (end > start) { + char[] encoded = data.substring(start, end - 1).toCharArray(); + Log.d(TAG, "encoded: " + new String(encoded)); + byte[] decoded = Base64.decode(encoded); + KeyPair kp = PubkeyUtils.recoverKeyPair(decoded); + pubkey.setType(kp.getPrivate().getAlgorithm()); + pubkey.setPrivateKey(kp.getPrivate().getEncoded()); + pubkey.setPublicKey(kp.getPublic().getEncoded()); + } + else { + Log.e(TAG, "Problem parsing PKCS#8 file; corrupt?"); + Toast.makeText(PubkeyListActivity.this, + R.string.pubkey_import_parse_problem, + Toast.LENGTH_LONG).show(); + } + } + else { + PEMStructure struct = PEMDecoder.parsePEM(new String(raw).toCharArray()); + pubkey.setEncrypted(PEMDecoder.isPEMEncrypted(struct)); + pubkey.setType(PubkeyDatabase.KEY_TYPE_IMPORTED); + pubkey.setPrivateKey(raw); + } + + // write new value into database + if (pubkeydb == null) + pubkeydb = new PubkeyDatabase(this); + + pubkeydb.savePubkey(pubkey); + updateList(); + } + catch (Exception e) { + Log.e(TAG, "Problem parsing imported private key", e); + Toast.makeText(PubkeyListActivity.this, R.string.pubkey_import_parse_problem, Toast.LENGTH_LONG).show(); + } + } + + private void saveKeyToFile(final String keyString, final String nickName, int keyType) { + final int titleId, messageId, successId, errorId; + final String errorString; + + if (keyType == KEYTYPE_PRIVATE) { + titleId = R.string.pubkey_private_save_as; + messageId = R.string.pubkey_private_save_as_desc; + successId = R.string.pubkey_private_export_success; + errorId = R.string.pubkey_private_export_problem; + errorString = "Error exporting private key"; + } + else { + titleId = R.string.pubkey_public_save_as; + messageId = R.string.pubkey_public_save_as_desc; + errorId = R.string.pubkey_public_export_problem; + successId = R.string.pubkey_public_export_success; + errorString = "Error exporting public key"; + } + + final String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath(); + final EditText fileName = new EditText(PubkeyListActivity.this); + fileName.setSingleLine(); + + if (nickName != null) { + if (keyType == KEYTYPE_PRIVATE) + fileName.setText(sdcard + File.separator + nickName.trim()); + else + fileName.setText(sdcard + File.separator + nickName.trim() + ".pub"); + } + + new AlertDialog.Builder(PubkeyListActivity.this) + .setTitle(titleId) + .setMessage(messageId) + .setView(fileName) + .setPositiveButton(R.string.save, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + File keyFile = new File(fileName.getText().toString()); + + if (!keyFile.exists()) { + try { + keyFile.createNewFile(); + } + catch (IOException e) { + Log.e(TAG, errorString); + Toast.makeText(PubkeyListActivity.this, + errorId, + Toast.LENGTH_LONG).show(); + return; + } + } + + FileOutputStream fout = null; + + try { + fout = new FileOutputStream(keyFile); + fout.write(keyString.getBytes(), 0, keyString.getBytes().length); + fout.flush(); + } + catch (Exception e) { + Log.e(TAG, errorString); + Toast.makeText(PubkeyListActivity.this, + errorId, + Toast.LENGTH_LONG).show(); + return; + } + + Toast.makeText(PubkeyListActivity.this, + getResources().getString(successId, keyFile.getPath().toString()), + Toast.LENGTH_LONG).show(); + } + }).setNegativeButton(android.R.string.cancel, null).create().show(); + } + + public void fileSelected(File f) { + Log.d(TAG, "File chooser returned " + f); + readKeyFromFile(f); + } + + class PubkeyAdapter extends ArrayAdapter<PubkeyBean> { + private List<PubkeyBean> pubkeys; + + class ViewHolder { + public TextView nickname; + public TextView caption; + public ImageView icon; + } + + public PubkeyAdapter(Context context, List<PubkeyBean> pubkeys) { + super(context, R.layout.item_pubkey, pubkeys); + this.pubkeys = pubkeys; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + + if (convertView == null) { + convertView = inflater.inflate(R.layout.item_pubkey, null, false); + holder = new ViewHolder(); + holder.nickname = (TextView) convertView.findViewById(android.R.id.text1); + holder.caption = (TextView) convertView.findViewById(android.R.id.text2); + holder.icon = (ImageView) convertView.findViewById(android.R.id.icon1); + convertView.setTag(holder); + } + else + holder = (ViewHolder) convertView.getTag(); + + PubkeyBean pubkey = pubkeys.get(position); + holder.nickname.setText(pubkey.getNickname()); + boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType()); + + if (imported) { + try { + PEMStructure struct = PEMDecoder.parsePEM(new String(pubkey.getPrivateKey()).toCharArray()); + String type = (struct.pemType == PEMDecoder.PEM_RSA_PRIVATE_KEY) ? "RSA" : + (struct.pemType == PEMDecoder.PEM_DSA_PRIVATE_KEY) ? "DSA" : "EC"; + holder.caption.setText(String.format("%s unknown-bit", type)); + } + catch (IOException e) { + Log.e(TAG, "Error decoding IMPORTED public key at " + pubkey.getId(), e); + } + } + else { + try { + holder.caption.setText(pubkey.getDescription()); + } + catch (Exception e) { + Log.e(TAG, "Error decoding public key at " + pubkey.getId(), e); + holder.caption.setText(R.string.pubkey_unknown_format); + } + } + + if (bound == null) { + holder.icon.setVisibility(View.GONE); + } + else { + holder.icon.setVisibility(View.VISIBLE); + + if (bound.isKeyLoaded(pubkey.getNickname())) + holder.icon.setImageState(new int[] { android.R.attr.state_checked }, true); + else + holder.icon.setImageState(new int[] { }, true); + } + + return convertView; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/SettingsActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,55 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import com.five_ten_sg.connectbot.util.PreferenceConstants; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.preference.PreferenceManager; +import android.util.Log; + +public class SettingsActivity extends PreferenceActivity { + private static final String TAG = "ConnectBot.Settings"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + try { + addPreferencesFromResource(R.xml.preferences); + } + catch (ClassCastException e) { + Log.e(TAG, "Shared preferences are corrupt! Resetting to default values."); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + // Blow away all the preferences + SharedPreferences.Editor editor = preferences.edit(); + editor.clear(); + editor.commit(); + PreferenceManager.setDefaultValues(this, R.xml.preferences, true); + // Since they were able to get to the Settings activity, they already agreed to the EULA + editor = preferences.edit(); + editor.putBoolean(PreferenceConstants.EULA, true); + editor.commit(); + addPreferencesFromResource(R.xml.preferences); + } + + // TODO: add parse checking here to make sure we have integer value for scrollback + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/StrictModeSetup.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,25 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.five_ten_sg.connectbot; +import android.annotation.TargetApi; +import android.os.StrictMode; +@TargetApi(9) +public class StrictModeSetup { + public static void run() { + StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/TerminalView.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,459 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.five_ten_sg.connectbot.bean.SelectionArea; +import com.five_ten_sg.connectbot.service.FontSizeChangedListener; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalKeyListener; +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.database.Cursor; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PixelXorXfermode; +import android.graphics.RectF; +import android.net.Uri; +import android.os.AsyncTask; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.inputmethod.BaseInputConnection; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; +import android.view.ScaleGestureDetector; +import android.widget.Toast; +import de.mud.terminal.VDUBuffer; + +/** + * User interface {@link View} for showing a TerminalBridge in an + * {@link Activity}. Handles drawing bitmap updates and passing keystrokes down + * to terminal. + * + * @author jsharkey + */ +public class TerminalView extends View implements FontSizeChangedListener { + public final static String TAG = "ConnectBot.TerminalView"; + + private final Context context; + public final TerminalBridge bridge; + private final Paint paint; + private final Paint cursorPaint; + private final Paint cursorStrokePaint; + + // Cursor paints to distinguish modes + private Path ctrlCursor, altCursor, shiftCursor; + private RectF tempSrc, tempDst; + private Matrix scaleMatrix; + private static final Matrix.ScaleToFit scaleType = Matrix.ScaleToFit.FILL; + + private Toast notification = null; + private String lastNotification = null; + private volatile boolean notifications = true; + + // Related to Accessibility Features + private boolean mAccessibilityInitialized = false; + private boolean mAccessibilityActive = true; + private Object[] mAccessibilityLock = new Object[0]; + private StringBuffer mAccessibilityBuffer; + private Pattern mControlCodes = null; + private Matcher mCodeMatcher = null; + private AccessibilityEventSender mEventSender = null; + + + private static final String BACKSPACE_CODE = "\\x08\\x1b\\[K"; + private static final String CONTROL_CODE_PATTERN = "\\x1b\\[K[^m]+[m|:]"; + + private static final int ACCESSIBILITY_EVENT_THRESHOLD = 1000; + private static final String SCREENREADER_INTENT_ACTION = "android.accessibilityservice.AccessibilityService"; + private static final String SCREENREADER_INTENT_CATEGORY = "android.accessibilityservice.category.FEEDBACK_SPOKEN"; + + public ScaleGestureDetector mScaleDetector; + + public TerminalView(Context context, TerminalBridge bridge) { + super(context); + this.context = context; + this.bridge = bridge; + paint = new Paint(); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + setFocusable(true); + setFocusableInTouchMode(true); + cursorPaint = new Paint(); + cursorPaint.setColor(bridge.color[bridge.defaultFg]); + cursorPaint.setXfermode(new PixelXorXfermode(bridge.color[bridge.defaultBg])); + cursorPaint.setAntiAlias(true); + cursorStrokePaint = new Paint(cursorPaint); + cursorStrokePaint.setStrokeWidth(0.1f); + cursorStrokePaint.setStyle(Paint.Style.STROKE); + /* + * Set up our cursor indicators on a 1x1 Path object which we can later + * transform to our character width and height + */ + // TODO make this into a resource somehow + shiftCursor = new Path(); + shiftCursor.lineTo(0.5f, 0.33f); + shiftCursor.lineTo(1.0f, 0.0f); + altCursor = new Path(); + altCursor.moveTo(0.0f, 1.0f); + altCursor.lineTo(0.5f, 0.66f); + altCursor.lineTo(1.0f, 1.0f); + ctrlCursor = new Path(); + ctrlCursor.moveTo(0.0f, 0.25f); + ctrlCursor.lineTo(1.0f, 0.5f); + ctrlCursor.lineTo(0.0f, 0.75f); + // For creating the transform when the terminal resizes + tempSrc = new RectF(); + tempSrc.set(0.0f, 0.0f, 1.0f, 1.0f); + tempDst = new RectF(); + scaleMatrix = new Matrix(); + bridge.addFontSizeChangedListener(this); + // connect our view up to the bridge + setOnKeyListener(bridge.getKeyHandler()); + mAccessibilityBuffer = new StringBuffer(); + // Enable accessibility features if a screen reader is active. + new AccessibilityStateTester().execute((Void) null); + mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); + } + + public void destroy() { + // tell bridge to destroy its bitmap + bridge.parentDestroyed(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + bridge.parentChanged(this); + scaleCursors(); + } + + public void onFontSizeChanged(float size) { + scaleCursors(); + } + + private void scaleCursors() { + // Create a scale matrix to scale our 1x1 representation of the cursor + tempDst.set(0.0f, 0.0f, bridge.charWidth, bridge.charHeight); + scaleMatrix.setRectToRect(tempSrc, tempDst, scaleType); + } + + @Override + public void onDraw(Canvas canvas) { + if (bridge.bitmap != null) { + // draw the bitmap + bridge.onDraw(); + // draw the bridge bitmap if it exists + canvas.drawBitmap(bridge.bitmap, 0, 0, paint); + + // also draw cursor if visible + if (bridge.buffer.isCursorVisible()) { + int cursorColumn = bridge.buffer.getCursorColumn(); + final int cursorRow = bridge.buffer.getCursorRow(); + final int columns = bridge.buffer.getColumns(); + + if (cursorColumn == columns) + cursorColumn = columns - 1; + + if (cursorColumn < 0 || cursorRow < 0) + return; + + int currentAttribute = bridge.buffer.getAttributes( + cursorColumn, cursorRow); + boolean onWideCharacter = (currentAttribute & VDUBuffer.FULLWIDTH) != 0; + int x = cursorColumn * bridge.charWidth; + int y = (bridge.buffer.getCursorRow() + + bridge.buffer.screenBase - bridge.buffer.windowBase) + * bridge.charHeight; + // Save the current clip and translation + canvas.save(); + canvas.translate(x, y); + canvas.clipRect(0, 0, + bridge.charWidth * (onWideCharacter ? 2 : 1), + bridge.charHeight); + canvas.drawPaint(cursorPaint); + final int deadKey = bridge.getKeyHandler().getDeadKey(); + + if (deadKey != 0) { + canvas.drawText(new char[] { (char)deadKey }, 0, 1, 0, 0, cursorStrokePaint); + } + + // Make sure we scale our decorations to the correct size. + canvas.concat(scaleMatrix); + int metaState = bridge.getKeyHandler().getMetaState(); + + if ((metaState & TerminalKeyListener.META_SHIFT_ON) != 0) + canvas.drawPath(shiftCursor, cursorStrokePaint); + else if ((metaState & TerminalKeyListener.META_SHIFT_LOCK) != 0) + canvas.drawPath(shiftCursor, cursorPaint); + + if ((metaState & TerminalKeyListener.META_ALT_ON) != 0) + canvas.drawPath(altCursor, cursorStrokePaint); + else if ((metaState & TerminalKeyListener.META_ALT_LOCK) != 0) + canvas.drawPath(altCursor, cursorPaint); + + if ((metaState & TerminalKeyListener.META_CTRL_ON) != 0) + canvas.drawPath(ctrlCursor, cursorStrokePaint); + else if ((metaState & TerminalKeyListener.META_CTRL_LOCK) != 0) + canvas.drawPath(ctrlCursor, cursorPaint); + + // Restore previous clip region + canvas.restore(); + } + + // draw any highlighted area + if (bridge.isSelectingForCopy()) { + SelectionArea area = bridge.getSelectionArea(); + canvas.save(Canvas.CLIP_SAVE_FLAG); + canvas.clipRect( + area.getLeft() * bridge.charWidth, + area.getTop() * bridge.charHeight, + (area.getRight() + 1) * bridge.charWidth, + (area.getBottom() + 1) * bridge.charHeight + ); + canvas.drawPaint(cursorPaint); + canvas.restore(); + } + } + } + + public void notifyUser(String message) { + try { + // ignore if don't want notifications + if (!notifications) return; + // Don't keep telling the user the same thing. + if (lastNotification != null && lastNotification.equals(message)) return; + // create or use old toast + if (notification == null) { + notification = Toast.makeText(context, message, Toast.LENGTH_SHORT); + } + else { + notification.setText(message); + } + notification.show(); + lastNotification = message; + } + catch (Exception e) { + Log.e(TAG, "Problem while trying to notify user", e); + } + } + + /** + * Ask the {@link TerminalBridge} we're connected to to resize to a specific size. + * @param width + * @param height + */ + public void forceSize(int width, int height) { + bridge.resizeComputed(width, height, getWidth(), getHeight()); + } + + /** + * Sets the ability for the TerminalView to display Toast notifications to the user. + * @param value whether to enable notifications or not + */ + public void setNotifications(boolean value) { + notifications = value; + } + + @Override + public boolean onCheckIsTextEditor() { + return true; + } + + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + outAttrs.imeOptions |= + EditorInfo.IME_FLAG_NO_EXTRACT_UI | + EditorInfo.IME_FLAG_NO_ENTER_ACTION | + EditorInfo.IME_ACTION_NONE; + outAttrs.inputType = EditorInfo.TYPE_NULL; + return new BaseInputConnection(this, false) { + @Override + public boolean deleteSurroundingText(int leftLength, int rightLength) { + if (rightLength == 0 && leftLength == 0) { + return this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + } + + for (int i = 0; i < leftLength; i++) { + this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + } + + // TODO: forward delete + return true; + } + }; + } + + public void propagateConsoleText(char[] rawText, int length) { + if (mAccessibilityActive) { + synchronized (mAccessibilityLock) { + mAccessibilityBuffer.append(rawText, 0, length); + } + + if (mAccessibilityInitialized) { + if (mEventSender != null) { + removeCallbacks(mEventSender); + } + else { + mEventSender = new AccessibilityEventSender(); + } + + postDelayed(mEventSender, ACCESSIBILITY_EVENT_THRESHOLD); + } + } + } + + private class AccessibilityEventSender implements Runnable { + public void run() { + synchronized (mAccessibilityLock) { + if (mCodeMatcher == null) { + mCodeMatcher = mControlCodes.matcher(mAccessibilityBuffer); + } + else { + mCodeMatcher.reset(mAccessibilityBuffer); + } + + // Strip all control codes out. + mAccessibilityBuffer = new StringBuffer(mCodeMatcher.replaceAll(" ")); + // Apply Backspaces using backspace character sequence + int i = mAccessibilityBuffer.indexOf(BACKSPACE_CODE); + + while (i != -1) { + mAccessibilityBuffer = mAccessibilityBuffer.replace(i == 0 ? 0 : i - 1, i + + BACKSPACE_CODE.length(), ""); + i = mAccessibilityBuffer.indexOf(BACKSPACE_CODE); + } + + if (mAccessibilityBuffer.length() > 0) { + AccessibilityEvent event = AccessibilityEvent.obtain( + AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); + event.setFromIndex(0); + event.setAddedCount(mAccessibilityBuffer.length()); + event.getText().add(mAccessibilityBuffer); + sendAccessibilityEventUnchecked(event); + mAccessibilityBuffer.setLength(0); + } + } + } + } + + private class AccessibilityStateTester extends AsyncTask<Void, Void, Boolean> { + @Override + protected Boolean doInBackground(Void... params) { + /* + * Presumably if the accessibility manager is not enabled, we don't + * need to send accessibility events. + */ + final AccessibilityManager accessibility = (AccessibilityManager) context + .getSystemService(Context.ACCESSIBILITY_SERVICE); + + if (!accessibility.isEnabled()) { + return false; + } + + /* + * Restrict the set of intents to only accessibility services that + * have the category FEEDBACK_SPOKEN (aka, screen readers). + */ + final Intent screenReaderIntent = new Intent(SCREENREADER_INTENT_ACTION); + screenReaderIntent.addCategory(SCREENREADER_INTENT_CATEGORY); + final ContentResolver cr = context.getContentResolver(); + final List<ResolveInfo> screenReaders = context.getPackageManager().queryIntentServices( + screenReaderIntent, 0); + boolean foundScreenReader = false; + final int N = screenReaders.size(); + + for (int i = 0; i < N; i++) { + final ResolveInfo screenReader = screenReaders.get(i); + /* + * All screen readers are expected to implement a content + * provider that responds to: + * content://<nameofpackage>.providers.StatusProvider + */ + final Cursor cursor = cr.query( + Uri.parse("content://" + screenReader.serviceInfo.packageName + + ".providers.StatusProvider"), null, null, null, null); + + if (cursor != null && cursor.moveToFirst()) { + /* + * These content providers use a special cursor that only has + * one element, an integer that is 1 if the screen reader is + * running. + */ + final int status = cursor.getInt(0); + cursor.close(); + + if (status == 1) { + foundScreenReader = true; + break; + } + } + } + + if (foundScreenReader) { + mControlCodes = Pattern.compile(CONTROL_CODE_PATTERN); + } + + return foundScreenReader; + } + + @Override + protected void onPostExecute(Boolean result) { + mAccessibilityActive = result; + mAccessibilityInitialized = true; + + if (result) { + mEventSender = new AccessibilityEventSender(); + postDelayed(mEventSender, ACCESSIBILITY_EVENT_THRESHOLD); + } + else { + mAccessibilityBuffer = null; + } + } + } + + private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + @Override + public boolean onScale(ScaleGestureDetector detector) { + float mScaleFactor = detector.getScaleFactor(); + + if (mScaleFactor > 1.1) { + bridge.increaseFontSize(); + return true; + } + else if (mScaleFactor < 0.9) { + bridge.decreaseFontSize(); + return true; + } + + return (false); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/WizardActivity.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,105 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot; + +import com.five_ten_sg.connectbot.util.HelpTopicView; +import android.app.Activity; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; +import android.widget.ViewFlipper; + +/** + * Show a series of wizard-like steps to the user, which might include an EULA, + * program credits, and helpful hints. + * + * @author jsharkey + */ +public class WizardActivity extends Activity { + protected ViewFlipper flipper = null; + private Button next, prev; + private static final String TAG = "ConnectBot.WizardActivity"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.act_wizard); + this.flipper = (ViewFlipper) findViewById(R.id.wizard_flipper); + // inflate the layout for EULA step + LayoutInflater inflater = LayoutInflater.from(this); + View helpView = inflater.inflate(R.layout.wiz_eula, this.flipper, false); + this.flipper.addView(helpView); + // Add a view for each help topic we want the user to see. + String[] topics = getResources().getStringArray(R.array.list_wizard_topics); + + for (String topic : topics) { + flipper.addView(new HelpTopicView(this).setTopic(topic)); + } + + next = (Button)this.findViewById(R.id.action_next); + next.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + if (isLastDisplayed()) { + // user walked past end of wizard, so return okay + WizardActivity.this.setResult(Activity.RESULT_OK); + WizardActivity.this.finish(); + } + else { + // show next step and update buttons + flipper.showNext(); + updateButtons(); + } + } + }); + prev = (Button)this.findViewById(R.id.action_prev); + prev.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + if (isFirstDisplayed()) { + // user walked past beginning of wizard, so return that they cancelled + WizardActivity.this.setResult(Activity.RESULT_CANCELED); + WizardActivity.this.finish(); + } + else { + // show previous step and update buttons + flipper.showPrevious(); + updateButtons(); + } + } + }); + this.updateButtons(); + } + + protected boolean isFirstDisplayed() { + return (flipper.getDisplayedChild() == 0); + } + + protected boolean isLastDisplayed() { + return (flipper.getDisplayedChild() == flipper.getChildCount() - 1); + } + + protected void updateButtons() { + boolean eula = (flipper.getDisplayedChild() == 0); + next.setText(eula ? getString(R.string.wizard_agree) : getString(R.string.wizard_next)); + prev.setText(eula ? getString(R.string.delete_neg) : getString(R.string.wizard_back)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/bean/AbstractBean.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,48 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.bean; + +import java.util.Map.Entry; + +import com.five_ten_sg.connectbot.util.XmlBuilder; +import android.content.ContentValues; + +/** + * @author Kenny Root + * + */ +abstract class AbstractBean { + public abstract ContentValues getValues(); + public abstract String getBeanName(); + + public String toXML() { + XmlBuilder xml = new XmlBuilder(); + xml.append(String.format("<%s>", getBeanName())); + ContentValues values = getValues(); + + for (Entry<String, Object> entry : values.valueSet()) { + Object value = entry.getValue(); + + if (value != null) + xml.append(entry.getKey(), value); + } + + xml.append(String.format("</%s>", getBeanName())); + return xml.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/bean/HostBean.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,454 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.bean; + +import com.five_ten_sg.connectbot.util.HostDatabase; +import android.content.ContentValues; +import android.net.Uri; + +/** + * @author Kenny Root + * + */ +public class HostBean extends AbstractBean { + public static final String BEAN_NAME = "host"; + + /* Database fields */ + private long id = -1; + private String nickname = null; + private String username = null; + private String hostname = null; + private int port = 22; + private String protocol = "ssh"; + private String hostKeyAlgo = null; + private byte[] hostKey = null; + private long lastConnect = -1; + private String color; + private boolean useKeys = true; + private String useAuthAgent = HostDatabase.AUTHAGENT_NO; + private String postLogin = null; + private long pubkeyId = -1; + private String delKey = HostDatabase.DELKEY_DEL; + private float fontSize = -1; + private boolean fixedSize = false; + private int fixedWidth = 80; + private int fixedHeight = 25; + private boolean wantSession = true; + private boolean compression = false; + private String httpproxy = null; + private String encoding = HostDatabase.ENCODING_DEFAULT; + private boolean stayConnected = false; + private boolean wantX11Forward = false; + private String x11Host = "localhost"; + private int x11Port = 6000; + private String monitor = null; + private String hostemulation = null; + private String encryption5250 = null; + private String library = null; + private String initialMenu = null; + private String program = null; + + public HostBean() { + } + + @Override + public String getBeanName() { + return BEAN_NAME; + } + + public HostBean(String nickname, String protocol, String username, String hostname, int port) { + this.nickname = nickname; + this.protocol = protocol; + this.username = username; + this.hostname = hostname; + this.port = port; + } + + public boolean isSSH() { + return protocol.equals("ssh"); + } + + public boolean is5250() { + return protocol.equals("tn5250"); + } + + public boolean isTelnet() { + return protocol.equals("telnet"); + } + + public boolean isAsync() { + return isSSH() || isTelnet(); + } + + public void setId(long id) { + this.id = id; + } + public long getId() { + return id; + } + public void setNickname(String nickname) { + this.nickname = nickname; + } + public String getNickname() { + return nickname; + } + public void setUsername(String username) { + this.username = username; + } + public String getUsername() { + return username; + } + public void setHostname(String hostname) { + this.hostname = hostname; + } + public String getHostname() { + return hostname; + } + public void setPort(int port) { + this.port = port; + } + public int getPort() { + return port; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getProtocol() { + return protocol; + } + + public void setHostKeyAlgo(String hostKeyAlgo) { + this.hostKeyAlgo = hostKeyAlgo; + } + public String getHostKeyAlgo() { + return hostKeyAlgo; + } + public void setHostKey(byte[] hostKey) { + if (hostKey == null) + this.hostKey = null; + else + this.hostKey = hostKey.clone(); + } + public byte[] getHostKey() { + if (hostKey == null) + return null; + else + return hostKey.clone(); + } + public void setLastConnect(long lastConnect) { + this.lastConnect = lastConnect; + } + public long getLastConnect() { + return lastConnect; + } + public void setColor(String color) { + this.color = color; + } + public String getColor() { + return color; + } + public void setUseKeys(boolean useKeys) { + this.useKeys = useKeys; + } + public boolean getUseKeys() { + return useKeys; + } + public void setUseAuthAgent(String useAuthAgent) { + this.useAuthAgent = useAuthAgent; + } + public String getUseAuthAgent() { + return useAuthAgent; + } + public void setPostLogin(String postLogin) { + this.postLogin = postLogin; + } + public String getPostLogin() { + return postLogin; + } + public void setPubkeyId(long pubkeyId) { + this.pubkeyId = pubkeyId; + } + public long getPubkeyId() { + return pubkeyId; + } + public void setWantSession(boolean wantSession) { + this.wantSession = wantSession; + } + public boolean getWantSession() { + return wantSession; + } + public void setDelKey(String delKey) { + this.delKey = delKey; + } + public String getDelKey() { + return delKey; + } + public void setFontSize(float fontSize) { + this.fontSize = fontSize; + } + public float getFontSize() { + return fontSize; + } + public void setFixedSize(boolean fixedSize) { + this.fixedSize = fixedSize; + } + public boolean getFixedSize() { + return fixedSize; + } + public void setFixedWidth(int fixedWidth) { + this.fixedWidth = fixedWidth; + } + public int getFixedWidth() { + return fixedWidth; + } + public void setFixedHeight(int fixedHeight) { + this.fixedHeight = fixedHeight; + } + public int getFixedHeight() { + return fixedHeight; + } + public void setCompression(boolean compression) { + this.compression = compression; + } + public boolean getCompression() { + return compression; + } + public void setHttpproxy(String httpproxy) { + this.httpproxy = httpproxy; + } + public String getHttpproxy() { + return httpproxy; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public String getEncoding() { + return this.encoding; + } + + public void setStayConnected(boolean stayConnected) { + this.stayConnected = stayConnected; + } + + public boolean getStayConnected() { + return stayConnected; + } + + public String getDescription() { + String description = String.format("%s@%s", username, hostname); + + if (port != 22) + description += String.format(":%d", port); + + return description; + } + + public boolean getWantX11Forward() { + return this.wantX11Forward; + } + + public void setWantX11Forward(boolean wantX11Forward) { + this.wantX11Forward = wantX11Forward; + } + + public String getX11Host() { + return this.x11Host; + } + + public void setX11Host(String x11Host) { + this.x11Host = x11Host; + } + + public int getX11Port() { + return this.x11Port; + } + + public void setX11Port(int x11Port) { + this.x11Port = x11Port; + } + + public String getMonitor() { + return this.monitor; + } + + public void setMonitor(String monitor) { + this.monitor = monitor; + } + + public String getHostEmulation() { + return this.hostemulation; + } + + public void setHostEmulation(String hostemulation) { + this.hostemulation = hostemulation; + } + + public String getEncryption5250() { + return this.encryption5250; + } + + public void setEncryption5250(String encryption5250) { + this.encryption5250 = encryption5250; + } + + public String getLibrary() { + return this.library; + } + + public void setLibrary(String library) { + this.library = library; + } + + public String getInitialMenu() { + return this.initialMenu; + } + + public void setInitialMenu(String initialMenu) { + this.initialMenu = initialMenu; + } + + public String getProgram() { + return this.program; + } + + public void setProgram(String program) { + this.program = program; + } + + @Override + public ContentValues getValues() { + ContentValues values = new ContentValues(); + values.put(HostDatabase.FIELD_HOST_NICKNAME, nickname); + values.put(HostDatabase.FIELD_HOST_PROTOCOL, protocol); + values.put(HostDatabase.FIELD_HOST_USERNAME, username); + values.put(HostDatabase.FIELD_HOST_HOSTNAME, hostname); + values.put(HostDatabase.FIELD_HOST_PORT, port); + values.put(HostDatabase.FIELD_HOST_HOSTKEYALGO, hostKeyAlgo); + values.put(HostDatabase.FIELD_HOST_HOSTKEY, hostKey); + values.put(HostDatabase.FIELD_HOST_LASTCONNECT, lastConnect); + values.put(HostDatabase.FIELD_HOST_COLOR, color); + values.put(HostDatabase.FIELD_HOST_USEKEYS, Boolean.toString(useKeys)); + values.put(HostDatabase.FIELD_HOST_USEAUTHAGENT, useAuthAgent); + values.put(HostDatabase.FIELD_HOST_POSTLOGIN, postLogin); + values.put(HostDatabase.FIELD_HOST_PUBKEYID, pubkeyId); + values.put(HostDatabase.FIELD_HOST_WANTSESSION, Boolean.toString(wantSession)); + values.put(HostDatabase.FIELD_HOST_DELKEY, delKey); + values.put(HostDatabase.FIELD_HOST_FONTSIZE, fontSize); + values.put(HostDatabase.FIELD_HOST_FIXEDSIZE, Boolean.toString(fixedSize)); + values.put(HostDatabase.FIELD_HOST_FIXEDWIDTH, fixedWidth); + values.put(HostDatabase.FIELD_HOST_FIXEDHEIGHT, fixedHeight); + values.put(HostDatabase.FIELD_HOST_COMPRESSION, Boolean.toString(compression)); + values.put(HostDatabase.FIELD_HOST_HTTPPROXY, httpproxy); + values.put(HostDatabase.FIELD_HOST_ENCODING, encoding); + values.put(HostDatabase.FIELD_HOST_STAYCONNECTED, stayConnected); + values.put(HostDatabase.FIELD_HOST_WANTX11FORWARD, wantX11Forward); + values.put(HostDatabase.FIELD_HOST_X11HOST, x11Host); + values.put(HostDatabase.FIELD_HOST_X11PORT, x11Port); + values.put(HostDatabase.FIELD_HOST_MONITOR, monitor); + values.put(HostDatabase.FIELD_HOST_EMULATION, hostemulation); + values.put(HostDatabase.FIELD_HOST_ENCRYPTION5250, encryption5250); + values.put(HostDatabase.FIELD_HOST_LIBRARY5250, library); + values.put(HostDatabase.FIELD_HOST_MENU5250, initialMenu); + values.put(HostDatabase.FIELD_HOST_PROGRAM5250, program); + return values; + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof HostBean)) + return false; + + HostBean host = (HostBean)o; + + if (id != -1 && host.getId() != -1) + return host.getId() == id; + + if (nickname == null) { + if (host.getNickname() != null) + return false; + } + else if (!nickname.equals(host.getNickname())) + return false; + + if (protocol == null) { + if (host.getProtocol() != null) + return false; + } + else if (!protocol.equals(host.getProtocol())) + return false; + + if (username == null) { + if (host.getUsername() != null) + return false; + } + else if (!username.equals(host.getUsername())) + return false; + + if (hostname == null) { + if (host.getHostname() != null) + return false; + } + else if (!hostname.equals(host.getHostname())) + return false; + + if (port != host.getPort()) + return false; + + return true; + } + + @Override + public int hashCode() { + int hash = 7; + + if (id != -1) + return (int)id; + + hash = 31 * hash + (null == nickname ? 0 : nickname.hashCode()); + hash = 31 * hash + (null == protocol ? 0 : protocol.hashCode()); + hash = 31 * hash + (null == username ? 0 : username.hashCode()); + hash = 31 * hash + (null == hostname ? 0 : hostname.hashCode()); + hash = 31 * hash + port; + return hash; + } + + /** + * @return URI identifying this HostBean + */ + public Uri getUri() { + StringBuilder sb = new StringBuilder(); + sb.append(protocol) + .append("://"); + + if (username != null) + sb.append(Uri.encode(username)) + .append('@'); + + sb.append(Uri.encode(hostname)) + .append(':') + .append(port) + .append("/#") + .append(nickname); + return Uri.parse(sb.toString()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/bean/PortForwardBean.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,240 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.bean; + +import com.five_ten_sg.connectbot.util.HostDatabase; +import android.content.ContentValues; + + +/** + * @author Kenny Root + * + */ +public class PortForwardBean extends AbstractBean { + public static final String BEAN_NAME = "portforward"; + + /* Database fields */ + private long id = -1; + private long hostId = -1; + private String nickname = null; + private String type = null; + private int sourcePort = -1; + private String destAddr = null; + private int destPort = -1; + + /* Transient values */ + private boolean enabled = false; + private Object identifier = null; + + /** + * @param id database ID of port forward + * @param nickname Nickname to use to identify port forward + * @param type One of the port forward types from {@link HostDatabase} + * @param sourcePort Source port number + * @param destAddr Destination hostname or IP address + * @param destPort Destination port number + */ + public PortForwardBean(long id, long hostId, String nickname, String type, int sourcePort, String destAddr, int destPort) { + this.id = id; + this.hostId = hostId; + this.nickname = nickname; + this.type = type; + this.sourcePort = sourcePort; + this.destAddr = destAddr; + this.destPort = destPort; + } + + /** + * @param type One of the port forward types from {@link HostDatabase} + * @param source Source port number + * @param dest Destination is "host:port" format + */ + public PortForwardBean(long hostId, String nickname, String type, String source, String dest) { + this.hostId = hostId; + this.nickname = nickname; + this.type = type; + this.sourcePort = Integer.parseInt(source); + setDest(dest); + } + + @Override + public String getBeanName() { + return BEAN_NAME; + } + + /** + * @param id the id to set + */ + public void setId(long id) { + this.id = id; + } + + /** + * @return the id + */ + public long getId() { + return id; + } + + /** + * @param nickname the nickname to set + */ + public void setNickname(String nickname) { + this.nickname = nickname; + } + + /** + * @return the nickname + */ + public String getNickname() { + return nickname; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param sourcePort the sourcePort to set + */ + public void setSourcePort(int sourcePort) { + this.sourcePort = sourcePort; + } + + /** + * @return the sourcePort + */ + public int getSourcePort() { + return sourcePort; + } + + /** + * @param dest The destination in "host:port" format + */ + public final void setDest(String dest) { + String[] destSplit = dest.split(":"); + this.destAddr = destSplit[0]; + + if (destSplit.length > 1) + this.destPort = Integer.parseInt(destSplit[1]); + } + + /** + * @param destAddr the destAddr to set + */ + public void setDestAddr(String destAddr) { + this.destAddr = destAddr; + } + + /** + * @return the destAddr + */ + public String getDestAddr() { + return destAddr; + } + + /** + * @param destPort the destPort to set + */ + public void setDestPort(int destPort) { + this.destPort = destPort; + } + + /** + * @return the destPort + */ + public int getDestPort() { + return destPort; + } + + /** + * @param enabled the enabled to set + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + /** + * @return the enabled + */ + public boolean isEnabled() { + return enabled; + } + + /** + * @param identifier the identifier of this particular type to set + */ + public void setIdentifier(Object identifier) { + this.identifier = identifier; + } + + /** + * @return the identifier used by this particular type + */ + public Object getIdentifier() { + return identifier; + } + + /** + * @return human readable description of the port forward + */ + public CharSequence getDescription() { + String description = "Unknown type"; + + if (HostDatabase.PORTFORWARD_LOCAL.equals(type)) { + description = String.format("Local port %d to %s:%d", sourcePort, destAddr, destPort); + } + else if (HostDatabase.PORTFORWARD_REMOTE.equals(type)) { + description = String.format("Remote port %d to %s:%d", sourcePort, destAddr, destPort); + /* I don't think we need the SOCKS4 type. + } else if (HostDatabase.PORTFORWARD_DYNAMIC4.equals(type)) { + description = String.format("Dynamic port %d (SOCKS4)", sourcePort); + */ + } + else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(type)) { + description = String.format("Dynamic port %d (SOCKS)", sourcePort); + } + + return description; + } + + /** + * @return + */ + @Override + public ContentValues getValues() { + ContentValues values = new ContentValues(); + values.put(HostDatabase.FIELD_PORTFORWARD_HOSTID, hostId); + values.put(HostDatabase.FIELD_PORTFORWARD_NICKNAME, nickname); + values.put(HostDatabase.FIELD_PORTFORWARD_TYPE, type); + values.put(HostDatabase.FIELD_PORTFORWARD_SOURCEPORT, sourcePort); + values.put(HostDatabase.FIELD_PORTFORWARD_DESTADDR, destAddr); + values.put(HostDatabase.FIELD_PORTFORWARD_DESTPORT, destPort); + return values; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/bean/PubkeyBean.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,232 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.bean; + +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; + +import com.five_ten_sg.connectbot.util.PubkeyDatabase; +import com.five_ten_sg.connectbot.util.PubkeyUtils; +import android.content.ContentValues; + +/** + * @author Kenny Root + * + */ +public class PubkeyBean extends AbstractBean { + public static final String BEAN_NAME = "pubkey"; + + /* Database fields */ + private long id; + private String nickname; + private String type; + private byte[] privateKey; + private byte[] publicKey; + private boolean encrypted = false; + private boolean startup = false; + private boolean confirmUse = false; + private int lifetime = 0; + + /* Transient values */ + private transient boolean unlocked = false; + private transient Object unlockedPrivate = null; + private transient String description; + + @Override + public String getBeanName() { + return BEAN_NAME; + } + + public void setId(long id) { + this.id = id; + } + + public long getId() { + return id; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getNickname() { + return nickname; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setPrivateKey(byte[] privateKey) { + if (privateKey == null) + this.privateKey = null; + else + this.privateKey = privateKey.clone(); + } + + public byte[] getPrivateKey() { + if (privateKey == null) + return null; + else + return privateKey.clone(); + } + + public void setPublicKey(byte[] encoded) { + if (encoded == null) + publicKey = null; + else + publicKey = encoded.clone(); + } + + public byte[] getPublicKey() { + if (publicKey == null) + return null; + else + return publicKey.clone(); + } + + public void setEncrypted(boolean encrypted) { + this.encrypted = encrypted; + } + + public boolean isEncrypted() { + return encrypted; + } + + public void setStartup(boolean startup) { + this.startup = startup; + } + + public boolean isStartup() { + return startup; + } + + public void setConfirmUse(boolean confirmUse) { + this.confirmUse = confirmUse; + } + + public boolean isConfirmUse() { + return confirmUse; + } + + public void setLifetime(int lifetime) { + this.lifetime = lifetime; + } + + public int getLifetime() { + return lifetime; + } + + public void setUnlocked(boolean unlocked) { + this.unlocked = unlocked; + } + + public boolean isUnlocked() { + return unlocked; + } + + public void setUnlockedPrivate(Object unlockedPrivate) { + this.unlockedPrivate = unlockedPrivate; + } + + public Object getUnlockedPrivate() { + return unlockedPrivate; + } + + public String getDescription() { + if (description == null) { + final StringBuilder sb = new StringBuilder(); + + try { + final PublicKey pubKey = PubkeyUtils.decodePublic(publicKey, type); + + if (PubkeyDatabase.KEY_TYPE_RSA.equals(type)) { + int bits = ((RSAPublicKey) pubKey).getModulus().bitLength(); + sb.append("RSA "); + sb.append(bits); + sb.append("-bit"); + } + else if (PubkeyDatabase.KEY_TYPE_DSA.equals(type)) { + sb.append("DSA 1024-bit"); + } + else if (PubkeyDatabase.KEY_TYPE_EC.equals(type)) { + int bits = ((ECPublicKey) pubKey).getParams().getCurve().getField() + .getFieldSize(); + sb.append("EC "); + sb.append(bits); + sb.append("-bit"); + } + else { + sb.append("Unknown Key Type"); + } + } + catch (NoSuchAlgorithmException e) { + sb.append("Unknown Key Type"); + } + catch (InvalidKeySpecException e) { + sb.append("Unknown Key Type"); + } + + if (encrypted) sb.append(" (encrypted)"); + + description = sb.toString(); + } + + return description; + } + + /* (non-Javadoc) + * @see com.five_ten_sg.connectbot.bean.AbstractBean#getValues() + */ + @Override + public ContentValues getValues() { + ContentValues values = new ContentValues(); + values.put(PubkeyDatabase.FIELD_PUBKEY_NICKNAME, nickname); + values.put(PubkeyDatabase.FIELD_PUBKEY_TYPE, type); + values.put(PubkeyDatabase.FIELD_PUBKEY_PRIVATE, privateKey); + values.put(PubkeyDatabase.FIELD_PUBKEY_PUBLIC, publicKey); + values.put(PubkeyDatabase.FIELD_PUBKEY_ENCRYPTED, encrypted ? 1 : 0); + values.put(PubkeyDatabase.FIELD_PUBKEY_STARTUP, startup ? 1 : 0); + values.put(PubkeyDatabase.FIELD_PUBKEY_CONFIRMUSE, confirmUse ? 1 : 0); + values.put(PubkeyDatabase.FIELD_PUBKEY_LIFETIME, lifetime); + return values; + } + + public boolean changePassword(String oldPassword, String newPassword) throws Exception { + PrivateKey priv; + + try { + priv = PubkeyUtils.decodePrivate(getPrivateKey(), getType(), oldPassword); + } + catch (Exception e) { + return false; + } + + setPrivateKey(PubkeyUtils.getEncodedPrivate(priv, newPassword)); + setEncrypted(newPassword.length() > 0); + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/bean/SelectionArea.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,198 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.bean; + +import de.mud.terminal.VDUBuffer; + +/** + * @author Kenny Root + * Keep track of a selection area for the terminal copying mechanism. + * If the orientation is flipped one way, swap the bottom and top or + * left and right to keep it in the correct orientation. + */ +public class SelectionArea { + private int top; + private int bottom; + private int left; + private int right; + private int maxColumns; + private int maxRows; + private boolean selectingOrigin; + + public SelectionArea() { + reset(); + } + + public final void reset() { + top = left = bottom = right = 0; + selectingOrigin = true; + } + + /** + * @param columns + * @param rows + */ + public void setBounds(int columns, int rows) { + maxColumns = columns - 1; + maxRows = rows - 1; + } + + private int checkBounds(int value, int max) { + if (value < 0) + return 0; + else if (value > max) + return max; + else + return value; + } + + public boolean isSelectingOrigin() { + return selectingOrigin; + } + + public void finishSelectingOrigin() { + selectingOrigin = false; + } + + public void decrementRow() { + if (selectingOrigin) + setTop(top - 1); + else + setBottom(bottom - 1); + } + + public void incrementRow() { + if (selectingOrigin) + setTop(top + 1); + else + setBottom(bottom + 1); + } + + public void setRow(int row) { + if (selectingOrigin) + setTop(row); + else + setBottom(row); + } + + private void setTop(int top) { + this.top = bottom = checkBounds(top, maxRows); + } + + public int getTop() { + return Math.min(top, bottom); + } + + private void setBottom(int bottom) { + this.bottom = checkBounds(bottom, maxRows); + } + + public int getBottom() { + return Math.max(top, bottom); + } + + public void decrementColumn() { + if (selectingOrigin) + setLeft(left - 1); + else + setRight(right - 1); + } + + public void incrementColumn() { + if (selectingOrigin) + setLeft(left + 1); + else + setRight(right + 1); + } + + public void setColumn(int column) { + if (selectingOrigin) + setLeft(column); + else + setRight(column); + } + + private void setLeft(int left) { + this.left = right = checkBounds(left, maxColumns); + } + + public int getLeft() { + return Math.min(left, right); + } + + private void setRight(int right) { + this.right = checkBounds(right, maxColumns); + } + + public int getRight() { + return Math.max(left, right); + } + + public String copyFrom(VDUBuffer vb) { + int size = (getRight() - getLeft() + 1) * (getBottom() - getTop() + 1); + StringBuffer buffer = new StringBuffer(size); + + for (int y = getTop(); y <= getBottom(); y++) { + int lastNonSpace = buffer.length(); + + for (int x = getLeft(); x <= getRight(); x++) { + // only copy printable chars + char c = vb.getChar(x, y); + + if (!Character.isDefined(c) || + (Character.isISOControl(c) && c != '\t')) + c = ' '; + + if (c != ' ') + lastNonSpace = buffer.length(); + + buffer.append(c); + } + + // Don't leave a bunch of spaces in our copy buffer. + if (buffer.length() > lastNonSpace) + buffer.delete(lastNonSpace + 1, buffer.length()); + + if (y != bottom) + buffer.append("\n"); + } + + return buffer.toString(); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("SelectionArea[top="); + buffer.append(top); + buffer.append(", bottom="); + buffer.append(bottom); + buffer.append(", left="); + buffer.append(left); + buffer.append(", right="); + buffer.append(right); + buffer.append(", maxColumns="); + buffer.append(maxColumns); + buffer.append(", maxRows="); + buffer.append(maxRows); + buffer.append(", isSelectingOrigin="); + buffer.append(isSelectingOrigin()); + buffer.append("]"); + return buffer.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/AuthAgentService.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,193 @@ +package com.five_ten_sg.connectbot.service; + +import java.io.IOException; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.service.TerminalManager.KeyHolder; +import android.app.Service; +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.madgag.ssh.android.authagent.AndroidAuthAgent; +import ch.ethz.ssh2.crypto.SecureRandomFix; +import ch.ethz.ssh2.signature.DSASHA1Verify; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; +import ch.ethz.ssh2.signature.RSASHA1Verify; + + +public class AuthAgentService extends Service { + private static final String TAG = "ConnectBot.AuthAgentService"; + protected TerminalManager manager; + final Lock lock = new ReentrantLock(); + final Condition managerReady = lock.newCondition(); + + private ServiceConnection connection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + Log.d(TAG, "Terminal manager available! Hurrah"); + manager = ((TerminalManager.TerminalBinder) service).getService(); + lock.lock(); + + try { + managerReady.signal(); + } + finally { + lock.unlock(); + } + } + public void onServiceDisconnected(ComponentName className) { + manager = null; + Log.d(TAG, "Terminal manager gone..."); + } + }; + + @Override + public IBinder onBind(Intent intent) { + Log.d(TAG, "onBind() called"); + bindService(new Intent(this, TerminalManager.class), connection, BIND_AUTO_CREATE); + return mBinder; + } + + private final AndroidAuthAgent.Stub mBinder = new AndroidAuthAgent.Stub() { + public Map getIdentities() throws RemoteException { + Log.d(TAG, "getIdentities() called"); + waitForTerminalManager(); + Log.d(TAG, "getIdentities() manager.loadedKeypairs : " + manager.loadedKeypairs); + return sshEncodedPubKeysFrom(manager.loadedKeypairs); + } + public byte[] sign(byte[] publicKey, byte[] data) throws RemoteException { + Log.d(TAG, "sign() called"); + waitForTerminalManager(); + KeyPair pair = keyPairFor(publicKey); + Log.d(TAG, "sign() - signing keypair found : " + pair); + + if (pair == null) { + return null; + } + + PrivateKey privKey = pair.getPrivate(); + + if (privKey instanceof RSAPrivateKey) { + return sshEncodedSignatureFor(data, (RSAPrivateKey) privKey); + } + else if (privKey instanceof DSAPrivateKey) { + return sshEncodedSignatureFor(data, (DSAPrivateKey) privKey); + } + else if (privKey instanceof ECPrivateKey) { + return sshEncodedSignatureFor(data, (ECPrivateKey) privKey); + } + + return null; + } + private void waitForTerminalManager() throws RemoteException { + lock.lock(); + + try { + while (manager == null) { + Log.d(TAG, "Waiting for TerminalManager..."); + managerReady.await(); + } + } + catch (InterruptedException e) { + throw new RemoteException(); + } + finally { + lock.unlock(); + } + + Log.d(TAG, "Got TerminalManager : " + manager); + } + private Map<String, byte[]> sshEncodedPubKeysFrom(Map<String, KeyHolder> keypairs) { + Map<String, byte[]> pubkeys = new HashMap<String, byte[]> (keypairs.size()); + + for (Entry<String, KeyHolder> entry : keypairs.entrySet()) { + byte[] encodedKey = sshEncodedPubKeyFrom(entry.getValue().pair); + + if (encodedKey != null) { + pubkeys.put(entry.getKey(), encodedKey); + } + } + + return pubkeys; + } + private byte[] sshEncodedPubKeyFrom(KeyPair pair) { + try { + PrivateKey privKey = pair.getPrivate(); + + if (privKey instanceof RSAPrivateKey) { + RSAPublicKey pubkey = (RSAPublicKey)pair.getPublic(); + return RSASHA1Verify.encodeSSHRSAPublicKey(pubkey); + } + else if (privKey instanceof DSAPrivateKey) { + DSAPublicKey pubkey = (DSAPublicKey)pair.getPublic(); + return DSASHA1Verify.encodeSSHDSAPublicKey(pubkey); + } + else if (privKey instanceof ECPrivateKey) { + ECPublicKey pubkey = (ECPublicKey) pair.getPublic(); + return ECDSASHA2Verify.encodeSSHECDSAPublicKey(pubkey); + } + } + catch (IOException e) { + Log.e(TAG, "Couldn't encode " + pair, e); + } + + return null; + } + private byte[] sshEncodedSignatureFor(byte[] data, RSAPrivateKey privKey) { + try { + byte[] signature = RSASHA1Verify.generateSignature(data, privKey); + return RSASHA1Verify.encodeSSHRSASignature(signature); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + private byte[] sshEncodedSignatureFor(byte[] data, DSAPrivateKey privKey) { + try { + byte[] signature = DSASHA1Verify.generateSignature(data, privKey, new SecureRandomFix()); + return DSASHA1Verify.encodeSSHDSASignature(signature); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + private byte[] sshEncodedSignatureFor(byte[] data, ECPrivateKey privKey) { + try { + byte[] signature = ECDSASHA2Verify.generateSignature(data, privKey); + return ECDSASHA2Verify.encodeSSHECDSASignature(signature, privKey.getParams()); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + private KeyPair keyPairFor(byte[] publicKey) { + String nickname = manager.getKeyNickname(publicKey); + + if (nickname == null) { + Log.w(TAG, "No key-pair found for public-key."); + return null; + } + + // check manager.loadedKeypairs.get(nickname).bean.isConfirmUse() and promptForPubkeyUse(nickname) ? + return manager.getKey(nickname); + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/BackupAgent.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,67 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2010 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.service; + +import java.io.IOException; + +import com.five_ten_sg.connectbot.util.HostDatabase; +import com.five_ten_sg.connectbot.util.PreferenceConstants; +import com.five_ten_sg.connectbot.util.PubkeyDatabase; +import android.app.backup.BackupAgentHelper; +import android.app.backup.BackupDataInput; +import android.app.backup.BackupDataOutput; +import android.app.backup.FileBackupHelper; +import android.app.backup.SharedPreferencesBackupHelper; +import android.os.ParcelFileDescriptor; +import android.util.Log; + +/** + * @author kroot + * + */ +public class BackupAgent extends BackupAgentHelper { + @Override + public void onCreate() { + Log.d("ConnectBot.BackupAgent", "onCreate called"); + SharedPreferencesBackupHelper prefs = new SharedPreferencesBackupHelper(this, getPackageName() + "_preferences"); + addHelper(PreferenceConstants.BACKUP_PREF_KEY, prefs); + FileBackupHelper hosts = new FileBackupHelper(this, "../databases/" + HostDatabase.DB_NAME); + addHelper(HostDatabase.DB_NAME, hosts); + FileBackupHelper pubkeys = new FileBackupHelper(this, "../databases/" + PubkeyDatabase.DB_NAME); + addHelper(PubkeyDatabase.DB_NAME, pubkeys); + } + + @Override + public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) throws IOException { + synchronized (HostDatabase.dbLock) { + super.onBackup(oldState, data, newState); + } + } + + @Override + public void onRestore(BackupDataInput data, int appVersionCode, + ParcelFileDescriptor newState) throws IOException { + Log.d("ConnectBot.BackupAgent", "onRestore called"); + + synchronized (HostDatabase.dbLock) { + Log.d("ConnectBot.BackupAgent", "onRestore in-lock"); + super.onRestore(data, appVersionCode, newState); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/BridgeDisconnectedListener.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,22 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.service; + +public interface BridgeDisconnectedListener { + public void onDisconnected(TerminalBridge bridge); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/ConnectionNotifier.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,113 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2010 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.service; + +import com.five_ten_sg.connectbot.ConsoleActivity; +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.util.HostDatabase; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.graphics.Color; + +/** + * @author Kenny Root + * + * Based on the concept from jasta's blog post. + */ +public class ConnectionNotifier { + private static final int ONLINE_NOTIFICATION = 1; + private static final int ACTIVITY_NOTIFICATION = 2; + + protected NotificationManager getNotificationManager(Context context) { + return (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); + } + + protected Notification newNotification(Context context) { + Notification notification = new Notification(); + notification.icon = R.drawable.notification_icon; + notification.when = System.currentTimeMillis(); + return notification; + } + + protected Notification newActivityNotification(Context context, HostBean host) { + Notification notification = newNotification(context); + Resources res = context.getResources(); + String contentText = res.getString( + R.string.notification_text, host.getNickname()); + Intent notificationIntent = new Intent(context, ConsoleActivity.class); + notificationIntent.setAction(Intent.ACTION_VIEW); + notificationIntent.setData(host.getUri()); + PendingIntent contentIntent = PendingIntent.getActivity(context, 0, + notificationIntent, 0); + notification.setLatestEventInfo(context, res.getString(R.string.app_name), contentText, contentIntent); + notification.flags = Notification.FLAG_AUTO_CANCEL; + notification.flags |= Notification.DEFAULT_LIGHTS; + + if (HostDatabase.COLOR_RED.equals(host.getColor())) + notification.ledARGB = Color.RED; + else if (HostDatabase.COLOR_GREEN.equals(host.getColor())) + notification.ledARGB = Color.GREEN; + else if (HostDatabase.COLOR_BLUE.equals(host.getColor())) + notification.ledARGB = Color.BLUE; + else + notification.ledARGB = Color.WHITE; + + notification.ledOnMS = 300; + notification.ledOffMS = 1000; + notification.flags |= Notification.FLAG_SHOW_LIGHTS; + return notification; + } + + protected Notification newRunningNotification(Context context) { + Notification notification = newNotification(context); + notification.flags = Notification.FLAG_ONGOING_EVENT + | Notification.FLAG_NO_CLEAR; + notification.when = 0; + notification.contentIntent = PendingIntent.getActivity(context, + ONLINE_NOTIFICATION, + new Intent(context, ConsoleActivity.class), 0); + Resources res = context.getResources(); + notification.setLatestEventInfo(context, + res.getString(R.string.app_name), + res.getString(R.string.app_is_running), + notification.contentIntent); + return notification; + } + + public void showActivityNotification(Service context, HostBean host) { + getNotificationManager(context).notify(ACTIVITY_NOTIFICATION, newActivityNotification(context, host)); + } + + public void hideActivityNotification(Service context) { + getNotificationManager(context).cancel(ACTIVITY_NOTIFICATION); + } + + public void showRunningNotification(Service context) { + context.startForeground(ONLINE_NOTIFICATION, newRunningNotification(context)); + } + + public void hideRunningNotification(Service context) { + context.stopForeground(true); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/ConnectivityReceiver.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,150 @@ +/** + * + */ +package com.five_ten_sg.connectbot.service; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.NetworkInfo.State; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiManager.WifiLock; +import android.util.Log; + +/** + * @author kroot + * + */ +public class ConnectivityReceiver extends BroadcastReceiver { + private static final String TAG = "ConnectBot.ConnectivityManager"; + + private boolean mIsConnected = false; + + final private TerminalManager mTerminalManager; + + final private WifiLock mWifiLock; + + private int mNetworkRef = 0; + + private boolean mLockingWifi; + + private Object[] mLock = new Object[0]; + + public ConnectivityReceiver(TerminalManager manager, boolean lockingWifi) { + mTerminalManager = manager; + final ConnectivityManager cm = + (ConnectivityManager) manager.getSystemService(Context.CONNECTIVITY_SERVICE); + final WifiManager wm = (WifiManager) manager.getSystemService(Context.WIFI_SERVICE); + mWifiLock = wm.createWifiLock(TAG); + final NetworkInfo info = cm.getActiveNetworkInfo(); + + if (info != null) { + mIsConnected = (info.getState() == State.CONNECTED); + } + + mLockingWifi = lockingWifi; + final IntentFilter filter = new IntentFilter(); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + manager.registerReceiver(this, filter); + } + + /* (non-Javadoc) + * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent) + */ + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + + if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + Log.w(TAG, "onReceived() called: " + intent); + return; + } + + boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); + boolean isFailover = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false); + Log.d(TAG, "onReceived() called; noConnectivity? " + noConnectivity + "; isFailover? " + isFailover); + + if (noConnectivity && !isFailover && mIsConnected) { + mIsConnected = false; + mTerminalManager.onConnectivityLost(); + } + else if (!mIsConnected) { + NetworkInfo info = (NetworkInfo) intent.getExtras() + .get(ConnectivityManager.EXTRA_NETWORK_INFO); + + if (mIsConnected = (info.getState() == State.CONNECTED)) { + mTerminalManager.onConnectivityRestored(); + } + } + } + + /** + * + */ + public void cleanup() { + if (mWifiLock.isHeld()) + mWifiLock.release(); + + mTerminalManager.unregisterReceiver(this); + } + + /** + * Increase the number of things using the network. Acquire a Wi-Fi lock + * if necessary. + */ + public void incRef() { + synchronized (mLock) { + mNetworkRef += 1; + acquireWifiLockIfNecessaryLocked(); + } + } + + /** + * Decrease the number of things using the network. Release the Wi-Fi lock + * if necessary. + */ + public void decRef() { + synchronized (mLock) { + mNetworkRef -= 1; + releaseWifiLockIfNecessaryLocked(); + } + } + + /** + * @param mLockingWifi + */ + public void setWantWifiLock(boolean lockingWifi) { + synchronized (mLock) { + mLockingWifi = lockingWifi; + + if (mLockingWifi) { + acquireWifiLockIfNecessaryLocked(); + } + else { + releaseWifiLockIfNecessaryLocked(); + } + } + } + + private void acquireWifiLockIfNecessaryLocked() { + if (mLockingWifi && mNetworkRef > 0 && !mWifiLock.isHeld()) { + mWifiLock.acquire(); + } + } + + private void releaseWifiLockIfNecessaryLocked() { + if (mNetworkRef == 0 && mWifiLock.isHeld()) { + mWifiLock.release(); + } + } + + /** + * @return whether we're connected to a network + */ + public boolean isConnected() { + return mIsConnected; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/FontSizeChangedListener.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,31 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.service; + +/** + * @author Kenny Root + * + */ +public interface FontSizeChangedListener { + + /** + * @param size + * new font size + */ + void onFontSizeChanged(float size); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/PromptHelper.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,184 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.service; + +import java.util.concurrent.Semaphore; + +import android.os.Handler; +import android.os.Message; + +/** + * Helps provide a relay for prompts and responses between a possible user + * interface and some underlying service. + * + * @author jsharkey + */ +public class PromptHelper { + private final Object tag; + + private Handler handler = null; + + private Semaphore promptToken; + private Semaphore promptResponse; + + public String promptInstructions = null; + public String promptHint = null; + public Object promptRequested = null; + public boolean passwordRequested = true; + + private Object response = null; + + public PromptHelper(Object tag) { + this.tag = tag; + // Threads must acquire this before they can send a prompt. + promptToken = new Semaphore(1); + // Responses will release this semaphore. + promptResponse = new Semaphore(0); + } + + + /** + * Register a user interface handler, if available. + */ + public void setHandler(Handler handler) { + this.handler = handler; + } + + /** + * Set an incoming value from an above user interface. Will automatically + * notify any waiting requests. + */ + public void setResponse(Object value) { + response = value; + promptRequested = null; + promptInstructions = null; + promptHint = null; + promptResponse.release(); + } + + /** + * Return the internal response value just before erasing and returning it. + */ + protected Object popResponse() { + Object value = response; + response = null; + return value; + } + + + /** + * Request a prompt response from parent. This is a blocking call until user + * interface returns a value. + * Only one thread can call this at a time. cancelPrompt() will force this to + * immediately return. + */ + private Object requestPrompt(String instructions, String hint, Object type) throws InterruptedException { + Object response = null; + promptToken.acquire(); + + try { + promptInstructions = instructions; + promptHint = hint; + promptRequested = type; + + // notify any parent watching for live events + if (handler != null) + Message.obtain(handler, -1, tag).sendToTarget(); + + // acquire lock until user passes back value + promptResponse.acquire(); + response = popResponse(); + } + finally { + promptToken.release(); + } + + return response; + } + + /** + * Request a string response from parent. This is a blocking call until user + * interface returns a value. + * @param hint prompt hint for user to answer + * @return string user has entered + */ + public String requestStringPrompt(String instructions, String hint) { + String value = null; + passwordRequested = false; + + try { + value = (String)this.requestPrompt(instructions, hint, String.class); + } + catch (Exception e) { + } + + return value; + } + + /** + * Request a password response from parent. This is a blocking call until user + * interface returns a value. + * @param hint prompt hint for user to answer + * @return string user has entered + */ + public String requestPasswordPrompt(String instructions, String hint) { + String value = null; + passwordRequested = true; + + try { + value = (String)this.requestPrompt(instructions, hint, String.class); + } + catch (Exception e) { + } + + return value; + } + + /** + * Request a boolean response from parent. This is a blocking call until user + * interface returns a value. + * @param hint prompt hint for user to answer + * @return choice user has made (yes/no) + */ + public Boolean requestBooleanPrompt(String instructions, String hint) { + Boolean value = null; + + try { + value = (Boolean)this.requestPrompt(instructions, hint, Boolean.class); + } + catch (Exception e) { + } + + return value; + } + + /** + * Cancel an in-progress prompt. + */ + public void cancelPrompt() { + if (!promptToken.tryAcquire()) { + // A thread has the token, so try to interrupt it + response = null; + promptResponse.release(); + } + else { + // No threads have acquired the token + promptToken.release(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/Relay.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,167 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.service; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; +import java.util.Timer; +import java.util.TimerTask; + +import org.apache.harmony.niochar.charset.additional.IBM437; + +import com.five_ten_sg.connectbot.transport.AbsTransport; +import android.graphics.Paint; +import android.text.AndroidCharacter; +import android.util.Log; +import de.mud.terminal.vt320; + +/** + * @author Kenny Root + */ +public class Relay implements Runnable { + private static final String TAG = "ConnectBot.Relay"; + + private static final int BUFFER_SIZE = 4096; + + private TerminalBridge bridge; + + private Charset currentCharset; + private CharsetDecoder decoder; + + private AbsTransport transport; + + private vt320 buffer; + + private ByteBuffer byteBuffer; + private CharBuffer charBuffer; + + private byte[] byteArray; + private char[] charArray; + + private void eastAsianWidthMeasure(char[] charArray, int start, int end, + byte[] wideAttribute, Paint paint, int charWidth) { + AndroidCharacter.getEastAsianWidths(charArray, start, end - start, wideAttribute); + } + + public Relay(TerminalBridge bridge, AbsTransport transport, vt320 buffer, String encoding) { + setCharset(encoding); + this.bridge = bridge; + this.transport = transport; + this.buffer = buffer; + } + + public void setCharset(String encoding) { + Log.d("ConnectBot.Relay", "changing charset to " + encoding); + Charset charset; + + if (encoding.equals("CP437")) + charset = new IBM437("IBM437", + new String[] { "IBM437", "CP437" }); + else + charset = Charset.forName(encoding); + + if (charset == currentCharset || charset == null) + return; + + CharsetDecoder newCd = charset.newDecoder(); + newCd.onUnmappableCharacter(CodingErrorAction.REPLACE); + newCd.onMalformedInput(CodingErrorAction.REPLACE); + currentCharset = charset; + + synchronized (this) { + decoder = newCd; + } + } + + public Charset getCharset() { + return currentCharset; + } + + public void run() { + byteBuffer = ByteBuffer.allocate(BUFFER_SIZE); + charBuffer = CharBuffer.allocate(BUFFER_SIZE); + /* for East Asian character widths */ + byte[] wideAttribute = new byte[BUFFER_SIZE]; + byteArray = byteBuffer.array(); + charArray = charBuffer.array(); + CoderResult result; + int bytesRead = 0; + byteBuffer.limit(0); + int bytesToRead; + int offset; + int charWidth; + Timer timer = new Timer("relay.blocker", true); + TimerTask task = null; + + try { + while (true) { + charWidth = bridge.charWidth; + bytesToRead = byteBuffer.capacity() - byteBuffer.limit(); + offset = byteBuffer.arrayOffset() + byteBuffer.limit(); + + if (transport.willBlock()) { + task = new TimerTask() { + public void run() { + buffer.testChanged(); + } + }; + timer.schedule(task, 10); // 10 ms delay + } + + bytesRead = transport.read(byteArray, offset, bytesToRead); + + if (task != null) { + task.cancel(); + task = null; + } + + if (bytesRead > 0) { + byteBuffer.limit(byteBuffer.limit() + bytesRead); + + synchronized (this) { + result = decoder.decode(byteBuffer, charBuffer, false); + } + + if (result.isUnderflow() && + byteBuffer.limit() == byteBuffer.capacity()) { + byteBuffer.compact(); + byteBuffer.limit(byteBuffer.position()); + byteBuffer.position(0); + } + + offset = charBuffer.position(); + eastAsianWidthMeasure(charArray, 0, offset, wideAttribute, bridge.defaultPaint, charWidth); + buffer.putString(charArray, wideAttribute, 0, charBuffer.position()); + bridge.propagateConsoleText(charArray, charBuffer.position()); + charBuffer.clear(); + bridge.redraw(); + } + } + } + catch (IOException e) { + Log.e(TAG, "Problem while handling incoming data in relay thread", e); + } + + timer.cancel(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/TerminalBridge.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1412 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.service; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.TerminalView; +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.bean.PortForwardBean; +import com.five_ten_sg.connectbot.bean.SelectionArea; +import com.five_ten_sg.connectbot.transport.AbsTransport; +import com.five_ten_sg.connectbot.transport.TransportFactory; +import com.five_ten_sg.connectbot.util.HostDatabase; +import com.five_ten_sg.connectbot.util.PreferenceConstants; +import com.five_ten_sg.connectbot.util.StringPickerDialog; +import android.app.AlertDialog; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.FontMetrics; +import android.graphics.Typeface; +import android.os.Binder; +import android.os.Environment; +import android.text.ClipboardManager; +import android.text.Editable; +import android.text.method.CharacterPickerDialog; +import android.util.FloatMath; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Button; +import de.mud.terminal.VDUBuffer; +import de.mud.terminal.VDUDisplay; +import de.mud.terminal.vt320; + + +/** + * Provides a bridge between a MUD terminal buffer and a possible TerminalView. + * This separation allows us to keep the TerminalBridge running in a background + * service. A TerminalView shares down a bitmap that we can use for rendering + * when available. + * + * This class also provides SSH hostkey verification prompting, and password + * prompting. + */ +@SuppressWarnings("deprecation") // for ClipboardManager +public class TerminalBridge implements VDUDisplay { + public final static String TAG = "ConnectBot.TerminalBridge"; + + private final static float FONT_SIZE_FACTOR = 1.1f; + + public Integer[] color; + + public int defaultFg = HostDatabase.DEFAULT_FG_COLOR; + public int defaultBg = HostDatabase.DEFAULT_BG_COLOR; + + protected final TerminalManager manager; + public final HostBean host; + public final String homeDirectory; + + AbsTransport transport; + + final Paint defaultPaint; + + private Relay relay; + + private String emulation; // aka answerback string, aka terminal type + + public Bitmap bitmap = null; + public vt320 buffer = null; + + public TerminalView parent = null; + private final Canvas canvas = new Canvas(); + + private boolean disconnected = false; + private boolean awaitingClose = false; + + private boolean forcedSize = false; + private int columns; + private int rows; + + public TerminalMonitor monitor = null; + private TerminalKeyListener keyListener = null; + + private boolean selectingForCopy = false; + private final SelectionArea selectionArea; + + // TODO add support for the new clipboard API + private ClipboardManager clipboard; + + public int charWidth = -1; + public int charHeight = -1; + private int charTop = -1; + private float fontSize = -1; + + private final List<FontSizeChangedListener> fontSizeChangedListeners; + + private final List<String> localOutput; + + /** + * Flag indicating if we should perform a full-screen redraw during our next + * rendering pass. + */ + private boolean fullRedraw = false; + + public PromptHelper promptHelper; + + protected BridgeDisconnectedListener disconnectListener = null; + + /** + * Create a new terminal bridge suitable for unit testing. + */ + public TerminalBridge() { + buffer = new vt320() { + @Override + public void write(byte[] b) {} + @Override + public void write(int b) {} + @Override + public void sendTelnetCommand(byte cmd) {} + @Override + public void setWindowSize(int c, int r) {} + @Override + public void debug(String s) {} + }; + emulation = null; + manager = null; + host = null; + homeDirectory = null; + defaultPaint = new Paint(); + selectionArea = new SelectionArea(); + localOutput = new LinkedList<String>(); + fontSizeChangedListeners = new LinkedList<FontSizeChangedListener>(); + transport = null; + keyListener = new TerminalKeyListener(manager, this, buffer, null); + monitor = null; + } + + /** + * Create new terminal bridge with following parameters. + */ + public TerminalBridge(final TerminalManager manager, final HostBean host, final String homeDirectory) throws IOException { + this.manager = manager; + this.host = host; + this.homeDirectory = homeDirectory; + emulation = host.getHostEmulation(); + + if ((emulation == null) || (emulation.length() == 0)) emulation = manager.getEmulation(); + + // create prompt helper to relay password and hostkey requests up to gui + promptHelper = new PromptHelper(this); + // create our default paint + defaultPaint = new Paint(); + defaultPaint.setAntiAlias(true); + defaultPaint.setTypeface(Typeface.MONOSPACE); + defaultPaint.setFakeBoldText(true); // more readable? + localOutput = new LinkedList<String>(); + fontSizeChangedListeners = new LinkedList<FontSizeChangedListener>(); + setMyFontSize(); + resetColors(); + selectionArea = new SelectionArea(); + } + + public PromptHelper getPromptHelper() { + return promptHelper; + } + + /** + * Spawn thread to open connection and start login process. + */ + protected void startConnection() { + transport = TransportFactory.getTransport(host.getProtocol()); + transport.setLinks(manager, this, homeDirectory, host, emulation); + buffer = transport.getTransportBuffer(); + keyListener = transport.getTerminalKeyListener(); + String monitor_init = host.getMonitor(); + + if ((monitor_init != null) && (monitor_init.length() > 0)) { + monitor = new TerminalMonitor(manager, buffer, parent, host, monitor_init); + } + + transport.setCompression(host.getCompression()); + transport.setHttpproxy(host.getHttpproxy()); + transport.setUseAuthAgent(host.getUseAuthAgent()); + + if (transport.canForwardPorts()) { + for (PortForwardBean portForward : manager.hostdb.getPortForwardsForHost(host)) + transport.addPortForward(portForward); + } + + outputLine(manager.res.getString(R.string.terminal_connecting, host.getHostname(), host.getPort(), host.getProtocol())); + Thread connectionThread = new Thread(new Runnable() { + public void run() { + transport.connect(); + } + }); + connectionThread.setName("Connection"); + connectionThread.setDaemon(true); + connectionThread.start(); + } + + /** + * Handle challenges from keyboard-interactive authentication mode. + */ + public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) { + String[] responses = new String[numPrompts]; + + for (int i = 0; i < numPrompts; i++) { + // request response from user for each prompt + responses[i] = promptHelper.requestPasswordPrompt(instruction, prompt[i]); + } + + return responses; + } + + /** + * @return charset in use by bridge + */ + public Charset getCharset() { + if (relay != null) return relay.getCharset(); + + return keyListener.getCharset(); + } + + /** + * Sets the encoding used by the terminal. If the connection is live, + * then the character set is changed for the next read. + * @param encoding the canonical name of the character encoding + */ + public void setCharset(String encoding) { + if (relay != null) relay.setCharset(encoding); + + keyListener.setCharset(encoding); + } + + /** + * Convenience method for writing a line into the underlying MUD buffer. + * Should never be called once the session is established. + */ + public final void outputLine(String line) { + if (transport != null && transport.isSessionOpen()) + Log.e(TAG, "Session established, cannot use outputLine!", new IOException("outputLine call traceback")); + + synchronized (localOutput) { + final String s = line + "\r\n"; + localOutput.add(s); + buffer.putString(s); + // For accessibility + final char[] charArray = s.toCharArray(); + propagateConsoleText(charArray, charArray.length); + } + } + + /** + * Inject a specific string into this terminal. Used for post-login strings + * and pasting clipboard. + */ + public void injectString(final String string) { + if (string == null || string.length() == 0) + return; + + Thread injectStringThread = new Thread(new Runnable() { + public void run() { + try { + transport.write(string.getBytes(host.getEncoding())); + } + catch (Exception e) { + Log.e(TAG, "Couldn't inject string to remote host: ", e); + } + } + }); + injectStringThread.setName("InjectString"); + injectStringThread.start(); + } + + /** + * Internal method to request actual PTY terminal once we've finished + * authentication. If called before authenticated, it will just fail. + */ + public void onConnected() { + disconnected = false; + buffer.reset(); + buffer.setAnswerBack(emulation); + localOutput.clear(); // We no longer need our local output. + + if (HostDatabase.DELKEY_BACKSPACE.equals(host.getDelKey())) + buffer.setBackspace(vt320.DELETE_IS_BACKSPACE); + else + buffer.setBackspace(vt320.DELETE_IS_DEL); + + // create thread to relay incoming connection data to buffer + // only if needed by the transport + if (transport.needsRelay()) { + relay = new Relay(this, transport, buffer, host.getEncoding()); + Thread relayThread = new Thread(relay); + relayThread.setDaemon(true); + relayThread.setName("Relay"); + relayThread.start(); + } + + // get proper font size + setMyFontSize(); + // finally send any post-login string, if requested + injectString(host.getPostLogin()); + } + + private void setMyFontSize() { + if ((parent != null) && (host.getFixedSize())) { + resizeComputed(host.getFixedWidth(), host.getFixedHeight(), parent.getWidth(), parent.getHeight()); + } + else { + setFontSize(host.getFontSize()); + } + } + + /** + * @return whether a session is open or not + */ + public boolean isSessionOpen() { + if (transport != null) return transport.isSessionOpen(); + + return false; + } + + public void setOnDisconnectedListener(BridgeDisconnectedListener disconnectListener) { + this.disconnectListener = disconnectListener; + } + + /** + * Force disconnection of this terminal bridge. + */ + public void dispatchDisconnect(boolean immediate) { + // We don't need to do this multiple times. + synchronized (this) { + if (disconnected && !immediate) return; + + disconnected = true; + } + + // Cancel any pending prompts. + promptHelper.cancelPrompt(); + // disconnection request hangs if we havent really connected to a host yet + // temporary fix is to just spawn disconnection into a thread + Thread disconnectThread = new Thread(new Runnable() { + public void run() { + if (transport != null && transport.isConnected()) + transport.close(); + } + }); + disconnectThread.setName("Disconnect"); + disconnectThread.start(); + + if (immediate) { + awaitingClose = true; + + if (disconnectListener != null) + disconnectListener.onDisconnected(TerminalBridge.this); + } + else { + final String line = manager.res.getString(R.string.alert_disconnect_msg); + buffer.putString("\r\n" + line + "\r\n"); + + if (host.getStayConnected()) { + manager.requestReconnect(this); + return; + } + + Thread disconnectPromptThread = new Thread(new Runnable() { + public void run() { + Boolean result = promptHelper.requestBooleanPrompt(null, + manager.res.getString(R.string.prompt_host_disconnected)); + + if (result == null || result.booleanValue()) { + awaitingClose = true; + + // Tell the TerminalManager that we can be destroyed now. + if (disconnectListener != null) + disconnectListener.onDisconnected(TerminalBridge.this); + } + } + }); + disconnectPromptThread.setName("DisconnectPrompt"); + disconnectPromptThread.setDaemon(true); + disconnectPromptThread.start(); + } + + // close the monitor + if (monitor != null) monitor.Disconnect(); + + monitor = null; + } + + public void setSelectingForCopy(boolean selectingForCopy) { + this.selectingForCopy = selectingForCopy; + } + + public boolean isSelectingForCopy() { + return selectingForCopy; + } + + public SelectionArea getSelectionArea() { + return selectionArea; + } + + public synchronized void tryKeyVibrate() { + manager.tryKeyVibrate(); + } + + /** + * Request a different font size. Will make call to parentChanged() to make + * sure we resize PTY if needed. + */ + final void setFontSize(float size) { + if (size <= 0.0) size = 12.0f; + + size = (float)(int)((size * 10.0f) + 0.5f) / 10.0f; + defaultPaint.setTextSize(size); + fontSize = size; + // read new metrics to get exact pixel dimensions + FontMetrics fm = defaultPaint.getFontMetrics(); + charTop = (int)FloatMath.ceil(fm.top); + float[] widths = new float[1]; + defaultPaint.getTextWidths("X", widths); + charWidth = (int)FloatMath.ceil(widths[0]); + charHeight = (int)FloatMath.ceil(fm.descent - fm.top); + + // refresh any bitmap with new font size + if (parent != null) parentChanged(parent); + + synchronized(fontSizeChangedListeners) { + for (FontSizeChangedListener ofscl : fontSizeChangedListeners) + ofscl.onFontSizeChanged(size); + } + + host.setFontSize(size); + manager.hostdb.updateFontSize(host); + } + + /** + * Add an {@link FontSizeChangedListener} to the list of listeners for this + * bridge. + * + * @param listener + * listener to add + */ + public void addFontSizeChangedListener(FontSizeChangedListener listener) { + synchronized(fontSizeChangedListeners) { + fontSizeChangedListeners.add(listener); + } + } + + /** + * Remove an {@link FontSizeChangedListener} from the list of listeners for + * this bridge. + * + * @param listener + */ + public void removeFontSizeChangedListener(FontSizeChangedListener listener) { + synchronized(fontSizeChangedListeners) { + fontSizeChangedListeners.remove(listener); + } + } + + /** + * Something changed in our parent {@link TerminalView}, maybe it's a new + * parent, or maybe it's an updated font size. We should recalculate + * terminal size information and request a PTY resize. + */ + + public final synchronized void parentChanged(TerminalView parent) { + if (manager != null && !manager.isResizeAllowed()) { + Log.d(TAG, "Resize is not allowed now"); + return; + } + + this.parent = parent; + final int width = parent.getWidth(); + final int height = parent.getHeight(); + + // Something has gone wrong with our layout; we're 0 width or height! + if (width <= 0 || height <= 0) + return; + + clipboard = (ClipboardManager) parent.getContext().getSystemService(Context.CLIPBOARD_SERVICE); + keyListener.setClipboardManager(clipboard); + + if (!forcedSize) { + // recalculate buffer size + int newColumns, newRows; + newColumns = width / charWidth; + newRows = height / charHeight; + + // If nothing has changed in the terminal dimensions and not an intial + // draw then don't blow away scroll regions and such. + if (newColumns == columns && newRows == rows) + return; + + columns = newColumns; + rows = newRows; + } + + // reallocate new bitmap if needed + boolean newBitmap = (bitmap == null); + + if (bitmap != null) + newBitmap = (bitmap.getWidth() != width || bitmap.getHeight() != height); + + if (newBitmap) { + discardBitmap(); + bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); + canvas.setBitmap(bitmap); + } + + // clear out any old buffer information + defaultPaint.setColor(Color.BLACK); + canvas.drawPaint(defaultPaint); + + // Stroke the border of the terminal if the size is being forced; + if (forcedSize) { + int borderX = (columns * charWidth) + 1; + int borderY = (rows * charHeight) + 1; + defaultPaint.setColor(Color.GRAY); + defaultPaint.setStrokeWidth(0.0f); + + if (width >= borderX) + canvas.drawLine(borderX, 0, borderX, borderY + 1, defaultPaint); + + if (height >= borderY) + canvas.drawLine(0, borderY, borderX + 1, borderY, defaultPaint); + } + + try { + // request a terminal pty resize + if (buffer != null) { + synchronized (buffer) { + buffer.setScreenSize(columns, rows, true); + } + } + + if (transport != null) + transport.setDimensions(columns, rows, width, height); + } + catch (Exception e) { + Log.e(TAG, "Problem while trying to resize screen or PTY", e); + } + + // redraw local output if we don't have a session to receive our resize request + if (transport == null) { + synchronized (localOutput) { + buffer.reset(); + + for (String line : localOutput) + buffer.putString(line); + } + } + + // force full redraw with new buffer size + fullRedraw = true; + redraw(); + + // initial sequence from + // transport.connect() + // bridge.onConnected() + // bridge.setMyFontSize() + // bridge.resizeComputed() + // bridge.setFontSize() + // bridge.parentChanged() here is on the wrong thread + try { + parent.notifyUser(String.format("%d x %d", columns, rows)); + } + catch (Exception e) { + Log.e(TAG, "Problem while trying to notify user", e); + } + + Log.i(TAG, String.format("parentChanged() now width=%d, height=%d", columns, rows)); + } + + /** + * Somehow our parent {@link TerminalView} was destroyed. Now we don't need + * to redraw anywhere, and we can recycle our internal bitmap. + */ + + public synchronized void parentDestroyed() { + parent = null; + discardBitmap(); + } + + private void discardBitmap() { + if (bitmap != null) + bitmap.recycle(); + + bitmap = null; + } + + public void propagateConsoleText(char[] rawText, int length) { + if (parent != null) { + parent.propagateConsoleText(rawText, length); + } + } + + public void onDraw() { + int fg, bg; + + synchronized (buffer) { + boolean entireDirty = buffer.update[0] || fullRedraw; + boolean isWideCharacter = false; + + // walk through all lines in the buffer + for (int l = 0; l < buffer.height; l++) { + // check if this line is dirty and needs to be repainted + // also check for entire-buffer dirty flags + if (!entireDirty && !buffer.update[l + 1]) continue; + + // reset dirty flag for this line + buffer.update[l + 1] = false; + + // walk through all characters in this line + for (int c = 0; c < buffer.width; c++) { + int addr = 0; + int currAttr = buffer.charAttributes[buffer.windowBase + l][c]; + { + int fgcolor = defaultFg; + + // check if foreground color attribute is set + if ((currAttr & VDUBuffer.COLOR_FG) != 0) + fgcolor = ((currAttr & VDUBuffer.COLOR_FG) >> VDUBuffer.COLOR_FG_SHIFT) - 1; + + if (fgcolor < 8 && (currAttr & VDUBuffer.BOLD) != 0) + fg = color[fgcolor + 8]; + else + fg = color[fgcolor]; + } + + // check if background color attribute is set + if ((currAttr & VDUBuffer.COLOR_BG) != 0) + bg = color[((currAttr & VDUBuffer.COLOR_BG) >> VDUBuffer.COLOR_BG_SHIFT) - 1]; + else + bg = color[defaultBg]; + + // support character inversion by swapping background and foreground color + if ((currAttr & VDUBuffer.INVERT) != 0) { + int swapc = bg; + bg = fg; + fg = swapc; + } + + // set underlined attributes if requested + defaultPaint.setUnderlineText((currAttr & VDUBuffer.UNDERLINE) != 0); + isWideCharacter = (currAttr & VDUBuffer.FULLWIDTH) != 0; + + if (isWideCharacter) + addr++; + else { + // determine the amount of continuous characters with the same settings and print them all at once + while (c + addr < buffer.width + && buffer.charAttributes[buffer.windowBase + l][c + addr] == currAttr) { + addr++; + } + } + + // Save the current clip region + canvas.save(Canvas.CLIP_SAVE_FLAG); + // clear this dirty area with background color + defaultPaint.setColor(bg); + + if (isWideCharacter) { + canvas.clipRect(c * charWidth, + l * charHeight, + (c + 2) * charWidth, + (l + 1) * charHeight); + } + else { + canvas.clipRect(c * charWidth, + l * charHeight, + (c + addr) * charWidth, + (l + 1) * charHeight); + } + + canvas.drawPaint(defaultPaint); + // write the text string starting at 'c' for 'addr' number of characters + defaultPaint.setColor(fg); + + if ((currAttr & VDUBuffer.INVISIBLE) == 0) + canvas.drawText(buffer.charArray[buffer.windowBase + l], c, + addr, c * charWidth, (l * charHeight) - charTop, + defaultPaint); + + // Restore the previous clip region + canvas.restore(); + // advance to the next text block with different characteristics + c += addr - 1; + + if (isWideCharacter) + c++; + } + } + + // reset entire-buffer flags + buffer.update[0] = false; + } + + fullRedraw = false; + } + + public void redraw() { + if (parent != null) + parent.postInvalidate(); + } + + // We don't have a scroll bar. + public void updateScrollBar() { + } + + /** + * Resize terminal to fit [rows]x[cols] in screen of size [width]x[height] + * @param rows + * @param cols + * @param width + * @param height + */ + + public synchronized void resizeComputed(int cols, int rows, int width, int height) { + float size = 8.0f; + float step = 8.0f; + float limit = 0.125f; + int direction; + boolean fixed = true; + + if (!fixed) { + while ((direction = fontSizeCompare(size, cols, rows, width, height)) < 0) + size += step; + + if (direction == 0) { + Log.d("fontsize", String.format("Found match at %f", size)); + return; + } + + step /= 2.0f; + size -= step; + + while ((direction = fontSizeCompare(size, cols, rows, width, height)) != 0 + && step >= limit) { + step /= 2.0f; + + if (direction > 0) { + size -= step; + } + else { + size += step; + } + } + + if (direction > 0) size -= step; + } + + this.columns = cols; + this.rows = rows; + forcedSize = true; + + if (fixed) setFontSize(host.getFontSize()); + else setFontSize(size); + } + + private int fontSizeCompare(float size, int cols, int rows, int width, int height) { + // read new metrics to get exact pixel dimensions + defaultPaint.setTextSize(size); + FontMetrics fm = defaultPaint.getFontMetrics(); + float[] widths = new float[1]; + defaultPaint.getTextWidths("X", widths); + int termWidth = (int)widths[0] * cols; + int termHeight = (int)FloatMath.ceil(fm.descent - fm.top) * rows; + Log.d("fontsize", String.format("font size %f resulted in %d x %d", size, termWidth, termHeight)); + + // Check to see if it fits in resolution specified. + if (termWidth > width || termHeight > height) + return 1; + + if (termWidth == width || termHeight == height) + return 0; + + return -1; + } + + /** + * @return whether underlying transport can forward ports + */ + public boolean canFowardPorts() { + return transport.canForwardPorts(); + } + + /** + * Adds the {@link PortForwardBean} to the list. + * @param portForward the port forward bean to add + * @return true on successful addition + */ + public boolean addPortForward(PortForwardBean portForward) { + return transport.addPortForward(portForward); + } + + /** + * Removes the {@link PortForwardBean} from the list. + * @param portForward the port forward bean to remove + * @return true on successful removal + */ + public boolean removePortForward(PortForwardBean portForward) { + return transport.removePortForward(portForward); + } + + /** + * @return the list of port forwards + */ + public List<PortForwardBean> getPortForwards() { + return transport.getPortForwards(); + } + + /** + * Enables a port forward member. After calling this method, the port forward should + * be operational. + * @param portForward member of our current port forwards list to enable + * @return true on successful port forward setup + */ + public boolean enablePortForward(PortForwardBean portForward) { + if (!transport.isConnected()) { + Log.i(TAG, "Attempt to enable port forward while not connected"); + return false; + } + + return transport.enablePortForward(portForward); + } + + /** + * Disables a port forward member. After calling this method, the port forward should + * be non-functioning. + * @param portForward member of our current port forwards list to enable + * @return true on successful port forward tear-down + */ + public boolean disablePortForward(PortForwardBean portForward) { + if (!transport.isConnected()) { + Log.i(TAG, "Attempt to disable port forward while not connected"); + return false; + } + + return transport.disablePortForward(portForward); + } + + /** + * @return whether underlying transport can transfer files + */ + public boolean canTransferFiles() { + return transport.canTransferFiles(); + } + + /** + * Downloads the specified remote file to the local connectbot folder. + * @return true on success, false on failure + */ + public boolean downloadFile(String remoteFile, String localFolder) { + return transport.downloadFile(remoteFile, localFolder); + } + + /** + * Uploads the specified local file to the remote host's default directory. + * @return true on success, false on failure + */ + public boolean uploadFile(String localFile, String remoteFolder, String remoteFile, String mode) { + if (mode == null) + mode = "0600"; + + return transport.uploadFile(localFile, remoteFolder, remoteFile, mode); + } + + /** + * @return whether the TerminalBridge should close + */ + public boolean isAwaitingClose() { + return awaitingClose; + } + + /** + * @return whether this connection had started and subsequently disconnected + */ + public boolean isDisconnected() { + return disconnected; + } + + /* (non-Javadoc) + * @see de.mud.terminal.VDUDisplay#setColor(byte, byte, byte, byte) + */ + public void setColor(int index, int red, int green, int blue) { + // Don't allow the system colors to be overwritten for now. May violate specs. + if (index < color.length && index >= 16) + color[index] = 0xff000000 | red << 16 | green << 8 | blue; + } + + public final void resetColors() { + int[] defaults = manager.hostdb.getDefaultColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME); + defaultFg = defaults[0]; + defaultBg = defaults[1]; + color = manager.hostdb.getColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME); + } + + private static Pattern urlPattern = null; + + /** + * @return + */ + public List<String> scanForURLs() { + Set<String> urls = new LinkedHashSet<String>(); + + if (urlPattern == null) { + // based on http://www.ietf.org/rfc/rfc2396.txt + String scheme = "[A-Za-z][-+.0-9A-Za-z]*"; + String unreserved = "[-._~0-9A-Za-z]"; + String pctEncoded = "%[0-9A-Fa-f]{2}"; + String subDelims = "[!$&'()*+,;:=]"; + String userinfo = "(?:" + unreserved + "|" + pctEncoded + "|" + subDelims + "|:)*"; + String h16 = "[0-9A-Fa-f]{1,4}"; + String decOctet = "(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; + String ipv4address = decOctet + "\\." + decOctet + "\\." + decOctet + "\\." + decOctet; + String ls32 = "(?:" + h16 + ":" + h16 + "|" + ipv4address + ")"; + String ipv6address = "(?:(?:" + h16 + "){6}" + ls32 + ")"; + String ipvfuture = "v[0-9A-Fa-f]+.(?:" + unreserved + "|" + subDelims + "|:)+"; + String ipLiteral = "\\[(?:" + ipv6address + "|" + ipvfuture + ")\\]"; + String regName = "(?:" + unreserved + "|" + pctEncoded + "|" + subDelims + ")*"; + String host = "(?:" + ipLiteral + "|" + ipv4address + "|" + regName + ")"; + String port = "[0-9]*"; + String authority = "(?:" + userinfo + "@)?" + host + "(?::" + port + ")?"; + String pchar = "(?:" + unreserved + "|" + pctEncoded + "|" + subDelims + "|@)"; + String segment = pchar + "*"; + String pathAbempty = "(?:/" + segment + ")*"; + String segmentNz = pchar + "+"; + String pathAbsolute = "/(?:" + segmentNz + "(?:/" + segment + ")*)?"; + String pathRootless = segmentNz + "(?:/" + segment + ")*"; + String hierPart = "(?://" + authority + pathAbempty + "|" + pathAbsolute + "|" + pathRootless + ")"; + String query = "(?:" + pchar + "|/|\\?)*"; + String fragment = "(?:" + pchar + "|/|\\?)*"; + String uriRegex = scheme + ":" + hierPart + "(?:" + query + ")?(?:#" + fragment + ")?"; + urlPattern = Pattern.compile(uriRegex); + } + + char[] visibleBuffer = new char[buffer.height * buffer.width]; + + for (int l = 0; l < buffer.height; l++) + System.arraycopy(buffer.charArray[buffer.windowBase + l], 0, + visibleBuffer, l * buffer.width, buffer.width); + + Matcher urlMatcher = urlPattern.matcher(new String(visibleBuffer)); + + while (urlMatcher.find()) + urls.add(urlMatcher.group()); + + return (new LinkedList<String> (urls)); + } + + /** + * @return + */ + public boolean isUsingNetwork() { + return transport.usesNetwork(); + } + + /** + * @return + */ + public TerminalKeyListener getKeyHandler() { + return keyListener; + } + + /** + * + */ + public void resetScrollPosition() { + // if we're in scrollback, scroll to bottom of window on input + if (buffer.windowBase != buffer.screenBase) + buffer.setWindowBase(buffer.screenBase); + } + + /** + * + */ + public void increaseFontSize() { + setFontSize(fontSize * FONT_SIZE_FACTOR); + } + + /** + * + */ + public void decreaseFontSize() { + setFontSize(fontSize / FONT_SIZE_FACTOR); + } + + /** + * Auto-size window back to default + */ + public void resetSize(TerminalView parent) { + this.forcedSize = false; + setMyFontSize(); + } + + /** + * Create a screenshot of the current view + */ + public void captureScreen() { + String msg; + File dir, path; + boolean success = true; + Bitmap screenshot = this.bitmap; + + if (manager == null || parent == null || screenshot == null) + return; + + SimpleDateFormat s = new SimpleDateFormat("yyyyMMdd_HHmmss"); + String date = s.format(new Date()); + String pref_path = manager.prefs.getString(PreferenceConstants.SCREEN_CAPTURE_FOLDER, ""); + File default_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); + + if (pref_path.equals("")) + dir = default_path; + else + dir = new File(pref_path); + + path = new File(dir, "vx-" + date + ".png"); + + try { + dir.mkdirs(); + FileOutputStream out = new FileOutputStream(path); + screenshot.compress(Bitmap.CompressFormat.PNG, 90, out); + out.close(); + } + catch (Exception e) { + e.printStackTrace(); + success = false; + } + + if (success) { + msg = manager.getResources().getString(R.string.screenshot_saved_as) + " " + path; + + if (manager.prefs.getBoolean(PreferenceConstants.SCREEN_CAPTURE_POPUP, true)) { + new AlertDialog.Builder(parent.getContext()) + .setTitle(R.string.screenshot_success_title) + .setMessage(msg) + .setPositiveButton(R.string.button_close, null) + .show(); + } + } + else { + msg = manager.getResources().getString(R.string.screenshot_not_saved_as) + " " + path; + new AlertDialog.Builder(parent.getContext()) + .setTitle(R.string.screenshot_error_title) + .setMessage(msg) + .setNegativeButton(R.string.button_close, null) + .show(); + } + + return; + } + + /** + * Show change font size dialog + */ + public boolean showFontSizeDialog() { + final String pickerString = "+-"; + CharSequence str = ""; + Editable content = Editable.Factory.getInstance().newEditable(str); + + if (parent == null) + return false; + + CharacterPickerDialog cpd = new CharacterPickerDialog(parent.getContext(), + parent, content, pickerString, true) { + private void changeFontSize(CharSequence result) { + if (result.equals("+")) + increaseFontSize(); + else if (result.equals("-")) + decreaseFontSize(); + } + @Override + public void onItemClick(AdapterView p, View v, int pos, long id) { + final String result = String.valueOf(pickerString.charAt(pos)); + changeFontSize(result); + } + @Override + public void onClick(View v) { + if (v instanceof Button) { + final CharSequence result = ((Button) v).getText(); + + if (result.equals("")) + dismiss(); + else + changeFontSize(result); + } + } + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) + dismiss(); + + return keyListener.onKey(parent, event.getKeyCode(), event); + } + + return true; + } + }; + cpd.show(); + return true; + } + + /** + * Show arrows dialog + */ + public boolean showArrowsDialog() { + final String []pickerStrings = {"←", "→", "↑", "↓", "tab", "ins", "del", "ret"}; + final HashMap<String, Integer> keymap = new HashMap<String, Integer>(); + keymap.put("←", vt320.KEY_LEFT); + keymap.put("→", vt320.KEY_RIGHT); + keymap.put("↑", vt320.KEY_UP); + keymap.put("↓", vt320.KEY_DOWN); + keymap.put("tab", vt320.KEY_TAB); + keymap.put("ins", vt320.KEY_INSERT); + keymap.put("del", vt320.KEY_DELETE); + keymap.put("ret", vt320.KEY_ENTER); + CharSequence str = ""; + Editable content = Editable.Factory.getInstance().newEditable(str); + + if (parent == null) return false; + + StringPickerDialog cpd = new StringPickerDialog(parent.getContext(), + parent, content, + pickerStrings, true) { + private void buttonPressed(String s) { + if (keymap.containsKey(s)) buffer.keyPressed(keymap.get(s), ' ', 0); + } + @Override + public void onItemClick(AdapterView p, View v, int pos, long id) { + buttonPressed(pickerStrings[pos]); + } + @Override + public void onClick(View v) { + if (v instanceof Button) { + final String s = ((Button) v).getText().toString(); + + if (s.equals("")) dismiss(); + else buttonPressed(s); + } + } + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) + dismiss(); + + return keyListener.onKey(parent, event.getKeyCode(), event); + } + + return true; + } + }; + cpd.show(); + return true; + } + + + /** + * CTRL dialog + */ + private String getCtrlString() { + final String defaultSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + String set = manager.prefs.getString(PreferenceConstants.CTRL_STRING, defaultSet); + + if (set == null || set.equals("")) { + set = defaultSet; + } + + return set; + } + + public boolean showCtrlDialog() { + CharSequence str = ""; + Editable content = Editable.Factory.getInstance().newEditable(str); + + if (parent == null) + return false; + + CharacterPickerDialog cpd = new CharacterPickerDialog(parent.getContext(), + parent, content, getCtrlString(), true) { + private void buttonPressed(CharSequence result) { + int code = result.toString().toUpperCase().charAt(0) - 64; + + if (code > 0 && code < 80) { + try { + transport.write(code); + } + catch (IOException e) { + Log.d(TAG, "Error writing CTRL+" + result.toString().toUpperCase().charAt(0)); + } + } + + dismiss(); + } + @Override + public void onItemClick(AdapterView p, View v, int pos, long id) { + final String result = String.valueOf(getCtrlString().charAt(pos)); + buttonPressed(result); + } + @Override + public void onClick(View v) { + if (v instanceof Button) { + final CharSequence result = ((Button) v).getText(); + + if (result.equals("")) + dismiss(); + else + buttonPressed(result); + } + } + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) + dismiss(); + + return keyListener.onKey(parent, event.getKeyCode(), event); + } + + return true; + } + }; + cpd.show(); + return true; + } + + /** + * Function keys dialog + */ + public boolean showFKeysDialog() { + final String []pickerStrings = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", "←", "→", "↑", "↓", "tab", "ins", "del", "ret"}; + final HashMap<String, Integer> keymap = new HashMap<String, Integer>(); + keymap.put("F1", vt320.KEY_F1); + keymap.put("F2", vt320.KEY_F2); + keymap.put("F3", vt320.KEY_F3); + keymap.put("F4", vt320.KEY_F4); + keymap.put("F5", vt320.KEY_F5); + keymap.put("F6", vt320.KEY_F6); + keymap.put("F7", vt320.KEY_F7); + keymap.put("F8", vt320.KEY_F8); + keymap.put("F9", vt320.KEY_F9); + keymap.put("F10", vt320.KEY_F10); + keymap.put("F11", vt320.KEY_F11); + keymap.put("F12", vt320.KEY_F12); + keymap.put("F13", vt320.KEY_F13); + keymap.put("F14", vt320.KEY_F14); + keymap.put("F15", vt320.KEY_F15); + keymap.put("F16", vt320.KEY_F16); + keymap.put("F17", vt320.KEY_F17); + keymap.put("F18", vt320.KEY_F18); + keymap.put("F19", vt320.KEY_F19); + keymap.put("F20", vt320.KEY_F20); + keymap.put("F21", vt320.KEY_F21); + keymap.put("F22", vt320.KEY_F22); + keymap.put("F23", vt320.KEY_F23); + keymap.put("F24", vt320.KEY_F24); + keymap.put("←", vt320.KEY_LEFT); + keymap.put("→", vt320.KEY_RIGHT); + keymap.put("↑", vt320.KEY_UP); + keymap.put("↓", vt320.KEY_DOWN); + keymap.put("tab", vt320.KEY_TAB); + keymap.put("ins", vt320.KEY_INSERT); + keymap.put("del", vt320.KEY_DELETE); + keymap.put("ret", vt320.KEY_ENTER); + CharSequence str = ""; + Editable content = Editable.Factory.getInstance().newEditable(str); + + if (parent == null) return false; + + StringPickerDialog cpd = new StringPickerDialog(parent.getContext(), + parent, content, + pickerStrings, true) { + private void buttonPressed(String s) { + if (keymap.containsKey(s)) buffer.keyPressed(keymap.get(s), ' ', 0); + + dismiss(); + } + @Override + public void onItemClick(AdapterView p, View v, int pos, long id) { + buttonPressed(pickerStrings[pos]); + } + @Override + public void onClick(View v) { + if (v instanceof Button) { + final String s = ((Button) v).getText().toString(); + + if (s.equals("")) dismiss(); + else buttonPressed(s); + } + } + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) + dismiss(); + + return keyListener.onKey(parent, event.getKeyCode(), event); + } + + return true; + } + }; + cpd.show(); + return true; + } + + private String getPickerString() { + final String defaultSet = "~\\^()[]{}<>|/:_;,.!@#$%&*?\"'-+="; + String set = manager.prefs.getString(PreferenceConstants.PICKER_STRING, defaultSet); + + if (set == null || set.equals("")) { + set = defaultSet; + } + + return set; + } + + public boolean showCharPickerDialog() { + CharSequence str = ""; + Editable content = Editable.Factory.getInstance().newEditable(str); + + if (parent == null || !transport.isAuthenticated()) + return false; + + CharacterPickerDialog cpd = new CharacterPickerDialog(parent.getContext(), + parent, content, getPickerString(), true) { + private void writeChar(CharSequence result) { + try { + if (transport.isAuthenticated()) + transport.write(result.toString().getBytes(getCharset().name())); + } + catch (IOException e) { + Log.e(TAG, "Problem with the CharacterPickerDialog", e); + } + + if (!manager.prefs.getBoolean(PreferenceConstants.PICKER_KEEP_OPEN, false)) + dismiss(); + } + @Override + public void onItemClick(AdapterView p, View v, int pos, long id) { + String result = String.valueOf(getPickerString().charAt(pos)); + writeChar(result); + } + @Override + public void onClick(View v) { + if (v instanceof Button) { + CharSequence result = ((Button) v).getText(); + + if (result.equals("")) + dismiss(); + else + writeChar(result); + } + } + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + int keyCode = event.getKeyCode(); + + if (event.getAction() == KeyEvent.ACTION_DOWN) { + // close window if SYM or BACK keys are pressed + if (keyListener.isSymKey(keyCode) || + keyCode == KeyEvent.KEYCODE_BACK) { + dismiss(); + return true; + } + } + + return super.dispatchKeyEvent(event); + } + }; + cpd.show(); + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/TerminalKeyListener.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1217 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2010 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.five_ten_sg.connectbot.service; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.lang.ref.WeakReference; +import java.util.List; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.TerminalView; +import com.five_ten_sg.connectbot.bean.SelectionArea; +import com.five_ten_sg.connectbot.util.PreferenceConstants; +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.res.Configuration; +import android.net.Uri; +import android.preference.PreferenceManager; +import android.text.ClipboardManager; +import android.util.Log; +import android.view.Gravity; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnKeyListener; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; +import de.mud.terminal.VDUBuffer; +import de.mud.terminal.vt320; + +/** + * @author kenny + * + */ +@SuppressWarnings("deprecation") // for ClipboardManager +public class TerminalKeyListener implements OnKeyListener, OnSharedPreferenceChangeListener { + private static final String TAG = "ConnectBot.OnKeyListener"; + + public final static int META_CTRL_ON = 0x01; + public final static int META_CTRL_LOCK = 0x02; + public final static int META_ALT_ON = 0x04; + public final static int META_ALT_LOCK = 0x08; + public final static int META_SHIFT_ON = 0x10; + public final static int META_SHIFT_LOCK = 0x20; + public final static int META_SLASH = 0x40; + public final static int META_TAB = 0x80; + + // The bit mask of momentary and lock states for each + public final static int META_CTRL_MASK = META_CTRL_ON | META_CTRL_LOCK; + public final static int META_ALT_MASK = META_ALT_ON | META_ALT_LOCK; + public final static int META_SHIFT_MASK = META_SHIFT_ON | META_SHIFT_LOCK; + + // backport constants from api level 11 + public final static int KEYCODE_ESCAPE = 111; + public final static int HC_META_CTRL_ON = 4096; + public final static int KEYCODE_PAGE_UP = 92; + public final static int KEYCODE_PAGE_DOWN = 93; + + // All the transient key codes + public final static int META_TRANSIENT = META_CTRL_ON | META_ALT_ON + | META_SHIFT_ON; + + protected final TerminalManager manager; + protected final TerminalBridge bridge; + protected final vt320 buffer; + protected String encoding; + + protected String keymode = null; + protected boolean hardKeyboard = false; + protected boolean hardKeyboardHidden; + protected String customKeyboard = null; + + protected int metaState = 0; + protected int mDeadKey = 0; + + // TODO add support for the new API. + private ClipboardManager clipboard = null; + private boolean selectingForCopy = false; + private final SelectionArea selectionArea; + protected final SharedPreferences prefs; + + + public TerminalKeyListener(TerminalManager manager, + TerminalBridge bridge, + vt320 buffer, + String encoding) { + this.manager = manager; + this.bridge = bridge; + this.buffer = buffer; + this.encoding = encoding; + selectionArea = new SelectionArea(); + prefs = PreferenceManager.getDefaultSharedPreferences(manager); + prefs.registerOnSharedPreferenceChangeListener(this); + hardKeyboard = (manager.res.getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY); + hardKeyboardHidden = manager.hardKeyboardHidden; + updateKeymode(); + updateCustomKeymap(); + } + + public void sendEscape() { + buffer.keyPressed(vt320.KEY_ESCAPE, ' ', getStateForBuffer()); + } + + protected void sendEncoded(String s) { + byte [] b = null; + + try { + b = s.getBytes(encoding); + } + catch (UnsupportedEncodingException e) { + } + + if (b != null) buffer.write(b); + } + + /** + * Handle onKey() events coming down from a {@link com.five_ten_sg.connectbot.TerminalView} above us. + * Modify the keys to make more sense to a host then pass it to the vt320. + */ + public boolean onKey(View v, int keyCode, KeyEvent event) { + try { + int repeat = event.getRepeatCount(); + + // skip keys if we aren't connected yet or have been disconnected + if (bridge.isDisconnected()) return false; + + // short cuts can see repeat counts and key up/down + if (handleShortcuts(v, keyCode, event, repeat, (event.getAction() == KeyEvent.ACTION_DOWN))) return true; + + // Ignore all key-up events except for the special keys + if (event.getAction() == KeyEvent.ACTION_UP) { + // There's nothing else here for virtual keyboard users. + if (!hardKeyboard || hardKeyboardHidden) return false; + + // if keycode debugging enabled, log and print the pressed key + if (prefs.getBoolean(PreferenceConstants.DEBUG_KEYCODES, false)) { + String keyCodeString = String.format(": %d", keyCode); + String toastText = v.getContext().getString(R.string.keycode_pressed) + keyCodeString; + Log.d(TAG, toastText); + } + + if (fullKeyboard()) { + switch (keyCode) { + case KeyEvent.KEYCODE_CTRL_LEFT: + case KeyEvent.KEYCODE_CTRL_RIGHT: + metaKeyUp(META_CTRL_ON); + return true; + + case KeyEvent.KEYCODE_ALT_LEFT: + case KeyEvent.KEYCODE_ALT_RIGHT: + metaKeyUp(META_ALT_ON); + return true; + + case KeyEvent.KEYCODE_SHIFT_LEFT: + case KeyEvent.KEYCODE_SHIFT_RIGHT: + metaKeyUp(META_SHIFT_ON); + return true; + + default: + } + } + else if (PreferenceConstants.KEYMODE_RIGHT.equals(keymode)) { + if (keyCode == KeyEvent.KEYCODE_ALT_RIGHT + && (metaState & META_SLASH) != 0) { + metaState &= ~(META_SLASH | META_TRANSIENT); + buffer.write('/'); + return true; + } + else if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT + && (metaState & META_TAB) != 0) { + metaState &= ~(META_TAB | META_TRANSIENT); + buffer.keyPressed(vt320.KEY_TAB, ' ', getStateForBuffer()); + return true; + } + } + else if (PreferenceConstants.KEYMODE_LEFT.equals(keymode)) { + if (keyCode == KeyEvent.KEYCODE_ALT_LEFT + && (metaState & META_SLASH) != 0) { + metaState &= ~(META_SLASH | META_TRANSIENT); + buffer.write('/'); + return true; + } + else if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT + && (metaState & META_TAB) != 0) { + metaState &= ~(META_TAB | META_TRANSIENT); + buffer.keyPressed(vt320.KEY_TAB, ' ', getStateForBuffer()); + return true; + } + } + + return false; + } + + bridge.resetScrollPosition(); + + if (keyCode == KeyEvent.KEYCODE_UNKNOWN && + event.getAction() == KeyEvent.ACTION_MULTIPLE) { + sendEncoded(event.getCharacters()); + return true; + } + + int curMetaState = event.getMetaState(); + final int orgMetaState = curMetaState; + + if ((metaState & META_SHIFT_MASK) != 0) { + curMetaState |= KeyEvent.META_SHIFT_ON; + } + + if ((metaState & META_ALT_MASK) != 0) { + curMetaState |= KeyEvent.META_ALT_ON; + } + + int uchar = event.getUnicodeChar(curMetaState); + + // no hard keyboard? ALT-k should pass through to below + if ((orgMetaState & KeyEvent.META_ALT_ON) != 0 && + (!hardKeyboard || hardKeyboardHidden)) { + uchar = 0; + } + + if ((uchar & KeyCharacterMap.COMBINING_ACCENT) != 0) { + mDeadKey = uchar & KeyCharacterMap.COMBINING_ACCENT_MASK; + return true; + } + + if (mDeadKey != 0 && uchar != 0) { + uchar = KeyCharacterMap.getDeadChar(mDeadKey, uchar); + mDeadKey = 0; + } + + // handle customized keymaps + if (customKeymapAction(v, keyCode, event)) + return true; + + if (v != null) { + //Show up the CharacterPickerDialog when the SYM key is pressed + if ((isSymKey(keyCode) || uchar == KeyCharacterMap.PICKER_DIALOG_INPUT)) { + bridge.showCharPickerDialog(); + + if (metaState == 4) { // reset fn-key state + metaState = 0; + bridge.redraw(); + } + + return true; + } + else if (keyCode == KeyEvent.KEYCODE_SEARCH) { + //Show up the URL scan dialog when the search key is pressed + urlScan(v); + return true; + } + } + + // otherwise pass through to existing session + // print normal keys + if (uchar > 0x00 && keyCode != KeyEvent.KEYCODE_ENTER) { + metaState &= ~(META_SLASH | META_TAB); + // Remove shift and alt modifiers + final int lastMetaState = metaState; + metaState &= ~(META_SHIFT_ON | META_ALT_ON); + + if (metaState != lastMetaState) { + bridge.redraw(); + } + + if ((metaState & META_CTRL_MASK) != 0) { + metaState &= ~META_CTRL_ON; + bridge.redraw(); + + // If there is no hard keyboard or there is a hard keyboard currently hidden, + // CTRL-1 through CTRL-9 will send F1 through F9 + if ((!hardKeyboard || hardKeyboardHidden) && sendFunctionKey(keyCode)) + return true; + + uchar = keyAsControl(uchar); + } + + // handle pressing f-keys + if ((hardKeyboard && !hardKeyboardHidden) + && (curMetaState & KeyEvent.META_ALT_ON) != 0 + && (curMetaState & KeyEvent.META_SHIFT_ON) != 0 + && sendFunctionKey(keyCode)) + return true; + + if (uchar < 0x80) + buffer.write(uchar); + else + sendEncoded(new String(Character.toChars(uchar))); + + return true; + } + + // send ctrl and meta-keys as appropriate + if (!hardKeyboard || hardKeyboardHidden) { + int k = event.getUnicodeChar(0); + int k0 = k; + boolean sendCtrl = false; + boolean sendMeta = false; + + if (k != 0) { + if ((orgMetaState & HC_META_CTRL_ON) != 0) { + k = keyAsControl(k); + if (k != k0) sendCtrl = true; + // send F1-F10 via CTRL-1 through CTRL-0 + if (!sendCtrl && sendFunctionKey(keyCode)) + return true; + } + else if ((orgMetaState & KeyEvent.META_ALT_ON) != 0) { + sendMeta = true; + sendEscape(); + } + + if (sendMeta || sendCtrl) { + buffer.write(k); + return true; + } + } + } + + // handle meta and f-keys for full hardware keyboard + if (hardKeyboard && !hardKeyboardHidden && fullKeyboard()) { + int k = event.getUnicodeChar(orgMetaState & KeyEvent.META_SHIFT_ON); + int k0 = k; + + if (k != 0) { + if ((orgMetaState & HC_META_CTRL_ON) != 0) { + k = keyAsControl(k); + if (k != k0) buffer.write(k); + return true; + } + else if ((orgMetaState & KeyEvent.META_ALT_ON) != 0) { + sendEscape(); + buffer.write(k); + return true; + } + } + + if (sendFullSpecialKey(keyCode)) + return true; + } + + // try handling keymode shortcuts + if (hardKeyboard && !hardKeyboardHidden && (repeat == 0)) { + if (PreferenceConstants.KEYMODE_RIGHT.equals(keymode)) { + switch (keyCode) { + case KeyEvent.KEYCODE_ALT_RIGHT: + metaState |= META_SLASH; + return true; + + case KeyEvent.KEYCODE_SHIFT_RIGHT: + metaState |= META_TAB; + return true; + + case KeyEvent.KEYCODE_SHIFT_LEFT: + metaPress(META_SHIFT_ON); + return true; + + case KeyEvent.KEYCODE_ALT_LEFT: + metaPress(META_ALT_ON); + return true; + } + } + else if (PreferenceConstants.KEYMODE_LEFT.equals(keymode)) { + switch (keyCode) { + case KeyEvent.KEYCODE_ALT_LEFT: + metaState |= META_SLASH; + return true; + + case KeyEvent.KEYCODE_SHIFT_LEFT: + metaState |= META_TAB; + return true; + + case KeyEvent.KEYCODE_SHIFT_RIGHT: + metaPress(META_SHIFT_ON); + return true; + + case KeyEvent.KEYCODE_ALT_RIGHT: + metaPress(META_ALT_ON); + return true; + } + } + else { + switch (keyCode) { + case KeyEvent.KEYCODE_ALT_RIGHT: + case KeyEvent.KEYCODE_ALT_LEFT: + metaPress(META_ALT_ON); + return true; + + case KeyEvent.KEYCODE_SHIFT_LEFT: + case KeyEvent.KEYCODE_SHIFT_RIGHT: + metaPress(META_SHIFT_ON); + return true; + } + } + + // Handle hardware CTRL keys + if (keyCode == KeyEvent.KEYCODE_CTRL_LEFT || + keyCode == KeyEvent.KEYCODE_CTRL_RIGHT) { + ctrlKeySpecial(); + return true; + } + } + + // look for special chars + switch (keyCode) { + case KeyEvent.KEYCODE_ESCAPE: + sendEscape(); + return true; + + case KeyEvent.KEYCODE_TAB: + buffer.keyPressed(vt320.KEY_TAB, ' ', getStateForBuffer()); + return true; + + case KeyEvent.KEYCODE_PAGE_DOWN: + buffer.keyPressed(vt320.KEY_PAGE_DOWN, ' ', getStateForBuffer()); + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + return true; + + case KeyEvent.KEYCODE_PAGE_UP: + buffer.keyPressed(vt320.KEY_PAGE_UP, ' ', getStateForBuffer()); + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + return true; + + case KeyEvent.KEYCODE_MOVE_HOME: + buffer.keyPressed(vt320.KEY_HOME, ' ', getStateForBuffer()); + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + return true; + + case KeyEvent.KEYCODE_MOVE_END: + buffer.keyPressed(vt320.KEY_END, ' ', getStateForBuffer()); + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + return true; + + case KeyEvent.KEYCODE_DEL: + if ((metaState & META_ALT_MASK) != 0) { + buffer.keyPressed(vt320.KEY_INSERT, ' ', getStateForBuffer()); + } + else { + buffer.keyPressed(vt320.KEY_BACK_SPACE, ' ', getStateForBuffer()); + } + + metaState &= ~META_TRANSIENT; + return true; + + case KeyEvent.KEYCODE_ENTER: + buffer.keyPressed(vt320.KEY_ENTER, ' ', getStateForBuffer()); + metaState &= ~META_TRANSIENT; + return true; + + case KeyEvent.KEYCODE_DPAD_LEFT: + if (selectingForCopy) { + selectionArea.decrementColumn(); + bridge.redraw(); + } + else { + if ((metaState & META_ALT_MASK) != 0) { + buffer.keyPressed(vt320.KEY_HOME, ' ', getStateForBuffer()); + } + else { + buffer.keyPressed(vt320.KEY_LEFT, ' ', getStateForBuffer()); + } + + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + } + + return true; + + case KeyEvent.KEYCODE_DPAD_UP: + if (selectingForCopy) { + selectionArea.decrementRow(); + bridge.redraw(); + } + else { + if ((metaState & META_ALT_MASK) != 0) { + buffer.keyPressed(vt320.KEY_PAGE_UP, ' ', getStateForBuffer()); + } + else { + buffer.keyPressed(vt320.KEY_UP, ' ', getStateForBuffer()); + } + + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + } + + return true; + + case KeyEvent.KEYCODE_DPAD_DOWN: + if (selectingForCopy) { + selectionArea.incrementRow(); + bridge.redraw(); + } + else { + if ((metaState & META_ALT_MASK) != 0) { + buffer.keyPressed(vt320.KEY_PAGE_DOWN, ' ', getStateForBuffer()); + } + else { + buffer.keyPressed(vt320.KEY_DOWN, ' ', getStateForBuffer()); + } + + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + } + + return true; + + case KeyEvent.KEYCODE_DPAD_RIGHT: + if (selectingForCopy) { + selectionArea.incrementColumn(); + bridge.redraw(); + } + else { + if ((metaState & META_ALT_MASK) != 0) { + buffer.keyPressed(vt320.KEY_END, ' ', getStateForBuffer()); + } + else { + buffer.keyPressed(vt320.KEY_RIGHT, ' ', getStateForBuffer()); + } + + metaState &= ~META_TRANSIENT; + bridge.tryKeyVibrate(); + } + + return true; + + case KeyEvent.KEYCODE_DPAD_CENTER: + ctrlKeySpecial(); + return true; + } + } + catch (NullPointerException npe) { + Log.d(TAG, "Input before connection established ignored."); + return true; + } + + return false; + } + + private boolean handleShortcuts(View v, int keyCode, KeyEvent event, int repeat, boolean down) { + String hwbuttonShortcut; + + switch (keyCode) { + case KeyEvent.KEYCODE_CAMERA: + // check to see which shortcut the camera button triggers + hwbuttonShortcut = manager.prefs.getString( + PreferenceConstants.CAMERA, + PreferenceConstants.HWBUTTON_SCREEN_CAPTURE); + return (handleShortcut(v, hwbuttonShortcut, repeat, down)); + + case KeyEvent.KEYCODE_VOLUME_UP: + // check to see which shortcut the volume button triggers + hwbuttonShortcut = manager.prefs.getString( + PreferenceConstants.VOLUP, + PreferenceConstants.HWBUTTON_FUNCTION_KEYS); + return (handleShortcut(v, hwbuttonShortcut, repeat, down)); + + case KeyEvent.KEYCODE_VOLUME_DOWN: + // check to see which shortcut the camera button triggers + hwbuttonShortcut = manager.prefs.getString( + PreferenceConstants.VOLDN, + PreferenceConstants.HWBUTTON_TAB); + return (handleShortcut(v, hwbuttonShortcut, repeat, down)); + + case KeyEvent.KEYCODE_SEARCH: + // check to see which shortcut the search button triggers + hwbuttonShortcut = manager.prefs.getString( + PreferenceConstants.SEARCH, + PreferenceConstants.HWBUTTON_ESC); + return (handleShortcut(v, hwbuttonShortcut, repeat, down)); + + case KeyEvent.KEYCODE_BUTTON_L2: + // check to see which shortcut the ptt button triggers + hwbuttonShortcut = manager.prefs.getString( + PreferenceConstants.PTT, + PreferenceConstants.HWBUTTON_MONITOR); + return (handleShortcut(v, hwbuttonShortcut, repeat, down)); + + default: return false; + } + } + + private boolean handleShortcut(View v, String shortcut, int repeat, boolean down) { + if (PreferenceConstants.HWBUTTON_DECREASE_FONTSIZE.equals(shortcut)) { + if (!down) return false; + + bridge.decreaseFontSize(); + } + else if (PreferenceConstants.HWBUTTON_INCREASE_FONTSIZE.equals(shortcut)) { + if (!down) return false; + + bridge.increaseFontSize(); + } + else if (PreferenceConstants.HWBUTTON_FUNCTION_KEYS.equals(shortcut)) { + if (repeat > 0) return false; + + if (!down) return false; + + bridge.showFKeysDialog(); + } + else if (PreferenceConstants.HWBUTTON_MONITOR.equals(shortcut)) { + if (repeat > 0) return false; + + buffer.monitorKey(down); + } + else if (PreferenceConstants.HWBUTTON_SCREEN_CAPTURE.equals(shortcut)) { + if (repeat > 0) return false; + + if (!down) return false; + + bridge.captureScreen(); + } + else if (PreferenceConstants.HWBUTTON_CTRL.equals(shortcut)) { + if (!down) return false; + + showMetakeyToast(v, PreferenceConstants.HWBUTTON_CTRL); + metaPress(META_CTRL_ON); + } + else if (PreferenceConstants.HWBUTTON_TAB.equals(shortcut)) { + if (!down) return false; + + buffer.keyPressed(vt320.KEY_TAB, ' ', getStateForBuffer()); + } + else if (PreferenceConstants.HWBUTTON_CTRLA_SPACE.equals(shortcut)) { + if (!down) return false; + + buffer.write(0x01); + buffer.write(' '); + } + else if (PreferenceConstants.HWBUTTON_CTRLA.equals(shortcut)) { + if (!down) return false; + + buffer.write(0x01); + } + else if (PreferenceConstants.HWBUTTON_ESC.equals(shortcut)) { + if (!down) return false; + + showMetakeyToast(v, PreferenceConstants.HWBUTTON_ESC); + sendEscape(); + } + else if (PreferenceConstants.HWBUTTON_ESC_A.equals(shortcut)) { + if (!down) return false; + + sendEscape(); + buffer.write('a'); + } + else { + return (false); + } + + return (true); + } + + private void showMetakeyToast(View v, String keyname) { + Log.d(TAG, keyname); + } + + public int keyAsControl(int key) { + // Support CTRL-a through CTRL-z + if (key >= 0x60 && key <= 0x7A) + key -= 0x60; + // Support CTRL-A through CTRL-_ + else if (key >= 0x40 && key <= 0x5F) + key -= 0x40; + // CTRL-space sends NULL + else if (key == 0x20) + key = 0x00; + // CTRL-? sends DEL + else if (key == 0x3F) + key = 0x7F; + + return key; + } + + /** + * @param key + * @return successful + */ + private boolean sendFunctionKey(int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_1: + buffer.keyPressed(vt320.KEY_F1, ' ', 0); + return true; + + case KeyEvent.KEYCODE_2: + buffer.keyPressed(vt320.KEY_F2, ' ', 0); + return true; + + case KeyEvent.KEYCODE_3: + buffer.keyPressed(vt320.KEY_F3, ' ', 0); + return true; + + case KeyEvent.KEYCODE_4: + buffer.keyPressed(vt320.KEY_F4, ' ', 0); + return true; + + case KeyEvent.KEYCODE_5: + buffer.keyPressed(vt320.KEY_F5, ' ', 0); + return true; + + case KeyEvent.KEYCODE_6: + buffer.keyPressed(vt320.KEY_F6, ' ', 0); + return true; + + case KeyEvent.KEYCODE_7: + buffer.keyPressed(vt320.KEY_F7, ' ', 0); + return true; + + case KeyEvent.KEYCODE_8: + buffer.keyPressed(vt320.KEY_F8, ' ', 0); + return true; + + case KeyEvent.KEYCODE_9: + buffer.keyPressed(vt320.KEY_F9, ' ', 0); + return true; + + case KeyEvent.KEYCODE_0: + buffer.keyPressed(vt320.KEY_F10, ' ', 0); + return true; + + default: + return false; + } + } + + private boolean sendFullSpecialKey(int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_F1: + buffer.keyPressed(vt320.KEY_F1, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F2: + buffer.keyPressed(vt320.KEY_F2, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F3: + buffer.keyPressed(vt320.KEY_F3, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F4: + buffer.keyPressed(vt320.KEY_F4, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F5: + buffer.keyPressed(vt320.KEY_F5, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F6: + buffer.keyPressed(vt320.KEY_F6, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F7: + buffer.keyPressed(vt320.KEY_F7, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F8: + buffer.keyPressed(vt320.KEY_F8, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F9: + buffer.keyPressed(vt320.KEY_F9, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F10: + buffer.keyPressed(vt320.KEY_F10, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F11: + buffer.keyPressed(vt320.KEY_F11, ' ', 0); + return true; + + case KeyEvent.KEYCODE_F12: + buffer.keyPressed(vt320.KEY_F12, ' ', 0); + return true; + + case KeyEvent.KEYCODE_INSERT: + buffer.keyPressed(vt320.KEY_INSERT, ' ', 0); + return true; + + case KeyEvent.KEYCODE_FORWARD_DEL: + buffer.keyPressed(vt320.KEY_DELETE, ' ', 0); + return true; + + /* + case KeyEvent.KEYCODE_PAGE_UP: + buffer.keyPressed(vt320.KEY_PAGE_UP, ' ', 0); + return true; + case KeyEvent.KEYCODE_PAGE_DOWN: + buffer.keyPressed(vt320.KEY_PAGE_DOWN, ' ', 0); + return true; + case KeyEvent.KEYCODE_MOVE_HOME: + buffer.keyPressed(vt320.KEY_HOME, ' ', getStateForBuffer()); + return true; + case KeyEvent.KEYCODE_MOVE_END: + buffer.keyPressed(vt320.KEY_END, ' ', getStateForBuffer()); + return true; + */ + default: + return false; + } + } + + /** + * Handle meta key presses for full hardware keyboard + */ + private void metaKeyDown(int code) { + if ((metaState & code) == 0) { + metaState |= code; + bridge.redraw(); + } + } + + protected void metaKeyUp(int code) { + if ((metaState & code) != 0) { + metaState &= ~code; + bridge.redraw(); + } + } + + /** + * Handle meta key presses where the key can be locked on. + * <p> + * 1st press: next key to have meta state<br /> + * 2nd press: meta state is locked on<br /> + * 3rd press: disable meta state + * + * @param code + */ + public void metaPress(int code) { + if ((metaState & (code << 1)) != 0) { + metaState &= ~(code << 1); + } + else if ((metaState & code) != 0) { + metaState &= ~code; + + if (!fullKeyboard()) + metaState |= code << 1; + } + else + metaState |= code; + + bridge.redraw(); + } + + public void setTerminalKeyMode(String keymode) { + this.keymode = keymode; + } + + private int getStateForBuffer() { + int bufferState = 0; + + if ((metaState & META_CTRL_MASK) != 0) + bufferState |= vt320.KEY_CONTROL; + + if ((metaState & META_SHIFT_MASK) != 0) + bufferState |= vt320.KEY_SHIFT; + + if ((metaState & META_ALT_MASK) != 0) + bufferState |= vt320.KEY_ALT; + + return bufferState; + } + + public int getMetaState() { + return metaState; + } + + public int getDeadKey() { + return mDeadKey; + } + + public void setClipboardManager(ClipboardManager clipboard) { + this.clipboard = clipboard; + } + + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + if (PreferenceConstants.KEYMODE.equals(key)) { + updateKeymode(); + } + else if (PreferenceConstants.CUSTOM_KEYMAP.equals(key)) { + updateCustomKeymap(); + } + } + + private void updateKeymode() { + keymode = prefs.getString(PreferenceConstants.KEYMODE, PreferenceConstants.KEYMODE_RIGHT); + } + + private void updateCustomKeymap() { + customKeyboard = prefs.getString(PreferenceConstants.CUSTOM_KEYMAP, + PreferenceConstants.CUSTOM_KEYMAP_DISABLED); + } + + public void setCharset(String encoding) { + this.encoding = encoding; + } + + public Charset getCharset() { + return Charset.forName(encoding); + } + + protected void ctrlKeySpecial() { + if (selectingForCopy) { + if (selectionArea.isSelectingOrigin()) + selectionArea.finishSelectingOrigin(); + else { + if (clipboard != null) { + // copy selected area to clipboard + String copiedText = selectionArea.copyFrom(buffer); + clipboard.setText(copiedText); + selectingForCopy = false; + selectionArea.reset(); + } + } + } + else { + if ((metaState & META_CTRL_ON) != 0) { + sendEscape(); + metaState &= ~META_CTRL_ON; + } + else + metaPress(META_CTRL_ON); + } + + bridge.redraw(); + } + + protected boolean customKeymapAction(View v, int keyCode, KeyEvent event) { + if (bridge == null || customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_DISABLED)) + return false; + + byte c = 0x00; + int termKey = 0; + + if (fullKeyboard()) { + switch (keyCode) { + case KeyEvent.KEYCODE_CTRL_LEFT: + case KeyEvent.KEYCODE_CTRL_RIGHT: + metaKeyDown(META_CTRL_ON); + return true; + + case KeyEvent.KEYCODE_ALT_LEFT: + case KeyEvent.KEYCODE_ALT_RIGHT: + metaKeyDown(META_ALT_ON); + return true; + + case KeyEvent.KEYCODE_SHIFT_LEFT: + case KeyEvent.KEYCODE_SHIFT_RIGHT: + metaKeyDown(META_SHIFT_ON); + return true; + + case KeyEvent.KEYCODE_BACK: + if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_ASUS_TF)) { + // Check to see whether this is the back button on the + // screen (-1) or the Asus Transformer Keyboard Dock. + // Treat the HW button as ESC. + if (event.getDeviceId() > 0) { + sendEscape(); + return true; + } + } + + default: + } + } + + if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_ASUS_TF)) { + if ((metaState & META_ALT_MASK) != 0 + && (metaState & META_SHIFT_MASK) != 0 + && sendFunctionKey(keyCode)) + return true; + } + else if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_SE_XPPRO)) { + // Sony Ericsson Xperia pro (MK16i) and Xperia mini Pro (SK17i) + // Language key acts as CTRL + if (keyCode == KeyEvent.KEYCODE_SWITCH_CHARSET) { + ctrlKeySpecial(); + return true; + } + + if ((metaState & META_ALT_MASK) != 0) { + if ((metaState & META_SHIFT_MASK) != 0) { + // ALT + shift + key + switch (keyCode) { + case KeyEvent.KEYCODE_U: + c = 0x5B; + break; + + case KeyEvent.KEYCODE_I: + c = 0x5D; + break; + + case KeyEvent.KEYCODE_O: + c = 0x7B; + break; + + case KeyEvent.KEYCODE_P: + c = 0x7D; + break; + } + } + else { + // ALT + key + switch (keyCode) { + case KeyEvent.KEYCODE_S: + c = 0x7c; + break; + + case KeyEvent.KEYCODE_Z: + c = 0x5c; + break; + + case KeyEvent.KEYCODE_DEL: + termKey = vt320.KEY_DELETE; + break; + } + } + } + else if ((metaState & META_SHIFT_MASK) != 0) { + // shift + key + switch (keyCode) { + case KeyEvent.KEYCODE_AT: + c = 0x3c; + break; + + case KeyEvent.KEYCODE_COMMA: + c = 0x3e; + break; + + case KeyEvent.KEYCODE_PERIOD: + c = 0x5e; + break; + + case KeyEvent.KEYCODE_GRAVE: + c = 0x60; + break; + + case KeyEvent.KEYCODE_APOSTROPHE: + c = 0x7e; + break; + + case KeyEvent.KEYCODE_DEL: + termKey = vt320.KEY_BACK_SPACE; + break; + } + } + } + else if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_SGH_I927)) { + // Samsung Captivate Glide (SGH-i927) + if (keyCode == 115) { + // .com key = ESC + c = 0x00; + termKey = vt320.KEY_ESCAPE; + return true; + } + else if (keyCode == 116) { + // Microphone key = TAB + c = 0x00; + termKey = vt320.KEY_TAB; + } + else if ((metaState & META_ALT_MASK) != 0 && (metaState & META_SHIFT_MASK) != 0) { + switch (keyCode) { + case KeyEvent.KEYCODE_O: + c = 0x5B; + break; + + case KeyEvent.KEYCODE_P: + c = 0x5D; + break; + + case KeyEvent.KEYCODE_A: + c = 0x3C; + break; + + case KeyEvent.KEYCODE_D: + c = 0x3E; + break; + } + } + } + else if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_SGH_I927_ICS)) { + // Samsung Captivate Glide (SGH-i927) Ice Cream Sandwich (4.0.x) + if (keyCode == 226) { + // .com key = ESC + c = 0x00; + termKey = vt320.KEY_ESCAPE; + } + else if (keyCode == 220) { + // Microphone key = TAB + c = 0x00; + termKey = vt320.KEY_TAB; + } + else if ((metaState & META_ALT_MASK) != 0 && (metaState & META_SHIFT_MASK) != 0) { + switch (keyCode) { + case KeyEvent.KEYCODE_O: + c = 0x5B; + break; + + case KeyEvent.KEYCODE_P: + c = 0x5D; + break; + + case KeyEvent.KEYCODE_A: + c = 0x3C; + break; + + case KeyEvent.KEYCODE_D: + c = 0x3E; + break; + } + } + } + + if ((c != 0x00) || termKey != 0) { + if (c != 0x00) + buffer.write(c); + else + buffer.keyPressed(termKey, ' ', 0); + + metaState &= ~(META_SHIFT_ON | META_ALT_ON); + bridge.redraw(); + return true; + } + + return false; + } + + public void urlScan(View v) { + //final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); + List<String> urls = bridge.scanForURLs(); + Dialog urlDialog = new Dialog(v.getContext()); + urlDialog.setTitle(R.string.console_menu_urlscan); + ListView urlListView = new ListView(v.getContext()); + URLItemListener urlListener = new URLItemListener(v.getContext()); + urlListView.setOnItemClickListener(urlListener); + urlListView.setAdapter(new ArrayAdapter<String> (v.getContext(), android.R.layout.simple_list_item_1, urls)); + urlDialog.setContentView(urlListView); + urlDialog.show(); + } + + public boolean isSymKey(int keyCode) { + if (keyCode == KeyEvent.KEYCODE_SYM || + keyCode == KeyEvent.KEYCODE_PICTSYMBOLS) + return true; + + if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_SGH_I927_ICS) && + keyCode == 227) + return true; + + return false; + } + + protected boolean fullKeyboard() { + if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_FULL) || + (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_ASUS_TF))) + return true; + + return false; + } + + private class URLItemListener implements OnItemClickListener { + private WeakReference<Context> contextRef; + + URLItemListener(Context context) { + this.contextRef = new WeakReference<Context> (context); + } + + public void onItemClick(AdapterView<?> arg0, View view, int position, + long id) { + Context context = contextRef.get(); + + if (context == null) + return; + + try { + TextView urlView = (TextView) view; + String url = urlView.getText().toString(); + + if (url.indexOf("://") < 0) + url = "http://" + url; + + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + context.startActivity(intent); + } + catch (Exception e) { + Log.e(TAG, "couldn't open URL", e); + // We should probably tell the user that we couldn't find a + // handler... + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/TerminalManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,730 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.service; + +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Timer; +import java.util.TimerTask; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.bean.PubkeyBean; +import com.five_ten_sg.connectbot.transport.TransportFactory; +import com.five_ten_sg.connectbot.util.HostDatabase; +import com.five_ten_sg.connectbot.util.PreferenceConstants; +import com.five_ten_sg.connectbot.util.PubkeyDatabase; +import com.five_ten_sg.connectbot.util.PubkeyUtils; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.res.AssetFileDescriptor; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.media.MediaPlayer.OnCompletionListener; +import android.net.Uri; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Vibrator; +import android.preference.PreferenceManager; +import android.util.Log; + +/** + * Manager for SSH connections that runs as a service. This service holds a list + * of currently connected SSH bridges that are ready for connection up to a GUI + * if needed. + * + * @author jsharkey + */ +public class TerminalManager extends Service implements BridgeDisconnectedListener, OnSharedPreferenceChangeListener { + public final static String TAG = "ConnectBot.TerminalManager"; + + public List<TerminalBridge> bridges = new LinkedList<TerminalBridge>(); + public Map<HostBean, WeakReference<TerminalBridge>> mHostBridgeMap = + new HashMap<HostBean, WeakReference<TerminalBridge>>(); + public Map<String, WeakReference<TerminalBridge>> mNicknameBridgeMap = + new HashMap<String, WeakReference<TerminalBridge>>(); + + public TerminalBridge defaultBridge = null; + + public List<HostBean> disconnected = new LinkedList<HostBean>(); + + public Handler disconnectHandler = null; + + public Map<String, KeyHolder> loadedKeypairs = new HashMap<String, KeyHolder>(); + + public Resources res; + + public HostDatabase hostdb; + public PubkeyDatabase pubkeydb; + + protected SharedPreferences prefs; + + final private IBinder binder = new TerminalBinder(); + + private ConnectivityReceiver connectivityManager; + private ConnectionNotifier connectionNotifier = new ConnectionNotifier(); + + private MediaPlayer mediaPlayer; + + private Timer pubkeyTimer; + + private Timer idleTimer; + private final long IDLE_TIMEOUT = 300000; // 5 minutes + + private Vibrator vibrator; + private volatile boolean wantKeyVibration; + public static final long VIBRATE_DURATION = 30; + + private boolean wantBellVibration; + + private boolean resizeAllowed = true; + + private int fullScreen = 0; + + private boolean savingKeys; + + protected List<WeakReference<TerminalBridge>> mPendingReconnect + = new LinkedList<WeakReference<TerminalBridge>>(); + + public boolean hardKeyboardHidden; + + @Override + public void onCreate() { + Log.i(TAG, "Starting service"); + prefs = PreferenceManager.getDefaultSharedPreferences(this); + prefs.registerOnSharedPreferenceChangeListener(this); + res = getResources(); + pubkeyTimer = new Timer("pubkeyTimer", true); + hostdb = new HostDatabase(this); + pubkeydb = new PubkeyDatabase(this); + // load all marked pubkeys into memory + updateSavingKeys(); + List<PubkeyBean> pubkeys = pubkeydb.getAllStartPubkeys(); + + for (PubkeyBean pubkey : pubkeys) { + try { + PrivateKey privKey = PubkeyUtils.decodePrivate(pubkey.getPrivateKey(), pubkey.getType()); + PublicKey pubKey = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); + KeyPair pair = new KeyPair(pubKey, privKey); + addKey(pubkey, pair); + } + catch (Exception e) { + Log.d(TAG, String.format("Problem adding key '%s' to in-memory cache", pubkey.getNickname()), e); + } + } + + vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + wantKeyVibration = prefs.getBoolean(PreferenceConstants.BUMPY_ARROWS, true); + wantBellVibration = prefs.getBoolean(PreferenceConstants.BELL_VIBRATE, true); + enableMediaPlayer(); + hardKeyboardHidden = (res.getConfiguration().hardKeyboardHidden == + Configuration.HARDKEYBOARDHIDDEN_YES); + final boolean lockingWifi = prefs.getBoolean(PreferenceConstants.WIFI_LOCK, true); + connectivityManager = new ConnectivityReceiver(this, lockingWifi); + } + + private void updateSavingKeys() { + savingKeys = prefs.getBoolean(PreferenceConstants.MEMKEYS, true); + } + + @Override + public void onDestroy() { + Log.i(TAG, "Destroying service"); + disconnectAll(true); + + if (hostdb != null) { + hostdb.close(); + hostdb = null; + } + + if (pubkeydb != null) { + pubkeydb.close(); + pubkeydb = null; + } + + synchronized (this) { + if (idleTimer != null) + idleTimer.cancel(); + + if (pubkeyTimer != null) + pubkeyTimer.cancel(); + } + + connectivityManager.cleanup(); + connectionNotifier.hideRunningNotification(this); + disableMediaPlayer(); + } + + /** + * Disconnect all currently connected bridges. + */ + private void disconnectAll(final boolean immediate) { + disconnectAll(immediate, false); + } + + /** + * Disconnect all currently connected bridges. + */ + private void disconnectAll(final boolean immediate, boolean onlyRemote) { + TerminalBridge[] tmpBridges = null; + + synchronized (bridges) { + if (bridges.size() > 0) { + tmpBridges = bridges.toArray(new TerminalBridge[bridges.size()]); + } + } + + if (tmpBridges != null) { + // disconnect and dispose of any existing bridges + for (int i = 0; i < tmpBridges.length; i++) { + if (!onlyRemote || !(tmpBridges[i].transport instanceof com.five_ten_sg.connectbot.transport.Local)) + tmpBridges[i].dispatchDisconnect(immediate); + } + } + } + + /** + * Open a new SSH session using the given parameters. + */ + private TerminalBridge openConnection(HostBean host) throws IllegalArgumentException, IOException { + // throw exception if terminal already open + if (getConnectedBridge(host) != null) { + throw new IllegalArgumentException("Connection already open for that nickname"); + } + + TerminalBridge bridge = new TerminalBridge(this, host, getApplicationInfo().dataDir); + bridge.setOnDisconnectedListener(this); + bridge.startConnection(); + + synchronized (bridges) { + bridges.add(bridge); + WeakReference<TerminalBridge> wr = new WeakReference<TerminalBridge> (bridge); + mHostBridgeMap.put(bridge.host, wr); + mNicknameBridgeMap.put(bridge.host.getNickname(), wr); + } + + synchronized (disconnected) { + disconnected.remove(bridge.host); + } + + if (bridge.isUsingNetwork()) { + connectivityManager.incRef(); + } + + if (prefs.getBoolean(PreferenceConstants.CONNECTION_PERSIST, true)) { + connectionNotifier.showRunningNotification(this); + } + + // also update database with new connected time + touchHost(host); + return bridge; + } + + public String getEmulation() { + return prefs.getString(PreferenceConstants.EMULATION, "xterm-256color"); + } + + public int getScrollback() { + int scrollback = 140; + + try { + scrollback = Integer.parseInt(prefs.getString(PreferenceConstants.SCROLLBACK, "140")); + } + catch (Exception e) { + } + + return scrollback; + } + + /** + * Open a new connection by reading parameters from the given URI. Follows + * format specified by an individual transport. + */ + public TerminalBridge openConnection(Uri uri) throws Exception { + HostBean host = TransportFactory.findHost(hostdb, uri); + + if (host == null) + host = TransportFactory.getTransport(uri.getScheme()).createHost(uri); + + return openConnection(host); + } + + /** + * Update the last-connected value for the given nickname by passing through + * to {@link HostDatabase}. + */ + private void touchHost(HostBean host) { + hostdb.touchHost(host); + } + + /** + * Find a connected {@link TerminalBridge} with the given HostBean. + * + * @param host the HostBean to search for + * @return TerminalBridge that uses the HostBean + */ + public TerminalBridge getConnectedBridge(HostBean host) { + WeakReference<TerminalBridge> wr = mHostBridgeMap.get(host); + + if (wr != null) { + return wr.get(); + } + else { + return null; + } + } + + /** + * Find a connected {@link TerminalBridge} using its nickname. + * + * @param nickname + * @return TerminalBridge that matches nickname + */ + public TerminalBridge getConnectedBridge(final String nickname) { + if (nickname == null) { + return null; + } + + WeakReference<TerminalBridge> wr = mNicknameBridgeMap.get(nickname); + + if (wr != null) { + return wr.get(); + } + else { + return null; + } + } + + /** + * Called by child bridge when somehow it's been disconnected. + */ + public void onDisconnected(TerminalBridge bridge) { + boolean shouldHideRunningNotification = false; + + synchronized (bridges) { + // remove this bridge from our list + bridges.remove(bridge); + mHostBridgeMap.remove(bridge.host); + mNicknameBridgeMap.remove(bridge.host.getNickname()); + + if (bridge.isUsingNetwork()) { + connectivityManager.decRef(); + } + + if (bridges.size() == 0 && + mPendingReconnect.size() == 0) { + shouldHideRunningNotification = true; + } + } + + synchronized (disconnected) { + disconnected.add(bridge.host); + } + + if (shouldHideRunningNotification) { + connectionNotifier.hideRunningNotification(this); + } + + // pass notification back up to gui + if (disconnectHandler != null) + Message.obtain(disconnectHandler, -1, bridge).sendToTarget(); + } + + public boolean isKeyLoaded(String nickname) { + return loadedKeypairs.containsKey(nickname); + } + + public void addKey(PubkeyBean pubkey, KeyPair pair) { + addKey(pubkey, pair, false); + } + + public void addKey(PubkeyBean pubkey, KeyPair pair, boolean force) { + if (!savingKeys && !force) + return; + + removeKey(pubkey.getNickname()); + byte[] sshPubKey = PubkeyUtils.extractOpenSSHPublic(pair); + KeyHolder keyHolder = new KeyHolder(); + keyHolder.bean = pubkey; + keyHolder.pair = pair; + keyHolder.openSSHPubkey = sshPubKey; + loadedKeypairs.put(pubkey.getNickname(), keyHolder); + + if (pubkey.getLifetime() > 0) { + final String nickname = pubkey.getNickname(); + pubkeyTimer.schedule(new TimerTask() { + @Override + public void run() { + Log.d(TAG, "Unloading from memory key: " + nickname); + removeKey(nickname); + } + }, pubkey.getLifetime() * 1000); + } + + Log.d(TAG, String.format("Added key '%s' to in-memory cache", pubkey.getNickname())); + } + + public boolean removeKey(String nickname) { + Log.d(TAG, String.format("Removed key '%s' from in-memory cache", nickname)); + return loadedKeypairs.remove(nickname) != null; + } + + public boolean removeKey(byte[] publicKey) { + String nickname = null; + + for (Entry<String, KeyHolder> entry : loadedKeypairs.entrySet()) { + if (Arrays.equals(entry.getValue().openSSHPubkey, publicKey)) { + nickname = entry.getKey(); + break; + } + } + + if (nickname != null) { + Log.d(TAG, String.format("Removed key '%s' to in-memory cache", nickname)); + return removeKey(nickname); + } + else + return false; + } + + public KeyPair getKey(String nickname) { + if (loadedKeypairs.containsKey(nickname)) { + KeyHolder keyHolder = loadedKeypairs.get(nickname); + return keyHolder.pair; + } + else + return null; + } + + public KeyPair getKey(byte[] publicKey) { + for (KeyHolder keyHolder : loadedKeypairs.values()) { + if (Arrays.equals(keyHolder.openSSHPubkey, publicKey)) + return keyHolder.pair; + } + + return null; + } + + public String getKeyNickname(byte[] publicKey) { + for (Entry<String, KeyHolder> entry : loadedKeypairs.entrySet()) { + if (Arrays.equals(entry.getValue().openSSHPubkey, publicKey)) + return entry.getKey(); + } + + return null; + } + + private void stopWithDelay() { + // TODO add in a way to check whether keys loaded are encrypted and only + // set timer when we have an encrypted key loaded + if (loadedKeypairs.size() > 0) { + synchronized (this) { + if (idleTimer == null) + idleTimer = new Timer("idleTimer", true); + + idleTimer.schedule(new IdleTask(), IDLE_TIMEOUT); + } + } + else { + Log.d(TAG, "Stopping service immediately"); + stopSelf(); + } + } + + protected void stopNow() { + if (bridges.size() == 0) { + stopSelf(); + } + } + + private synchronized void stopIdleTimer() { + if (idleTimer != null) { + idleTimer.cancel(); + idleTimer = null; + } + } + + public class TerminalBinder extends Binder { + public TerminalManager getService() { + return TerminalManager.this; + } + } + + @Override + public IBinder onBind(Intent intent) { + Log.i(TAG, "Someone bound to TerminalManager"); + setResizeAllowed(true); + stopIdleTimer(); + // Make sure we stay running to maintain the bridges + startService(new Intent(this, TerminalManager.class)); + return binder; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + /* + * We want this service to continue running until it is explicitly + * stopped, so return sticky. + */ + return START_STICKY; + } + + @Override + public void onRebind(Intent intent) { + super.onRebind(intent); + setResizeAllowed(true); + Log.i(TAG, "Someone rebound to TerminalManager"); + stopIdleTimer(); + } + + @Override + public boolean onUnbind(Intent intent) { + Log.i(TAG, "Someone unbound from TerminalManager"); + setResizeAllowed(true); + + if (bridges.size() == 0) { + stopWithDelay(); + } + + return true; + } + + private class IdleTask extends TimerTask { + /* (non-Javadoc) + * @see java.util.TimerTask#run() + */ + @Override + public void run() { + Log.d(TAG, String.format("Stopping service after timeout of ~%d seconds", IDLE_TIMEOUT / 1000)); + TerminalManager.this.stopNow(); + } + } + + public void tryKeyVibrate() { + if (wantKeyVibration) + vibrate(); + } + + private void vibrate() { + if (vibrator != null) + vibrator.vibrate(VIBRATE_DURATION); + } + + private void enableMediaPlayer() { + mediaPlayer = new MediaPlayer(); + float volume = prefs.getFloat(PreferenceConstants.BELL_VOLUME, + PreferenceConstants.DEFAULT_BELL_VOLUME); + mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION); + mediaPlayer.setOnCompletionListener(new BeepListener()); + AssetFileDescriptor file = res.openRawResourceFd(R.raw.bell); + + try { + mediaPlayer.setDataSource(file.getFileDescriptor(), file + .getStartOffset(), file.getLength()); + file.close(); + mediaPlayer.setVolume(volume, volume); + mediaPlayer.prepare(); + } + catch (IOException e) { + Log.e(TAG, "Error setting up bell media player", e); + } + } + + private void disableMediaPlayer() { + if (mediaPlayer != null) { + mediaPlayer.release(); + mediaPlayer = null; + } + } + + public void playBeep() { + if (mediaPlayer != null) + mediaPlayer.start(); + + if (wantBellVibration) + vibrate(); + } + + private static class BeepListener implements OnCompletionListener { + public void onCompletion(MediaPlayer mp) { + mp.seekTo(0); + } + } + + /** + * Send system notification to user for a certain host. When user selects + * the notification, it will bring them directly to the ConsoleActivity + * displaying the host. + * + * @param host + */ + public void sendActivityNotification(HostBean host) { + if (!prefs.getBoolean(PreferenceConstants.BELL_NOTIFICATION, false)) + return; + + connectionNotifier.showActivityNotification(this, host); + } + + /* (non-Javadoc) + * @see android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged(android.content.SharedPreferences, java.lang.String) + */ + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + if (PreferenceConstants.BELL.equals(key)) { + boolean wantAudible = sharedPreferences.getBoolean( + PreferenceConstants.BELL, true); + + if (wantAudible && mediaPlayer == null) + enableMediaPlayer(); + else if (!wantAudible && mediaPlayer != null) + disableMediaPlayer(); + } + else if (PreferenceConstants.BELL_VOLUME.equals(key)) { + if (mediaPlayer != null) { + float volume = sharedPreferences.getFloat( + PreferenceConstants.BELL_VOLUME, + PreferenceConstants.DEFAULT_BELL_VOLUME); + mediaPlayer.setVolume(volume, volume); + } + } + else if (PreferenceConstants.BELL_VIBRATE.equals(key)) { + wantBellVibration = sharedPreferences.getBoolean( + PreferenceConstants.BELL_VIBRATE, true); + } + else if (PreferenceConstants.BUMPY_ARROWS.equals(key)) { + wantKeyVibration = sharedPreferences.getBoolean( + PreferenceConstants.BUMPY_ARROWS, true); + } + else if (PreferenceConstants.WIFI_LOCK.equals(key)) { + final boolean lockingWifi = prefs.getBoolean(PreferenceConstants.WIFI_LOCK, true); + connectivityManager.setWantWifiLock(lockingWifi); + } + else if (PreferenceConstants.MEMKEYS.equals(key)) { + updateSavingKeys(); + } + } + + /** + * Allow {@link TerminalBridge} to resize when the parent has changed. + * @param resizeAllowed + */ + public void setResizeAllowed(boolean resizeAllowed) { + this.resizeAllowed = resizeAllowed; + } + + public boolean isResizeAllowed() { + return resizeAllowed; + } + + public void setFullScreen(int fullScreen) { + this.fullScreen = fullScreen; + } + + public int getFullScreen() { + return this.fullScreen; + } + + public static class KeyHolder { + public PubkeyBean bean; + public KeyPair pair; + public byte[] openSSHPubkey; + } + + /** + * Called when connectivity to the network is lost and it doesn't appear + * we'll be getting a different connection any time soon. + */ + public void onConnectivityLost() { + final Thread t = new Thread() { + @Override + public void run() { + disconnectAll(false, true); + } + }; + t.setName("Disconnector"); + t.start(); + } + + /** + * Called when connectivity to the network is restored. + */ + public void onConnectivityRestored() { + final Thread t = new Thread() { + @Override + public void run() { + reconnectPending(); + } + }; + t.setName("Reconnector"); + t.start(); + } + + /** + * Insert request into reconnect queue to be executed either immediately + * or later when connectivity is restored depending on whether we're + * currently connected. + * + * @param bridge the TerminalBridge to reconnect when possible + */ + public void requestReconnect(TerminalBridge bridge) { + synchronized (mPendingReconnect) { + mPendingReconnect.add(new WeakReference<TerminalBridge> (bridge)); + + if (!bridge.isUsingNetwork() || + connectivityManager.isConnected()) { + reconnectPending(); + } + } + } + + /** + * Reconnect all bridges that were pending a reconnect when connectivity + * was lost. + */ + private void reconnectPending() { + synchronized (mPendingReconnect) { + for (WeakReference<TerminalBridge> ref : mPendingReconnect) { + TerminalBridge bridge = ref.get(); + + if (bridge == null) { + continue; + } + + bridge.startConnection(); + } + + mPendingReconnect.clear(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/service/TerminalMonitor.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,522 @@ +package com.five_ten_sg.connectbot.service; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.net.Uri; +import android.os.IBinder; +import android.util.Log; +import android.view.View; +import de.mud.terminal.vt320; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.HashMap; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; + +import com.five_ten_sg.connectbot.ConsoleActivity; +import com.five_ten_sg.connectbot.bean.HostBean; + + +public class TerminalMonitor { + public final static String TAG = "ConnectBot.TerminalMonitor"; + + public static final char MONITOR_CMD_INIT = 0; + public static final char MONITOR_CMD_ACTIVATE = 1; + public static final char MONITOR_CMD_KEYSTATE = 2; + public static final char MONITOR_CMD_CURSORMOVE = 3; + public static final char MONITOR_CMD_SCREENCHANGE = 4; + public static final char MONITOR_CMD_FIELDVALUE = 5; + public static final char MONITOR_CMD_SETFIELD = 5; + public static final char MONITOR_CMD_GETFIELD = 6; + public static final char MONITOR_CMD_SCREENWATCH = 7; + public static final char MONITOR_CMD_DEPRESS = 8; + public static final char MONITOR_CMD_SHOWURL = 9; + public static final char MONITOR_CMD_SWITCHSESSION = 10; + public static final char MONITOR_CMD_CURSORREQUEST = 11; + + public static final String[] commands = { + "cmd_init", + "cmd_activate", + "cmd_keystate", + "cmd_cursormove", + "cmd_screenchange", + "cmd_fieldvalue/setfield", + "cmd_getfield", + "cmd_screenwatch", + "cmd_depress", + "cmd_showurl", + "cmd_switchsession", + "cmd_cursorrequest" + }; + + public static final char CURSOR_REQUESTED = 0; + public static final char CURSOR_SCREEN_CHANGE = 1; + public static final char CURSOR_USER_KEY = 2; + + private static final int MONITORPORT = 6000; + private static final String LOCALHOST = "127.0.0.1"; + + private Context parent = null; + private vt320 buffer = null; + private View view = null; + private HostBean host = null; + private String init = null; + private int start_line = 0; // monitor part of the screen for changes + private int end_line = 500; // "" + private int start_column = 0; // "" + private int end_column = 500; // "" + private boolean modified = false; // used to delay screen change notifications + private boolean moved = false; // used to delay cursor moved notifications + private int to_line = 0; // "" + private int to_column = 0; // "" + private HashMap<Integer, Integer> keymap = null; // map MS VK_ keys to vt320 virtual keys + private IBinder bound = null; + private Socket monitor_socket = null; + private InputStream monitor_in = null; + private OutputStream monitor_out = null; + private MyReader monitor_reader = null; + private BlockingQueue<char[]> pending_commands = new ArrayBlockingQueue<char[]>(100); + private MyServiceConnection monitor_connection = new MyServiceConnection(); + + class MyReader extends Thread { + private InputStream monitor_in; + private byte[] b; + private boolean is_closing = false; + + public MyReader(InputStream monitor_in) { + this.monitor_in = monitor_in; + b = new byte[100]; + Log.i(TAG, "MyReader constructor"); + } + + public void closing() { + is_closing = true; + } + + private char[] forceRead(int len) throws IOException { + int len2 = len * 2; + int off = 0; + + if (b.length < len2) b = new byte[len2]; + + while (off < len2) { + int l = monitor_in.read(b, off, len2 - off); + + if (l < 0) throw new IOException("eof"); + + off += l; + } + + return bytesToChars(b, len2); + } + + public void run() { + while (true) { + try { + char[] len = forceRead(1); + char[] packet = forceRead(len[0]); + char cmd = packet[0]; + Log.i(TAG, String.format("received %s", commands[cmd])); + + switch (cmd) { + case MONITOR_CMD_SETFIELD: + if (packet.length >= 3) + setField(packet[1], packet[2], packet, 3); + + break; + + case MONITOR_CMD_GETFIELD: + if (packet.length == 4) + getField(packet[1], packet[2], packet[3]); + + break; + + case MONITOR_CMD_SCREENWATCH: + if (packet.length == 4) + screenWatch(packet[1], packet[2], packet[3]); + + break; + + case MONITOR_CMD_DEPRESS: + if (packet.length == 2) + depress(packet[1]); + + break; + + case MONITOR_CMD_SHOWURL: + if (packet.length > 1) + showUrl(packet, 1); + + break; + + case MONITOR_CMD_SWITCHSESSION: + if (packet.length == 1) + switchSession(); + + break; + + case MONITOR_CMD_CURSORREQUEST: + if (packet.length == 1) + cursorRequest(); + + break; + + default: + break; + } + } + catch (IOException e) { + if (!is_closing) Log.e(TAG, "exception in MyReader.run()", e); + + break; + } + } + } + } + + class MyServiceConnection implements ServiceConnection { + public void onServiceConnected(ComponentName className, IBinder service) { + bound = service; + Log.i(TAG, "bound to service"); + + try { + InetAddress serverAddr = InetAddress.getByName(LOCALHOST); + int tries = 0; + while (tries < 10) { + try { + Thread.sleep(100); + monitor_socket = new Socket(serverAddr, MONITORPORT); + break; + } + catch (Exception e) { + monitor_socket = null; + Log.e(TAG, "exception connecting to monitor socket", e); + tries = tries + 1; + } + } + if (monitor_socket != null) { + Log.i(TAG, "connected to monitor socket, send init " + init); + monitor_in = monitor_socket.getInputStream(); + monitor_out = monitor_socket.getOutputStream(); + monitor_reader = new MyReader(monitor_in); + monitor_reader.start(); + String x = " " + init; + monitorWrite(MONITOR_CMD_INIT, x.toCharArray()); + char [] c; + + while (true) { + c = pending_commands.poll(); + + if (c == null) break; + + monitorWrite(c[1], c); + } + } + } + catch (IOException e) { + Log.e(TAG, "exception in onServiceConnected()", e); + } + } + public void onServiceDisconnected(ComponentName classNam) { + bound = null; + Log.i(TAG, "unbound from service"); + } + }; + + + public TerminalMonitor(Context parent, vt320 buffer, View view, HostBean host, String init) { + this.parent = parent; + this.buffer = buffer; + this.view = view; + this.host = host; + this.init = init; + // setup the windows->android keymapping + // http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731 + keymap = new HashMap<Integer, Integer>(); + keymap.put(0x08, vt320.KEY_BACK_SPACE); // vk_back + keymap.put(0x09, vt320.KEY_TAB); // vk_tab + keymap.put(0x0d, vt320.KEY_ENTER); // vk_return + keymap.put(0x1b, vt320.KEY_ESCAPE); // vk_escape + keymap.put(0x21, vt320.KEY_PAGE_UP); // vk_prior + keymap.put(0x22, vt320.KEY_PAGE_DOWN); // vk_next + keymap.put(0x23, vt320.KEY_END); // vk_end + keymap.put(0x24, vt320.KEY_HOME); // vk_home + keymap.put(0x25, vt320.KEY_LEFT); // vk_left + keymap.put(0x26, vt320.KEY_UP); // vk_up + keymap.put(0x27, vt320.KEY_RIGHT); // vk_right + keymap.put(0x28, vt320.KEY_DOWN); // vk_down + keymap.put(0x2d, vt320.KEY_INSERT); // vk_insert + keymap.put(0x2e, vt320.KEY_DELETE); // vk_delete + keymap.put(0x70, vt320.KEY_F1); // vk_f1 + keymap.put(0x71, vt320.KEY_F2); // vk_f2 + keymap.put(0x72, vt320.KEY_F3); // vk_f3 + keymap.put(0x73, vt320.KEY_F4); // vk_f4 + keymap.put(0x74, vt320.KEY_F5); // vk_f5 + keymap.put(0x75, vt320.KEY_F6); // vk_f6 + keymap.put(0x76, vt320.KEY_F7); // vk_f7 + keymap.put(0x77, vt320.KEY_F8); // vk_f8 + keymap.put(0x78, vt320.KEY_F9); // vk_f9 + keymap.put(0x79, vt320.KEY_F10); // vk_f10 + keymap.put(0x7a, vt320.KEY_F11); // vk_f11 + keymap.put(0x7b, vt320.KEY_F12); // vk_f12 + keymap.put(0x7c, vt320.KEY_F13); // vk_f13 + keymap.put(0x7d, vt320.KEY_F14); // vk_f14 + keymap.put(0x7e, vt320.KEY_F15); // vk_f15 + keymap.put(0x7f, vt320.KEY_F16); // vk_f16 + keymap.put(0x80, vt320.KEY_F17); // vk_f17 + keymap.put(0x81, vt320.KEY_F18); // vk_f18 + keymap.put(0x82, vt320.KEY_F19); // vk_f19 + keymap.put(0x83, vt320.KEY_F20); // vk_f20 + keymap.put(0x84, vt320.KEY_F21); // vk_f21 + keymap.put(0x85, vt320.KEY_F22); // vk_f22 + keymap.put(0x86, vt320.KEY_F23); // vk_f23 + keymap.put(0x87, vt320.KEY_F24); // vk_f24 + // bind to the monitor service + Intent intent = new Intent("com.five_ten_sg.connectbot.monitor.MonitorService"); + parent.bindService(intent, monitor_connection, Context.BIND_AUTO_CREATE); + Log.i(TAG, "constructor"); + } + + + public void Disconnect() { + if (monitor_reader != null) monitor_reader.closing(); + + try { + if (monitor_out != null) monitor_out.close(); + + if (monitor_in != null) monitor_in.close(); + + if (monitor_socket != null) monitor_socket.close(); + + Log.i(TAG, "disconnected from monitor socket"); + } + catch (IOException e) { + Log.e(TAG, "exception in Disconnect() closing sockets", e); + } + + monitor_reader = null; + monitor_out = null; + monitor_in = null; + monitor_socket = null; + + if (bound != null) parent.unbindService(monitor_connection); + + monitor_connection = null; + } + + + public char[] bytesToChars(byte[] b, int len) { + char[] c = new char[len >> 1]; + int bp = 0; + + for (int i = 0; i < c.length; i++) { + byte b1 = b[bp++]; + byte b2 = b[bp++]; + c[i] = (char)(((b1 & 0x00FF) << 8) + (b2 & 0x00FF)); + } + + return c; + } + + + public byte[] charsToBytes(char[] c) { + byte[] b = new byte[c.length << 1]; + int bp = 0; + + for (int i = 0; i < c.length; i++) { + b[bp++] = (byte)((c[i] & 0xff00) >> 8); + b[bp++] = (byte)(c[i] & 0x00ff); + } + + return b; + } + + + public synchronized void monitorWrite(char cmd, char[] c) { + try { + if (monitor_out != null) { + c[0] = (char)(c.length - 1); // number of chars following + c[1] = cmd; + Log.i(TAG, String.format("sending %s", commands[cmd])); + monitor_out.write(charsToBytes(c)); + monitor_out.flush(); + } + else { + c[1] = cmd; + pending_commands.offer(c); + } + } + catch (IOException e) { + Log.i(TAG, "exception in monitorWrite(), monitor died or closed the socket", e); + + try { + monitor_out.close(); + } + catch (IOException ee) { + Log.e(TAG, "exception in monitorWrite() closing output stream", ee); + } + + monitor_out = null; + } + }; + + public void resetWatch() { + start_line = 0; + end_line = 500; + start_column = 0; + end_column = 500; + }; + + public void sendScreen(char cmd) { + char lines = (char)(buffer.height & 0x0000ffff); + char columns = (char)(buffer.width & 0x0000ffff); + char[] arg = new char[4 + lines * columns]; + arg[2] = lines; + arg[3] = columns; + int base = 4; + + for (int i = 0; i < lines; i++) { + System.arraycopy(buffer.charArray[buffer.screenBase + i], 0, arg, base, columns); + base += columns; + } + + monitorWrite(cmd, arg); + resetWatch(); + } + + public synchronized void activate() { + sendScreen(MONITOR_CMD_ACTIVATE); + cursorMoved(CURSOR_SCREEN_CHANGE); + } + + public synchronized void keyState(boolean down) { + char[] arg = new char[3]; + arg[2] = (char)((down) ? 1 : 0); + monitorWrite(MONITOR_CMD_KEYSTATE, arg); + } + + public synchronized void cursorMove(int l, int c) { + if ((to_line != l) || (to_column != c)) moved = true; + + to_line = l; + to_column = c; + } + + public void cursorMoved(char why) { + char[] arg = new char[5]; + arg[2] = (char)(to_line & 0x0000ffff); + arg[3] = (char)(to_column & 0x0000ffff); + arg[4] = why; + monitorWrite(MONITOR_CMD_CURSORMOVE, arg); + moved = false; + } + + public void testMoved() { + if (moved) cursorMoved(CURSOR_USER_KEY); + } + + public synchronized void testChanged() { + if (modified) { + modified = false; + sendScreen(MONITOR_CMD_SCREENCHANGE); + cursorMoved(CURSOR_SCREEN_CHANGE); + } + else { + if (moved) cursorMoved(CURSOR_SCREEN_CHANGE); + } + } + + public synchronized void screenChanged(int llow, int lhigh, int clow, int chigh) { + if ((start_line <= lhigh) && (llow <= end_line) && (start_column <= chigh) && (clow <= end_column)) { + modified = true; + } + } + + public synchronized void screenChanged(int l, int c) { + screenChanged(l, l, c, c); + } + + public synchronized void setField(int l, int c, char[] data, int offset) { + int len = data.length - offset; + char[] da = new char[len]; + System.arraycopy(data, offset, da, 0, len); + Log.i(TAG, String.format("setField(line %d, col %d, value %s)", l, c, new String(da))); + + if ((l > 60000) || (c > 60000)) { + l = -1; + c = -1; + } + else { + // ignore setfield outside screen boundaries + if ((l >= buffer.height) || (c + len > buffer.width)) return; + } + + buffer.setField(l, c, da); + } + + public synchronized void showUrl(char [] data, int offset) { + char[] da = new char[data.length - offset]; + System.arraycopy(data, offset, da, 0, data.length - offset); + String url = new String(da); + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + parent.startActivity(intent); + } + + public synchronized void getField(int l, int c, int len) { + Log.i(TAG, String.format("getField(line %d, col %d, len %d)", l, c, len)); + char[] arg2 = new char[4 + len]; + arg2[2] = (char)(l & 0x0000ffff); + arg2[3] = (char)(c & 0x0000ffff); + int base = 4; + + if ((l >= buffer.height) || (c + len > buffer.width)) { + Arrays.fill(arg2, base, base + len, ' '); + } + else { + System.arraycopy(buffer.charArray[buffer.screenBase + l], c, arg2, base, len); + } + + char[] da = new char[len]; + System.arraycopy(arg2, base, da, 0, len); + Log.i(TAG, String.format("getField value %s", new String(da))); + + monitorWrite(MONITOR_CMD_FIELDVALUE, arg2); + } + + public synchronized void screenWatch(int l, int c, int len) { + Log.i(TAG, String.format("screenWatch(line %d, col %d, len %d)", l, c, len)); + start_line = l; + end_line = l; + start_column = c; + end_column = c + len - 1; + } + + public synchronized void depress(int vk_key) { + Log.i(TAG, String.format("depress(%d)", vk_key)); + Integer x = keymap.get(new Integer(vk_key)); + + if (x != null) buffer.keyDepressed(x, ' ', 0); + } + + public synchronized void switchSession() { + Log.i(TAG, "switchSession()"); + Intent intent = new Intent(parent, ConsoleActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(host.getUri()); + parent.startActivity(intent); + } + + + public synchronized void cursorRequest() { + cursorMoved(CURSOR_REQUESTED); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/transport/AbsTransport.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,413 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.transport; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.bean.PortForwardBean; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalKeyListener; +import com.five_ten_sg.connectbot.service.TerminalManager; +import android.content.Context; +import android.net.Uri; +import android.util.Log; +import de.mud.terminal.vt320; + +/** + * @author Kenny Root + * + */ +public abstract class AbsTransport { + protected String TAG; + protected TerminalManager manager; + protected TerminalBridge bridge; + protected String homeDirectory; + protected HostBean host; + protected vt320 buffer = null; + protected String emulation; + + class vt320Default extends vt320 { + @Override + public void debug(String s) { + Log.d(TAG, s); + } + + // monitor injecting a field + //@Override + //public void setField(int l, int c, char [] data) + // implementation in the base vt320 + + // terminal key listener found special key, send notification to monitor + @Override + public void monitorKey(boolean down) { + if (bridge.monitor != null) bridge.monitor.keyState(down); + } + + // terminal key listener sending to the host + @Override + public void write(byte[] b) { + try { + AbsTransport.this.write(b); + } + catch (IOException e) { + Log.e(TAG, "Problem writing outgoing data in vt320() thread", e); + } + } + @Override + public void write(int b) { + try { + AbsTransport.this.write(b); + } + catch (IOException e) { + Log.e(TAG, "Problem writing outgoing data in vt320() thread", e); + } + } + + // We don't use telnet sequences. + @Override + public void sendTelnetCommand(byte cmd) { + } + // We don't want remote to resize our window. + @Override + public void setWindowSize(int c, int r) { + } + // play beep noise + @Override + public void beep() { + if ((bridge.parent != null) && (bridge.parent.isShown())) + manager.playBeep(); + else + manager.sendActivityNotification(host); + } + + // test for changed screen contents + @Override + public void testChanged() { + if (bridge.monitor != null) bridge.monitor.testChanged(); + } + // relay socket writing to the screen + // bridge.monitor placement of new characters + @Override + public void putChar(int c, int l, char ch, int attributes) { + if (bridge.monitor != null) bridge.monitor.screenChanged(l, c); + + super.putChar(c, l, ch, attributes); + } + @Override + public void insertChar(int c, int l, char ch, int attributes) { + if (bridge.monitor != null) bridge.monitor.screenChanged(l, l, c, width - 1); + + super.insertChar(c, l, ch, attributes); + } + @Override + public void insertLine(int l, int n, boolean scrollDown) { + if (bridge.monitor != null) { + if (scrollDown) bridge.monitor.screenChanged(l, height - 1, 0, width - 1); + else bridge.monitor.screenChanged(0, l, 0, width - 1); + } + + super.insertLine(l, n, scrollDown); + } + @Override + public void deleteLine(int l) { + if (bridge.monitor != null) bridge.monitor.screenChanged(l, height - 1, 0, width - 1); + + super.deleteLine(l); + } + @Override + public void deleteChar(int c, int l) { + if (bridge.monitor != null) bridge.monitor.screenChanged(l, l, c, width - 1); + + super.deleteChar(c, l); + } + @Override + public void setCursorPosition(int c, int l) { + if (bridge.monitor != null) bridge.monitor.cursorMove(l, c); + + super.setCursorPosition(c, l); + } + + }; + + + public AbsTransport() {} + + /** + * @return protocol part of the URI + */ + public static String getProtocolName() { + return "unknown"; + } + + /** + * Encode the current transport into a URI that can be passed via intent calls. + * @return URI to host + */ + public abstract Uri getUri(String input); + + + /** + * Causes transport to connect to the target host. After connecting but before a + * session is started, must call back to {@link TerminalBridge#onConnected()}. + * After that call a session may be opened. + */ + public abstract void connect(); + + /** + * Checks if read() will block. If there are no bytes remaining in + * the underlying transport, return true. + */ + public abstract boolean willBlock(); + + /** + * Reads from the transport. Transport must support reading into a byte array + * <code>buffer</code> at the start of <code>offset</code> and a maximum of + * <code>length</code> bytes. If the remote host disconnects, throw an + * {@link IOException}. + * @param buffer byte buffer to store read bytes into + * @param offset where to start writing in the buffer + * @param length maximum number of bytes to read + * @return number of bytes read + * @throws IOException when remote host disconnects + */ + public abstract int read(byte[] buffer, int offset, int length) throws IOException; + + /** + * Writes to the transport. If the host is not yet connected, simply return without + * doing anything. An {@link IOException} should be thrown if there is an error after + * connection. + * @param buffer bytes to write to transport + * @throws IOException when there is a problem writing after connection + */ + public abstract void write(byte[] buffer) throws IOException; + + /** + * Writes to the transport. See {@link #write(byte[])} for behavior details. + * @param c character to write to the transport + * @throws IOException when there is a problem writing after connection + */ + public abstract void write(int c) throws IOException; + + /** + * Flushes the write commands to the transport. + * @throws IOException when there is a problem writing after connection + */ + public abstract void flush() throws IOException; + + /** + * Closes the connection to the terminal. Note that the resulting failure to read + * should call {@link TerminalBridge#dispatchDisconnect(boolean)}. + */ + public abstract void close(); + + /** + * Tells the transport what dimensions the display is currently + * @param columns columns of text + * @param rows rows of text + * @param width width in pixels + * @param height height in pixels + */ + public abstract void setDimensions(int columns, int rows, int width, int height); + + public void setOptions(Map<String, String> options) { + // do nothing + } + + public Map<String, String> getOptions() { + return null; + } + + public void setCompression(boolean compression) { + // do nothing + } + + public void setHttpproxy(String httpproxy) { + // do nothing + } + + public void setUseAuthAgent(String useAuthAgent) { + // do nothing + } + + public String getEmulation() { + return emulation; + } + + protected vt320 setupTransportBuffer() { + int scrollback = (host.getWantSession()) ? manager.getScrollback() : 0; + buffer.setBufferSize(scrollback); + buffer.setDisplay(bridge); + return buffer; + } + + public vt320 getTransportBuffer() { + buffer = new vt320Default(); + return setupTransportBuffer(); + } + + public void setLinks(TerminalManager manager, TerminalBridge bridge, String homeDirectory, HostBean host, String emulation) { + this.manager = manager; + this.bridge = bridge; + this.homeDirectory = homeDirectory; + this.host = host; + this.emulation = emulation; + } + + /** + * Whether or not this transport type can forward ports. + * @return true on ability to forward ports + */ + public boolean canForwardPorts() { + return false; + } + + /** + * Adds the {@link PortForwardBean} to the list. + * @param portForward the port forward bean to add + * @return true on successful addition + */ + public boolean addPortForward(PortForwardBean portForward) { + return false; + } + + /** + * Enables a port forward member. After calling this method, the port forward should + * be operational iff it could be enabled by the transport. + * @param portForward member of our current port forwards list to enable + * @return true on successful port forward setup + */ + public boolean enablePortForward(PortForwardBean portForward) { + return false; + } + + /** + * Disables a port forward member. After calling this method, the port forward should + * be non-functioning iff it could be disabled by the transport. + * @param portForward member of our current port forwards list to enable + * @return true on successful port forward tear-down + */ + public boolean disablePortForward(PortForwardBean portForward) { + return false; + } + + /** + * Removes the {@link PortForwardBean} from the available port forwards. + * @param portForward the port forward bean to remove + * @return true on successful removal + */ + public boolean removePortForward(PortForwardBean portForward) { + return false; + } + + /** + * Gets a list of the {@link PortForwardBean} currently used by this transport. + * @return the list of port forwards + */ + public List<PortForwardBean> getPortForwards() { + return null; + } + + /** + * Whether or not this transport type can transfer files. + * @return true on ability to transfer files + */ + public boolean canTransferFiles() { + return false; + } + + /** + * Downloads the specified remote file to a local folder. + * @param remoteFile The path to the remote file to be downloaded. Must be non-null. + * @param localFolder The path to local folder. Null = default external storage folder. + * @return true on success, false on failure + */ + public boolean downloadFile(String remoteFile, String localFolder) { + return false; + } + + /** + * Uploads the specified local file to the remote host. + * @param localFile The path to the local file to be uploaded. Must be non-null. + * @param remoteFolder The path to the remote directory. Null == default remote directory. + * @return true on success, false on failure + */ + public boolean uploadFile(String localFile, String remoteFile, + String remoteFolder, String mode) { + return false; + } + + + /** + * @return int default port for protocol + */ + public abstract int getDefaultPort(); + public abstract boolean isConnected(); + public abstract boolean isSessionOpen(); + public abstract boolean isAuthenticated(); + + /** + * @param username + * @param hostname + * @param port + * @return + */ + public abstract String getDefaultNickname(String username, String hostname, int port); + + /** + * @param uri + * @param selectionKeys + * @param selectionValues + */ + public abstract void getSelectionArgs(Uri uri, Map<String, String> selection); + + /** + * @param uri + * @return + */ + public abstract HostBean createHost(Uri uri); + + /** + * @param context context containing the correct resources + * @return string that hints at the format for connection + */ + public abstract String getFormatHint(Context context); + + /** + * @return do we use the network + */ + public abstract boolean usesNetwork(); + + /** + * @return do we need a relay object to read from the transport + * and send the data into the vt320 buffer + */ + public boolean needsRelay() { + return true; + } + + /** + * @return a key listener + */ + public TerminalKeyListener getTerminalKeyListener() { + return new TerminalKeyListener(manager, bridge, buffer, host.getEncoding()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/transport/Local.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,226 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.transport; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Map; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.util.HostDatabase; +import android.content.Context; +import android.net.Uri; +import android.util.Log; + +import com.google.ase.Exec; + +/** + * @author Kenny Root + * + */ +public class Local extends AbsTransport { + private static final String TAG = "ConnectBot.Local"; + private static final String PROTOCOL = "local"; + private static final String DEFAULT_URI = "local:#Local"; + + private FileDescriptor shellFd; + private FileInputStream is; + private FileOutputStream os; + + /** + * + */ + public Local() { + } + + + public static String getProtocolName() { + return PROTOCOL; + } + + + public Uri getUri(String input) { + Uri uri = Uri.parse(DEFAULT_URI); + + if (input != null && input.length() > 0) { + uri = uri.buildUpon().fragment(input).build(); + } + + return uri; + } + + + @Override + public void connect() { + int[] pids = new int[1]; + + try { + shellFd = Exec.createSubprocess("/system/bin/sh", "-", null, pids); + } + catch (Exception e) { + bridge.outputLine(manager.res.getString(R.string.local_shell_unavailable)); + Log.e(TAG, "Cannot start local shell", e); + return; + } + + final int shellPid = pids[0]; + Runnable exitWatcher = new Runnable() { + public void run() { + Exec.waitFor(shellPid); + bridge.dispatchDisconnect(false); + } + }; + Thread exitWatcherThread = new Thread(exitWatcher); + exitWatcherThread.setName("LocalExitWatcher"); + exitWatcherThread.setDaemon(true); + exitWatcherThread.start(); + is = new FileInputStream(shellFd); + os = new FileOutputStream(shellFd); + bridge.onConnected(); + } + + + @Override + public boolean willBlock() { + if (is == null) return true; + + try { + return is.available() == 0; + } + catch (Exception e) { + return true; + } + } + + @Override + public int read(byte[] buffer, int start, int len) throws IOException { + if (is == null) { + bridge.dispatchDisconnect(false); + throw new IOException("session closed"); + } + + return is.read(buffer, start, len); + } + + @Override + public void write(byte[] buffer) throws IOException { + if (os != null) + os.write(buffer); + } + + @Override + public void write(int c) throws IOException { + if (os != null) + os.write(c); + } + + @Override + public void flush() throws IOException { + os.flush(); + } + + @Override + public void close() { + try { + if (os != null) { + os.close(); + os = null; + } + + if (is != null) { + is.close(); + is = null; + } + } + catch (IOException e) { + Log.e(TAG, "Couldn't close shell", e); + } + } + + @Override + public void setDimensions(int columns, int rows, int width, int height) { + try { + Exec.setPtyWindowSize(shellFd, rows, columns, width, height); + } + catch (Exception e) { + Log.e(TAG, "Couldn't resize pty", e); + } + } + + @Override + public int getDefaultPort() { + return 0; + } + + @Override + public boolean isConnected() { + return is != null && os != null; + } + + @Override + public boolean isSessionOpen() { + return isConnected(); + } + + @Override + public boolean isAuthenticated() { + return isConnected(); + } + + @Override + public String getDefaultNickname(String username, String hostname, int port) { + return DEFAULT_URI; + } + + @Override + public void getSelectionArgs(Uri uri, Map<String, String> selection) { + selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL); + selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment()); + } + + @Override + public HostBean createHost(Uri uri) { + HostBean host = new HostBean(); + host.setProtocol(PROTOCOL); + String nickname = uri.getFragment(); + + if (nickname == null || nickname.length() == 0) { + host.setNickname(getDefaultNickname(host.getUsername(), + host.getHostname(), host.getPort())); + } + else { + host.setNickname(uri.getFragment()); + } + + return host; + } + + public String getFormatHint(Context context) { + return context.getString(R.string.hostpref_nickname_title); + } + + @Override + public boolean usesNetwork() { + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/transport/SSH.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1152 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.transport; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.URL; +import java.net.MalformedURLException; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.bean.PortForwardBean; +import com.five_ten_sg.connectbot.bean.PubkeyBean; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.service.TerminalManager.KeyHolder; +import com.five_ten_sg.connectbot.util.HostDatabase; +import com.five_ten_sg.connectbot.util.PubkeyDatabase; +import com.five_ten_sg.connectbot.util.PubkeyUtils; +import android.content.Context; +import android.net.Uri; +import android.os.Environment; +import android.util.Log; + +import ch.ethz.ssh2.AuthAgentCallback; +import ch.ethz.ssh2.ChannelCondition; +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.ConnectionInfo; +import ch.ethz.ssh2.ConnectionMonitor; +import ch.ethz.ssh2.DynamicPortForwarder; +import ch.ethz.ssh2.InteractiveCallback; +import ch.ethz.ssh2.KnownHosts; +import ch.ethz.ssh2.LocalPortForwarder; +import ch.ethz.ssh2.SCPClient; +import ch.ethz.ssh2.ServerHostKeyVerifier; +import ch.ethz.ssh2.Session; +import ch.ethz.ssh2.HTTPProxyData; +import ch.ethz.ssh2.HTTPProxyException; +import ch.ethz.ssh2.crypto.PEMDecoder; +import ch.ethz.ssh2.signature.DSASHA1Verify; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; +import ch.ethz.ssh2.signature.RSASHA1Verify; + +/** + * @author Kenny Root + * + */ +public class SSH extends AbsTransport implements ConnectionMonitor, InteractiveCallback, AuthAgentCallback { + private static final String PROTOCOL = "ssh"; + private static final String TAG = "ConnectBot.SSH"; + private static final int DEFAULT_PORT = 22; + + private static final String AUTH_PUBLICKEY = "publickey", + AUTH_PASSWORD = "password", + AUTH_KEYBOARDINTERACTIVE = "keyboard-interactive"; + + private final static int AUTH_TRIES = 20; + + static final Pattern hostmask; + static { + hostmask = Pattern.compile("^(.+)@([0-9a-z.-]+)(:(\\d+))?$", Pattern.CASE_INSENSITIVE); + } + + private boolean compression = false; + private String httpproxy = null; + private volatile boolean authenticated = false; + private volatile boolean connected = false; + private volatile boolean sessionOpen = false; + + private boolean pubkeysExhausted = false; + private boolean interactiveCanContinue = true; + + private Connection connection; + private Session session; + private ConnectionInfo connectionInfo; + + private OutputStream stdin; + private InputStream stdout; + private InputStream stderr; + + private static final int conditions = ChannelCondition.STDOUT_DATA + | ChannelCondition.STDERR_DATA + | ChannelCondition.CLOSED + | ChannelCondition.EOF; + + private List<PortForwardBean> portForwards = new LinkedList<PortForwardBean>(); + + private int columns; + private int rows; + + private int width; + private int height; + + private String useAuthAgent = HostDatabase.AUTHAGENT_NO; + private String agentLockPassphrase; + + public class HostKeyVerifier implements ServerHostKeyVerifier { + public boolean verifyServerHostKey(String hostname, int port, + String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { + // read in all known hosts from hostdb + KnownHosts hosts = manager.hostdb.getKnownHosts(); + Boolean result; + String matchName = String.format(Locale.US, "%s:%d", hostname, port); + String fingerprint = KnownHosts.createHexFingerprint(serverHostKeyAlgorithm, serverHostKey); + String algorithmName; + + if ("ssh-rsa".equals(serverHostKeyAlgorithm)) + algorithmName = "RSA"; + else if ("ssh-dss".equals(serverHostKeyAlgorithm)) + algorithmName = "DSA"; + else if (serverHostKeyAlgorithm.startsWith("ecdsa-sha2-")) + algorithmName = "EC"; + else + algorithmName = serverHostKeyAlgorithm; + + switch (hosts.verifyHostkey(matchName, serverHostKeyAlgorithm, serverHostKey)) { + case KnownHosts.HOSTKEY_IS_OK: + bridge.outputLine(manager.res.getString(R.string.terminal_sucess, algorithmName, fingerprint)); + return true; + + case KnownHosts.HOSTKEY_IS_NEW: + // prompt user + bridge.outputLine(manager.res.getString(R.string.host_authenticity_warning, hostname)); + bridge.outputLine(manager.res.getString(R.string.host_fingerprint, algorithmName, fingerprint)); + result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_continue_connecting)); + + if (result == null) return false; + + if (result.booleanValue()) { + // save this key in known database + manager.hostdb.saveKnownHost(hostname, port, serverHostKeyAlgorithm, serverHostKey); + } + + return result.booleanValue(); + + case KnownHosts.HOSTKEY_HAS_CHANGED: + String header = String.format("@ %s @", + manager.res.getString(R.string.host_verification_failure_warning_header)); + char[] atsigns = new char[header.length()]; + Arrays.fill(atsigns, '@'); + String border = new String(atsigns); + bridge.outputLine(border); + bridge.outputLine(manager.res.getString(R.string.host_verification_failure_warning)); + bridge.outputLine(border); + bridge.outputLine(String.format(manager.res.getString(R.string.host_fingerprint), + algorithmName, fingerprint)); + // Users have no way to delete keys, so we'll prompt them for now. + result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_continue_connecting)); + + if (result == null) return false; + + if (result.booleanValue()) { + // save this key in known database + manager.hostdb.saveKnownHost(hostname, port, serverHostKeyAlgorithm, serverHostKey); + } + + return result.booleanValue(); + + default: + return false; + } + } + + } + + + public SSH() { + super(); + } + + + /** + * @return protocol part of the URI + */ + public static String getProtocolName() { + return PROTOCOL; + } + + + public Uri getUri(String input) { + Matcher matcher = hostmask.matcher(input); + + if (!matcher.matches()) + return null; + + StringBuilder sb = new StringBuilder(); + sb.append(PROTOCOL) + .append("://") + .append(Uri.encode(matcher.group(1))) + .append('@') + .append(matcher.group(2)); + String portString = matcher.group(4); + int port = DEFAULT_PORT; + + if (portString != null) { + try { + port = Integer.parseInt(portString); + + if (port < 1 || port > 65535) { + port = DEFAULT_PORT; + } + } + catch (NumberFormatException nfe) { + // Keep the default port + } + } + + if (port != DEFAULT_PORT) { + sb.append(':') + .append(port); + } + + sb.append("/#") + .append(Uri.encode(input)); + Uri uri = Uri.parse(sb.toString()); + return uri; + } + + + private void authenticate() { + try { + if (connection.authenticateWithNone(host.getUsername())) { + finishConnection(); + return; + } + } + catch (Exception e) { + Log.d(TAG, "Host does not support 'none' authentication."); + } + + bridge.outputLine(manager.res.getString(R.string.terminal_auth)); + + try { + long pubkeyId = host.getPubkeyId(); + + if (!pubkeysExhausted && + pubkeyId != HostDatabase.PUBKEYID_NEVER && + connection.isAuthMethodAvailable(host.getUsername(), AUTH_PUBLICKEY)) { + // if explicit pubkey defined for this host, then prompt for password as needed + // otherwise just try all in-memory keys held in terminalmanager + if (pubkeyId == HostDatabase.PUBKEYID_ANY) { + // try each of the in-memory keys + bridge.outputLine(manager.res + .getString(R.string.terminal_auth_pubkey_any)); + + for (Entry<String, KeyHolder> entry : manager.loadedKeypairs.entrySet()) { + if (entry.getValue().bean.isConfirmUse() + && !promptForPubkeyUse(entry.getKey())) + continue; + + if (this.tryPublicKey(host.getUsername(), entry.getKey(), + entry.getValue().pair)) { + finishConnection(); + break; + } + } + } + else { + bridge.outputLine(manager.res.getString(R.string.terminal_auth_pubkey_specific)); + // use a specific key for this host, as requested + PubkeyBean pubkey = manager.pubkeydb.findPubkeyById(pubkeyId); + + if (pubkey == null) + bridge.outputLine(manager.res.getString(R.string.terminal_auth_pubkey_invalid)); + else if (tryPublicKey(pubkey)) + finishConnection(); + } + + pubkeysExhausted = true; + } + else if (interactiveCanContinue && + connection.isAuthMethodAvailable(host.getUsername(), AUTH_KEYBOARDINTERACTIVE)) { + // this auth method will talk with us using InteractiveCallback interface + // it blocks until authentication finishes + bridge.outputLine(manager.res.getString(R.string.terminal_auth_ki)); + interactiveCanContinue = false; + + if (connection.authenticateWithKeyboardInteractive(host.getUsername(), this)) { + finishConnection(); + } + else { + bridge.outputLine(manager.res.getString(R.string.terminal_auth_ki_fail)); + } + } + else if (connection.isAuthMethodAvailable(host.getUsername(), AUTH_PASSWORD)) { + bridge.outputLine(manager.res.getString(R.string.terminal_auth_pass)); + String password = bridge.getPromptHelper().requestPasswordPrompt(null, + manager.res.getString(R.string.prompt_password)); + + if (password != null + && connection.authenticateWithPassword(host.getUsername(), password)) { + finishConnection(); + } + else { + bridge.outputLine(manager.res.getString(R.string.terminal_auth_pass_fail)); + } + } + else { + bridge.outputLine(manager.res.getString(R.string.terminal_auth_fail)); + } + } + catch (IllegalStateException e) { + Log.e(TAG, "Connection went away while we were trying to authenticate", e); + return; + } + catch (Exception e) { + Log.e(TAG, "Problem during handleAuthentication()", e); + } + } + + + /** + * Attempt connection with database row pointed to by cursor. + * @param cursor + * @return true for successful authentication + * @throws NoSuchAlgorithmException + * @throws InvalidKeySpecException + * @throws IOException + */ + private boolean tryPublicKey(PubkeyBean pubkey) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { + KeyPair pair = null; + + if (manager.isKeyLoaded(pubkey.getNickname())) { + // load this key from memory if its already there + Log.d(TAG, String.format("Found unlocked key '%s' already in-memory", pubkey.getNickname())); + + if (pubkey.isConfirmUse()) { + if (!promptForPubkeyUse(pubkey.getNickname())) + return false; + } + + pair = manager.getKey(pubkey.getNickname()); + } + else { + // otherwise load key from database and prompt for password as needed + String password = null; + + if (pubkey.isEncrypted()) { + password = bridge.getPromptHelper().requestPasswordPrompt(null, + manager.res.getString(R.string.prompt_pubkey_password, pubkey.getNickname())); + + // Something must have interrupted the prompt. + if (password == null) + return false; + } + + if (PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType())) { + // load specific key using pem format + pair = PEMDecoder.decode(new String(pubkey.getPrivateKey()).toCharArray(), password); + } + else { + // load using internal generated format + PrivateKey privKey; + + try { + privKey = PubkeyUtils.decodePrivate(pubkey.getPrivateKey(), + pubkey.getType(), password); + } + catch (Exception e) { + String message = String.format("Bad password for key '%s'. Authentication failed.", pubkey.getNickname()); + Log.e(TAG, message, e); + bridge.outputLine(message); + return false; + } + + PublicKey pubKey = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); + // convert key to trilead format + pair = new KeyPair(pubKey, privKey); + Log.d(TAG, "Unlocked key " + PubkeyUtils.formatKey(pubKey)); + } + + Log.d(TAG, String.format("Unlocked key '%s'", pubkey.getNickname())); + // save this key in memory + manager.addKey(pubkey, pair); + } + + return tryPublicKey(host.getUsername(), pubkey.getNickname(), pair); + } + + + private boolean tryPublicKey(String username, String keyNickname, KeyPair pair) throws IOException { + //bridge.outputLine(String.format("Attempting 'publickey' with key '%s' [%s]...", keyNickname, trileadKey.toString())); + boolean success = connection.authenticateWithPublicKey(username, pair); + + if (!success) + bridge.outputLine(manager.res.getString(R.string.terminal_auth_pubkey_fail, keyNickname)); + + return success; + } + + + /** + * Internal method to request actual PTY terminal once we've finished + * authentication. If called before authenticated, it will just fail. + */ + private void finishConnection() { + authenticated = true; + + for (PortForwardBean portForward : portForwards) { + try { + enablePortForward(portForward); + bridge.outputLine(manager.res.getString(R.string.terminal_enable_portfoward, portForward.getDescription())); + } + catch (Exception e) { + Log.e(TAG, "Error setting up port forward during connect", e); + } + } + + if (!host.getWantSession()) { + bridge.outputLine(manager.res.getString(R.string.terminal_no_session)); + bridge.onConnected(); + return; + } + + try { + session = connection.openSession(); + + if (!useAuthAgent.equals(HostDatabase.AUTHAGENT_NO)) + session.requestAuthAgentForwarding(this); + + if (host.getWantX11Forward()) { + try { + session.requestX11Forwarding(host.getX11Host(), host.getX11Port(), null, false); + } + catch (IOException e2) { + Log.e(TAG, "Problem while trying to setup X11 forwarding in finishConnection()", e2); + } + } + + session.requestPTY(getEmulation(), columns, rows, width, height, null); + session.startShell(); + stdin = session.getStdin(); + stdout = session.getStdout(); + stderr = session.getStderr(); + sessionOpen = true; + bridge.onConnected(); + } + catch (IOException e1) { + Log.e(TAG, "Problem while trying to create PTY in finishConnection()", e1); + } + } + + + @Override + public void connect() { + connection = new Connection(host.getHostname(), host.getPort()); + connection.addConnectionMonitor(this); + + try { + connection.setCompression(compression); + } + catch (IOException e) { + Log.e(TAG, "Could not enable compression!", e); + } + + if (httpproxy != null && httpproxy.length() > 0) { + Log.d(TAG, "Want HTTP Proxy: " + httpproxy, null); + + try { + URL u; + + if (httpproxy.startsWith("http://")) { + u = new URL(httpproxy); + } + else { + u = new URL("http://" + httpproxy); + } + + connection.setProxyData(new HTTPProxyData( + u.getHost(), + u.getPort(), + u.getUserInfo(), + u.getAuthority())); + bridge.outputLine("Connecting via proxy: " + httpproxy); + } + catch (MalformedURLException e) { + Log.e(TAG, "Could not parse proxy " + httpproxy, e); + // Display the reason in the text. + bridge.outputLine("Bad proxy URL: " + httpproxy); + onDisconnect(); + return; + } + } + + try { + /* Uncomment when debugging SSH protocol: + DebugLogger logger = new DebugLogger() { + + public void log(int level, String className, String message) { + Log.d("SSH", message); + } + + }; + Logger.enabled = true; + Logger.logger = logger; + */ + connectionInfo = connection.connect(new HostKeyVerifier()); + connected = true; + + if (connectionInfo.clientToServerCryptoAlgorithm + .equals(connectionInfo.serverToClientCryptoAlgorithm) + && connectionInfo.clientToServerMACAlgorithm + .equals(connectionInfo.serverToClientMACAlgorithm)) { + bridge.outputLine(manager.res.getString(R.string.terminal_using_algorithm, + connectionInfo.clientToServerCryptoAlgorithm, + connectionInfo.clientToServerMACAlgorithm)); + } + else { + bridge.outputLine(manager.res.getString( + R.string.terminal_using_c2s_algorithm, + connectionInfo.clientToServerCryptoAlgorithm, + connectionInfo.clientToServerMACAlgorithm)); + bridge.outputLine(manager.res.getString( + R.string.terminal_using_s2c_algorithm, + connectionInfo.serverToClientCryptoAlgorithm, + connectionInfo.serverToClientMACAlgorithm)); + } + } + catch (HTTPProxyException e) { + Log.e(TAG, "Failed to connect to HTTP Proxy", e); + // Display the reason in the text. + bridge.outputLine("Failed to connect to HTTP Proxy."); + onDisconnect(); + return; + } + catch (IOException e) { + Log.e(TAG, "Problem in SSH connection thread during authentication", e); + // Display the reason in the text. + Throwable t = e.getCause(); + String m = (t == null) ? e.getMessage() : t.getMessage(); + bridge.outputLine(m); + onDisconnect(); + return; + } + + try { + // enter a loop to keep trying until authentication + int tries = 0; + + while (connected && !connection.isAuthenticationComplete() && tries++ < AUTH_TRIES) { + authenticate(); + // sleep to make sure we dont kill system + Thread.sleep(1000); + } + } + catch (Exception e) { + Log.e(TAG, "Problem in SSH connection thread during authentication", e); + } + } + + + @Override + public boolean willBlock() { + if (stdout == null) return true; + + try { + return stdout.available() == 0; + } + catch (Exception e) { + return true; + } + } + + + @Override + public int read(byte[] buffer, int start, int len) throws IOException { + int bytesRead = 0; + + if (session == null) + return 0; + + int newConditions = session.waitForCondition(conditions, 0); + + if ((newConditions & ChannelCondition.STDOUT_DATA) != 0) { + bytesRead = stdout.read(buffer, start, len); + } + + if ((newConditions & ChannelCondition.STDERR_DATA) != 0) { + byte discard[] = new byte[256]; + + while (stderr.available() > 0) { + stderr.read(discard); + } + } + + if ((newConditions & ChannelCondition.EOF) != 0) { + onDisconnect(); + throw new IOException("Remote end closed connection"); + } + + return bytesRead; + } + + + @Override + public void write(byte[] buffer) throws IOException { + if (stdin != null) + stdin.write(buffer); + } + + + @Override + public void write(int c) throws IOException { + if (stdin != null) + stdin.write(c); + } + + + @Override + public void flush() throws IOException { + if (stdin != null) + stdin.flush(); + } + + + public void connectionLost(Throwable reason) { + onDisconnect(); + } + + + private void onDisconnect() { + close(); + bridge.dispatchDisconnect(false); + } + + + @Override + public void close() { + connected = false; + + if (session != null) { + session.close(); + session = null; + } + + if (connection != null) { + connection.close(); + connection = null; + } + } + + + @Override + public void setDimensions(int columns, int rows, int width, int height) { + this.columns = columns; + this.rows = rows; + + if (sessionOpen) { + try { + session.resizePTY(columns, rows, width, height); + } + catch (IOException e) { + Log.e(TAG, "Couldn't send resize PTY packet", e); + } + } + } + + + @Override + public void setOptions(Map<String, String> options) { + if (options.containsKey("compression")) + compression = Boolean.parseBoolean(options.get("compression")); + + if (options.containsKey("httpproxy")) + httpproxy = options.get("httpproxy"); + } + + + @Override + public Map<String, String> getOptions() { + Map<String, String> options = new HashMap<String, String>(); + options.put("compression", Boolean.toString(compression)); + + if (httpproxy != null) + options.put("httpproxy", httpproxy); + + return options; + } + + + @Override + public void setCompression(boolean compression) { + this.compression = compression; + } + + + @Override + public void setHttpproxy(String httpproxy) { + this.httpproxy = httpproxy; + } + + + @Override + public void setUseAuthAgent(String useAuthAgent) { + this.useAuthAgent = useAuthAgent; + } + + @Override + public boolean canForwardPorts() { + return true; + } + + @Override + public List<PortForwardBean> getPortForwards() { + return portForwards; + } + + @Override + public boolean addPortForward(PortForwardBean portForward) { + return portForwards.add(portForward); + } + + @Override + public boolean removePortForward(PortForwardBean portForward) { + // Make sure we don't have a phantom forwarder. + disablePortForward(portForward); + return portForwards.remove(portForward); + } + + @Override + public boolean enablePortForward(PortForwardBean portForward) { + if (!portForwards.contains(portForward)) { + Log.e(TAG, "Attempt to enable port forward not in list"); + return false; + } + + if (!authenticated) + return false; + + if (HostDatabase.PORTFORWARD_LOCAL.equals(portForward.getType())) { + LocalPortForwarder lpf = null; + + try { + lpf = connection.createLocalPortForwarder( + new InetSocketAddress(InetAddress.getLocalHost(), portForward.getSourcePort()), + portForward.getDestAddr(), portForward.getDestPort()); + } + catch (Exception e) { + Log.e(TAG, "Could not create local port forward", e); + return false; + } + + if (lpf == null) { + Log.e(TAG, "returned LocalPortForwarder object is null"); + return false; + } + + portForward.setIdentifier(lpf); + portForward.setEnabled(true); + return true; + } + else if (HostDatabase.PORTFORWARD_REMOTE.equals(portForward.getType())) { + try { + connection.requestRemotePortForwarding("", portForward.getSourcePort(), portForward.getDestAddr(), portForward.getDestPort()); + } + catch (Exception e) { + Log.e(TAG, "Could not create remote port forward", e); + return false; + } + + portForward.setEnabled(true); + return true; + } + else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(portForward.getType())) { + DynamicPortForwarder dpf = null; + + try { + dpf = connection.createDynamicPortForwarder( + new InetSocketAddress(InetAddress.getLocalHost(), portForward.getSourcePort())); + } + catch (Exception e) { + Log.e(TAG, "Could not create dynamic port forward", e); + return false; + } + + portForward.setIdentifier(dpf); + portForward.setEnabled(true); + return true; + } + else { + // Unsupported type + Log.e(TAG, String.format("attempt to forward unknown type %s", portForward.getType())); + return false; + } + } + + @Override + public boolean disablePortForward(PortForwardBean portForward) { + if (!portForwards.contains(portForward)) { + Log.e(TAG, "Attempt to disable port forward not in list"); + return false; + } + + if (!authenticated) + return false; + + if (HostDatabase.PORTFORWARD_LOCAL.equals(portForward.getType())) { + LocalPortForwarder lpf = null; + lpf = (LocalPortForwarder)portForward.getIdentifier(); + + if (!portForward.isEnabled() || lpf == null) { + Log.d(TAG, String.format("Could not disable %s; it appears to be not enabled or have no handler", portForward.getNickname())); + return false; + } + + portForward.setEnabled(false); + + try { + lpf.close(); + } + catch (IOException e) { + Log.e(TAG, "Could not stop local port forwarder, setting enabled to false", e); + return false; + } + + return true; + } + else if (HostDatabase.PORTFORWARD_REMOTE.equals(portForward.getType())) { + portForward.setEnabled(false); + + try { + connection.cancelRemotePortForwarding(portForward.getSourcePort()); + } + catch (IOException e) { + Log.e(TAG, "Could not stop remote port forwarding, setting enabled to false", e); + return false; + } + + return true; + } + else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(portForward.getType())) { + DynamicPortForwarder dpf = null; + dpf = (DynamicPortForwarder)portForward.getIdentifier(); + + if (!portForward.isEnabled() || dpf == null) { + Log.d(TAG, String.format("Could not disable %s; it appears to be not enabled or have no handler", portForward.getNickname())); + return false; + } + + portForward.setEnabled(false); + + try { + dpf.close(); + } + catch (IOException e) { + Log.e(TAG, "Could not stop dynamic port forwarder, setting enabled to false", e); + return false; + } + + return true; + } + else { + // Unsupported type + Log.e(TAG, String.format("attempt to forward unknown type %s", portForward.getType())); + return false; + } + } + + @Override + public boolean canTransferFiles() { + return true; + } + + @Override + public boolean downloadFile(String remoteFile, String localFolder) { + try { + SCPClient client = new SCPClient(connection); + + if (localFolder == null || localFolder == "") + localFolder = Environment.getExternalStorageDirectory().getAbsolutePath(); + + File dir = new File(localFolder); + dir.mkdirs(); + client.get(remoteFile, localFolder); + return true; + } + catch (IOException e) { + Log.e(TAG, "Could not download remote file", e); + return false; + } + } + + @Override + public boolean uploadFile(String localFile, String remoteFile, + String remoteFolder, String mode) { + try { + SCPClient client = new SCPClient(connection); + + if (remoteFolder == null) + remoteFolder = ""; + + if (remoteFile == null || remoteFile == "") + client.put(localFile, remoteFolder, mode); + else + client.put(localFile, remoteFile, remoteFolder, mode); + + return true; + } + catch (IOException e) { + Log.e(TAG, "Could not upload local file", e); + return false; + } + } + + + @Override + public int getDefaultPort() { + return DEFAULT_PORT; + } + + + @Override + public boolean isConnected() { + return connected; + } + + + @Override + public boolean isSessionOpen() { + return sessionOpen; + } + + + @Override + public boolean isAuthenticated() { + return authenticated; + } + + + @Override + public String getDefaultNickname(String username, String hostname, int port) { + if (port == DEFAULT_PORT) { + return String.format(Locale.US, "%s@%s", username, hostname); + } + else { + return String.format(Locale.US, "%s@%s:%d", username, hostname, port); + } + } + + + @Override + public void getSelectionArgs(Uri uri, Map<String, String> selection) { + selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL); + selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment()); + selection.put(HostDatabase.FIELD_HOST_HOSTNAME, uri.getHost()); + int port = uri.getPort(); + + if (port < 0) + port = DEFAULT_PORT; + + selection.put(HostDatabase.FIELD_HOST_PORT, Integer.toString(port)); + selection.put(HostDatabase.FIELD_HOST_USERNAME, uri.getUserInfo()); + } + + + @Override + public HostBean createHost(Uri uri) { + HostBean host = new HostBean(); + host.setProtocol(PROTOCOL); + host.setHostname(uri.getHost()); + int port = uri.getPort(); + + if (port < 0) + port = DEFAULT_PORT; + + host.setPort(port); + host.setUsername(uri.getUserInfo()); + String nickname = uri.getFragment(); + + if (nickname == null || nickname.length() == 0) { + host.setNickname(getDefaultNickname(host.getUsername(), + host.getHostname(), host.getPort())); + } + else { + host.setNickname(uri.getFragment()); + } + + return host; + } + + + public String getFormatHint(Context context) { + return String.format("%s@%s:%s", + context.getString(R.string.format_username), + context.getString(R.string.format_hostname), + context.getString(R.string.format_port)); + } + + + /** + * @return do we use the network + */ + @Override + public boolean usesNetwork() { + return true; + } + + + /** + * Handle challenges from keyboard-interactive authentication mode. + */ + public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) { + interactiveCanContinue = true; + String[] responses = new String[numPrompts]; + + for (int i = 0; i < numPrompts; i++) { + // request response from user for each prompt + responses[i] = bridge.promptHelper.requestPasswordPrompt(instruction, prompt[i]); + } + + return responses; + } + + public Map<String, byte[]> retrieveIdentities() { + Map<String, byte[]> pubKeys = new HashMap<String, byte[]> (manager.loadedKeypairs.size()); + + for (Entry<String, KeyHolder> entry : manager.loadedKeypairs.entrySet()) { + KeyPair pair = entry.getValue().pair; + + try { + PrivateKey privKey = pair.getPrivate(); + + if (privKey instanceof RSAPrivateKey) { + RSAPublicKey pubkey = (RSAPublicKey) pair.getPublic(); + pubKeys.put(entry.getKey(), RSASHA1Verify.encodeSSHRSAPublicKey(pubkey)); + } + else if (privKey instanceof DSAPrivateKey) { + DSAPublicKey pubkey = (DSAPublicKey) pair.getPublic(); + pubKeys.put(entry.getKey(), DSASHA1Verify.encodeSSHDSAPublicKey(pubkey)); + } + else if (privKey instanceof ECPrivateKey) { + ECPublicKey pubkey = (ECPublicKey) pair.getPublic(); + pubKeys.put(entry.getKey(), ECDSASHA2Verify.encodeSSHECDSAPublicKey(pubkey)); + } + else + continue; + } + catch (IOException e) { + continue; + } + } + + return pubKeys; + } + + public KeyPair getKeyPair(byte[] publicKey) { + String nickname = manager.getKeyNickname(publicKey); + + if (nickname == null) + return null; + + if (useAuthAgent.equals(HostDatabase.AUTHAGENT_NO)) { + Log.e(TAG, ""); + return null; + } + else if (useAuthAgent.equals(HostDatabase.AUTHAGENT_CONFIRM) || + manager.loadedKeypairs.get(nickname).bean.isConfirmUse()) { + if (!promptForPubkeyUse(nickname)) + return null; + } + + return manager.getKey(nickname); + } + + private boolean promptForPubkeyUse(String nickname) { + Boolean result = bridge.promptHelper.requestBooleanPrompt(null, + manager.res.getString(R.string.prompt_allow_agent_to_use_key, + nickname)); + return result; + } + + public boolean addIdentity(KeyPair pair, String comment, boolean confirmUse, int lifetime) { + PubkeyBean pubkey = new PubkeyBean(); +// pubkey.setType(PubkeyDatabase.KEY_TYPE_IMPORTED); + pubkey.setNickname(comment); + pubkey.setConfirmUse(confirmUse); + pubkey.setLifetime(lifetime); + manager.addKey(pubkey, pair); + return true; + } + + public boolean removeAllIdentities() { + manager.loadedKeypairs.clear(); + return true; + } + + public boolean removeIdentity(byte[] publicKey) { + return manager.removeKey(publicKey); + } + + public boolean isAgentLocked() { + return agentLockPassphrase != null; + } + + public boolean requestAgentUnlock(String unlockPassphrase) { + if (agentLockPassphrase == null) + return false; + + if (agentLockPassphrase.equals(unlockPassphrase)) + agentLockPassphrase = null; + + return agentLockPassphrase == null; + } + + public boolean setAgentLock(String lockPassphrase) { + if (agentLockPassphrase != null) + return false; + + agentLockPassphrase = lockPassphrase; + return true; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/transport/TN5250.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,472 @@ +/* + * 510ConnectBot + * Copyright 2014 Carl Byington + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.transport; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.tn5250j.framework.tn5250.Screen5250; +import org.tn5250j.framework.tn5250.tnvt; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.bean.PortForwardBean; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalKeyListener; +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.util.HostDatabase; +import com.five_ten_sg.connectbot.util.PreferenceConstants; +import android.content.Context; +import android.net.Uri; +import android.util.Log; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.View; +import de.mud.terminal.vt320; + + +/** + * @author Carl Byington + * + */ +public class TN5250 extends AbsTransport { + private static final String PROTOCOL = "tn5250"; + private static final String TAG = "ConnectBot.tn5250"; + private static final int DEFAULT_PORT = 23; + + private Screen5250 screen52; + private tnvt handler = null; + private Socket socket; + private boolean connected = false; + + static final Pattern hostmask; + static { + hostmask = Pattern.compile("^([0-9a-z.-]+)(:(\\d+))?$", Pattern.CASE_INSENSITIVE); + } + + + class vt320x5250 extends vt320 { + private HashMap<Integer, Integer> controls; + private HashMap<Integer, String> mnemonics; + + public vt320x5250() { + this(80, 24); + } + + public vt320x5250(int width, int height) { + super(width, height); + controls = new HashMap<Integer, Integer>(); + controls.put(0x01, KEY_PAUSE); // ctrl-a -> [attn] + controls.put(0x08, KEY_BACK_SPACE); + controls.put(0x09, KEY_TAB); + controls.put(0x0d, KEY_ENTER); + controls.put(0x12, KEY_ESCAPE); // ctrl-r -> [reset] + controls.put(0x13, KEY_SYSREQ); // ctrl-s -> [sysreq] + controls.put(0x1b, KEY_ESCAPE); // esc -> [reset] + mnemonics = new HashMap<Integer, String>(); + mnemonics.put(KEY_PAUSE , "[attn]"); + mnemonics.put(KEY_F1 , "[pf1]"); + mnemonics.put(KEY_F2 , "[pf2]"); + mnemonics.put(KEY_F3 , "[pf3]"); + mnemonics.put(KEY_F4 , "[pf4]"); + mnemonics.put(KEY_F5 , "[pf5]"); + mnemonics.put(KEY_F6 , "[pf6]"); + mnemonics.put(KEY_F7 , "[pf7]"); + mnemonics.put(KEY_F8 , "[pf8]"); + mnemonics.put(KEY_F9 , "[pf9]"); + mnemonics.put(KEY_F10 , "[pf10]"); + mnemonics.put(KEY_F11 , "[pf11]"); + mnemonics.put(KEY_F12 , "[pf12]"); + mnemonics.put(KEY_F13 , "[pf13]"); + mnemonics.put(KEY_F14 , "[pf14]"); + mnemonics.put(KEY_F15 , "[pf15]"); + mnemonics.put(KEY_F16 , "[pf16]"); + mnemonics.put(KEY_F17 , "[pf17]"); + mnemonics.put(KEY_F18 , "[pf18]"); + mnemonics.put(KEY_F19 , "[pf19]"); + mnemonics.put(KEY_F20 , "[pf20]"); + mnemonics.put(KEY_F21 , "[pf21]"); + mnemonics.put(KEY_F22 , "[pf22]"); + mnemonics.put(KEY_F23 , "[pf23]"); + mnemonics.put(KEY_F24 , "[pf24]"); + mnemonics.put(KEY_UP , "[up]"); + mnemonics.put(KEY_DOWN , "[down]"); + mnemonics.put(KEY_LEFT , "[left]"); + mnemonics.put(KEY_RIGHT , "[right]"); + mnemonics.put(KEY_PAGE_DOWN , "[pgdown]"); + mnemonics.put(KEY_PAGE_UP , "[pgup]"); + mnemonics.put(KEY_INSERT , "[insert]"); + mnemonics.put(KEY_DELETE , "[delete]"); + mnemonics.put(KEY_BACK_SPACE , "[backspace]"); + mnemonics.put(KEY_HOME , "[home]"); + mnemonics.put(KEY_END , "[end]"); + mnemonics.put(KEY_NUM_LOCK , ""); + mnemonics.put(KEY_CAPS_LOCK , ""); + mnemonics.put(KEY_SHIFT , ""); + mnemonics.put(KEY_CONTROL , ""); + mnemonics.put(KEY_ALT , ""); + mnemonics.put(KEY_ENTER , "[enter]"); + mnemonics.put(KEY_NUMPAD0 , "0"); + mnemonics.put(KEY_NUMPAD1 , "1"); + mnemonics.put(KEY_NUMPAD2 , "2"); + mnemonics.put(KEY_NUMPAD3 , "3"); + mnemonics.put(KEY_NUMPAD4 , "4"); + mnemonics.put(KEY_NUMPAD5 , "5"); + mnemonics.put(KEY_NUMPAD6 , "6"); + mnemonics.put(KEY_NUMPAD7 , "7"); + mnemonics.put(KEY_NUMPAD8 , "8"); + mnemonics.put(KEY_NUMPAD9 , "9"); + mnemonics.put(KEY_DECIMAL , "."); + mnemonics.put(KEY_ADD , "+"); + mnemonics.put(KEY_ESCAPE , "[reset]"); + mnemonics.put(KEY_TAB , "[tab]"); + mnemonics.put(KEY_SYSREQ , "[sysreq]"); + } + + @Override + public void debug(String s) { + Log.d(TAG, s); + } + + // monitor injecting a field + @Override + public void setField(int l, int c, char [] data) { + screen52.setField(l, c, data); + } + + // monitor simulating key depress + @Override + public void keyDepressed(int keyCode, char keyChar, int modifiers) { + if (mnemonics.containsKey(keyCode)) { + String s = mnemonics.get(keyCode); + + if (s != "") screen52.sendKeys(s); + } + } + + // terminal key listener found special key, send notification to monitor + @Override + public void monitorKey(boolean down) { + if (bridge.monitor != null) bridge.monitor.keyState(down); + } + + // terminal key listener sending to local screen + @Override + public void write(byte[] b) { + screen52.sendKeys(new String(b)); + + if (bridge.monitor != null) bridge.monitor.testMoved(); + } + @Override + public void write(int b) { + if (controls.containsKey(b)) keyPressed(controls.get(b), ' ', 0); + else screen52.sendKeys(new String(new byte[] {(byte)b})); + + if (bridge.monitor != null) bridge.monitor.testMoved(); + } + @Override + public void keyPressed(int keyCode, char keyChar, int modifiers) { + keyDepressed(keyCode, keyChar, modifiers); + + if (bridge.monitor != null) bridge.monitor.testMoved(); + } + + // 5250 writing to the screen + // test for changed screen contents + @Override + public void testChanged() { + if (bridge.monitor != null) bridge.monitor.testChanged(); + } + @Override + public void putChar(int c, int l, char ch, int attributes) { + if (bridge.monitor != null) bridge.monitor.screenChanged(l, c); + + super.putChar(c, l, ch, attributes); + } + @Override + public void setCursorPosition(int c, int l) { + if (bridge.monitor != null) bridge.monitor.cursorMove(l, c); + + super.setCursorPosition(c, l); + redraw(); + } + }; + + + public TN5250() { + super(); + } + + + /** + * @return protocol part of the URI + */ + public static String getProtocolName() { + return PROTOCOL; + } + + + /** + * Encode the current transport into a URI that can be passed via intent calls. + * @return URI to host + */ + public Uri getUri(String input) { + Matcher matcher = hostmask.matcher(input); + + if (!matcher.matches()) + return null; + + StringBuilder sb = new StringBuilder(); + sb.append(PROTOCOL) + .append("://") + .append(matcher.group(1)); + String portString = matcher.group(3); + int port = DEFAULT_PORT; + + if (portString != null) { + try { + port = Integer.parseInt(portString); + + if (port < 1 || port > 65535) { + port = DEFAULT_PORT; + } + } + catch (NumberFormatException nfe) { + // Keep the default port + } + } + + if (port != DEFAULT_PORT) { + sb.append(':'); + sb.append(port); + } + + sb.append("/#") + .append(Uri.encode(input)); + Uri uri = Uri.parse(sb.toString()); + return uri; + } + + + /** + * Causes transport to connect to the target host. After connecting but before a + * session is started, must call back to {@link TerminalBridge#onConnected()}. + * After that call a session may be opened. + */ + @Override + public void connect() { + screen52 = new Screen5250(); + handler = new tnvt(screen52, true, true, bridge, manager); + screen52.setVT(handler); + screen52.setBuffer(buffer); + bridge.addFontSizeChangedListener(screen52); + connected = handler.connect(host, homeDirectory, buffer); + + if (connected) bridge.onConnected(); + } + + + /** + * Checks if read() will block. If there are no bytes remaining in + * the underlying transport, return true. + */ + @Override + public boolean willBlock() { + // we don't use a relay thread between the transport and the vt320 buffer + return true; + } + + + /** + * Reads from the transport. Transport must support reading into a byte array + * <code>buffer</code> at the start of <code>offset</code> and a maximum of + * <code>length</code> bytes. If the remote host disconnects, throw an + * {@link IOException}. + * @param buffer byte buffer to store read bytes into + * @param offset where to start writing in the buffer + * @param length maximum number of bytes to read + * @return number of bytes read + * @throws IOException when remote host disconnects + */ + public int read(byte[] buffer, int offset, int length) throws IOException { + // we don't use a relay thread between the transport and the vt320 buffer + return 0; + } + + + /** + * Writes to the transport. If the host is not yet connected, simply return without + * doing anything. An {@link IOException} should be thrown if there is an error after + * connection. + * @param buffer bytes to write to transport + * @throws IOException when there is a problem writing after connection + */ + public void write(byte[] buffer) throws IOException { + } + + + /** + * Writes to the transport. See {@link #write(byte[])} for behavior details. + * @param c character to write to the transport + * @throws IOException when there is a problem writing after connection + */ + public void write(int c) throws IOException { + } + + + /** + * Flushes the write commands to the transport. + * @throws IOException when there is a problem writing after connection + */ + public void flush() throws IOException { + } + + + /** + * Closes the connection to the terminal. + */ + public void close() { + handler.disconnect(); + connected = false; + bridge.removeFontSizeChangedListener(screen52); + bridge.dispatchDisconnect(false); + } + + + /** + * Tells the transport what dimensions the display is currently + * @param columns columns of text + * @param rows rows of text + * @param width width in pixels + * @param height height in pixels + */ + @Override + public void setDimensions(int columns, int rows, int width, int height) { + // do nothing + } + + + @Override + public vt320 getTransportBuffer() { + buffer = new vt320x5250(); + return setupTransportBuffer(); + } + + + @Override + public int getDefaultPort() { + return DEFAULT_PORT; + } + + + @Override + public boolean isConnected() { + return connected; + } + + + @Override + public boolean isSessionOpen() { + return connected; + } + + + @Override + public boolean isAuthenticated() { + return connected; + } + + + @Override + public String getDefaultNickname(String username, String hostname, int port) { + if (port == DEFAULT_PORT) { + return String.format("%s", hostname); + } + else { + return String.format("%s:%d", hostname, port); + } + } + + + @Override + public void getSelectionArgs(Uri uri, Map<String, String> selection) { + selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL); + selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment()); + selection.put(HostDatabase.FIELD_HOST_HOSTNAME, uri.getHost()); + int port = uri.getPort(); + + if (port < 0) port = DEFAULT_PORT; + + selection.put(HostDatabase.FIELD_HOST_PORT, Integer.toString(port)); + } + + + @Override + public HostBean createHost(Uri uri) { + HostBean host = new HostBean(); + host.setProtocol(PROTOCOL); + host.setHostname(uri.getHost()); + int port = uri.getPort(); + + if (port < 0) port = DEFAULT_PORT; + + host.setPort(port); + String nickname = uri.getFragment(); + + if (nickname == null || nickname.length() == 0) { + nickname = getDefaultNickname(host.getUsername(), host.getHostname(), host.getPort()); + } + + host.setNickname(nickname); + return host; + } + + + public String getFormatHint(Context context) { + return String.format("%s:%s", + context.getString(R.string.format_hostname), + context.getString(R.string.format_port)); + } + + + @Override + public boolean usesNetwork() { + return true; + } + + + @Override + public boolean needsRelay() { + // we don't use a relay thread between the transport and the vt320 buffer + return false; + } + + public TerminalKeyListener getTerminalKeyListener() { + return new TerminalKeyListener(manager, bridge, buffer, host.getEncoding()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/transport/Telnet.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,357 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.transport; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; +import com.five_ten_sg.connectbot.util.HostDatabase; + +import android.content.Context; +import android.net.Uri; +import android.util.Log; + +import de.mud.telnet.TelnetProtocolHandler; + + +/** + * Telnet transport implementation.<br/> + * Original idea from the JTA telnet package (de.mud.telnet) + * + * @author Kenny Root + * + */ +public class Telnet extends AbsTransport { + private static final String TAG = "ConnectBot.Telnet"; + private static final String PROTOCOL = "telnet"; + private static final int DEFAULT_PORT = 23; + + private TelnetProtocolHandler handler; + private Socket socket; + private InputStream is; + private OutputStream os; + private int width; + private int height; + private boolean connected = false; + + static final Pattern hostmask; + static { + hostmask = Pattern.compile("^([0-9a-z.-]+)(:(\\d+))?$", Pattern.CASE_INSENSITIVE); + } + + public Telnet() { + handler = new TelnetProtocolHandler() { + /** get the current terminal type */ + @Override + public String getTerminalType() { + return getEmulation(); + } + /** get the current window size */ + @Override + public int[] getWindowSize() { + return new int[] { width, height }; + } + /** notify about local echo */ + @Override + public void setLocalEcho(boolean echo) { + /* EMPTY */ + } + /** write data to our back end */ + @Override + public void write(byte[] b) throws IOException { + if (os != null) + os.write(b); + } + /** sent on IAC EOR (prompt terminator for remote access systems). */ + @Override + public void notifyEndOfRecord() { + } + @Override + protected String getCharsetName() { + Charset charset = bridge.getCharset(); + + if (charset != null) + return charset.name(); + else + return ""; + } + }; + } + + + public static String getProtocolName() { + return PROTOCOL; + } + + + public Uri getUri(String input) { + Matcher matcher = hostmask.matcher(input); + + if (!matcher.matches()) + return null; + + StringBuilder sb = new StringBuilder(); + sb.append(PROTOCOL) + .append("://") + .append(matcher.group(1)); + String portString = matcher.group(3); + int port = DEFAULT_PORT; + + if (portString != null) { + try { + port = Integer.parseInt(portString); + + if (port < 1 || port > 65535) { + port = DEFAULT_PORT; + } + } + catch (NumberFormatException nfe) { + // Keep the default port + } + } + + if (port != DEFAULT_PORT) { + sb.append(':'); + sb.append(port); + } + + sb.append("/#") + .append(Uri.encode(input)); + Uri uri = Uri.parse(sb.toString()); + return uri; + } + + + @Override + public void connect() { + try { + socket = new Socket(host.getHostname(), host.getPort()); + connected = true; + is = socket.getInputStream(); + os = socket.getOutputStream(); + bridge.onConnected(); + } + catch (UnknownHostException e) { + Log.d(TAG, "IO Exception connecting to host", e); + } + catch (IOException e) { + Log.d(TAG, "IO Exception connecting to host", e); + } + } + + + @Override + public boolean willBlock() { + if (is == null) return true; + + try { + return is.available() == 0; + } + catch (Exception e) { + return true; + } + } + + + @Override + public int read(byte[] buffer, int start, int len) throws IOException { + /* process all already read bytes */ + int n = 0; + + do { + n = handler.negotiate(buffer, start); + + if (n > 0) + return n; + } + while (n == 0); + + while (n <= 0) { + do { + n = handler.negotiate(buffer, start); + + if (n > 0) + return n; + } + while (n == 0); + + n = is.read(buffer, start, len); + + if (n < 0) { + bridge.dispatchDisconnect(false); + throw new IOException("Remote end closed connection."); + } + + handler.inputfeed(buffer, start, n); + n = handler.negotiate(buffer, start); + } + + return n; + } + + + @Override + public void write(byte[] buffer) throws IOException { + try { + if (os != null) + os.write(buffer); + } + catch (SocketException e) { + bridge.dispatchDisconnect(false); + } + } + + + @Override + public void write(int c) throws IOException { + try { + if (os != null) + os.write(c); + } + catch (SocketException e) { + bridge.dispatchDisconnect(false); + } + } + + + @Override + public void flush() throws IOException { + os.flush(); + } + + + @Override + public void close() { + connected = false; + + if (socket != null) + try { + socket.close(); + socket = null; + } + catch (IOException e) { + Log.d(TAG, "Error closing telnet socket.", e); + } + } + + + @Override + public void setDimensions(int columns, int rows, int width, int height) { + try { + handler.setWindowSize(columns, rows); + } + catch (IOException e) { + Log.e(TAG, "Couldn't resize remote terminal", e); + } + } + + + @Override + public int getDefaultPort() { + return DEFAULT_PORT; + } + + @Override + public boolean isConnected() { + return connected; + } + + @Override + public boolean isSessionOpen() { + return isConnected(); + } + + @Override + public boolean isAuthenticated() { + return isConnected(); + } + + + @Override + public String getDefaultNickname(String username, String hostname, int port) { + if (port == DEFAULT_PORT) { + return String.format("%s", hostname); + } + else { + return String.format("%s:%d", hostname, port); + } + } + + + @Override + public void getSelectionArgs(Uri uri, Map<String, String> selection) { + selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL); + selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment()); + selection.put(HostDatabase.FIELD_HOST_HOSTNAME, uri.getHost()); + int port = uri.getPort(); + + if (port < 0) + port = DEFAULT_PORT; + + selection.put(HostDatabase.FIELD_HOST_PORT, Integer.toString(port)); + } + + + @Override + public HostBean createHost(Uri uri) { + HostBean host = new HostBean(); + host.setProtocol(PROTOCOL); + host.setHostname(uri.getHost()); + int port = uri.getPort(); + + if (port < 0) + port = DEFAULT_PORT; + + host.setPort(port); + String nickname = uri.getFragment(); + + if (nickname == null || nickname.length() == 0) { + host.setNickname(getDefaultNickname(host.getUsername(), + host.getHostname(), host.getPort())); + } + else { + host.setNickname(uri.getFragment()); + } + + return host; + } + + + public String getFormatHint(Context context) { + return String.format("%s:%s", + context.getString(R.string.format_hostname), + context.getString(R.string.format_port)); + } + + @Override + public boolean usesNetwork() { + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/transport/TransportFactory.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,127 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.transport; + +import java.util.HashMap; +import java.util.Map; + +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.util.HostDatabase; +import android.content.Context; +import android.net.Uri; +import android.util.Log; + + +/** + * @author Kenny Root + * + */ +public class TransportFactory { + private static final String TAG = "ConnectBot.TransportFactory"; + + private static String[] transportNames = { + SSH.getProtocolName(), + TN5250.getProtocolName(), + Telnet.getProtocolName(), + Local.getProtocolName(), + }; + + /** + * @param protocol + * @return + */ + public static AbsTransport getTransport(String protocol) { + if (SSH.getProtocolName().equals(protocol)) { + return new SSH(); + } + else if (TN5250.getProtocolName().equals(protocol)) { + return new TN5250(); + } + else if (Telnet.getProtocolName().equals(protocol)) { + return new Telnet(); + } + else if (Local.getProtocolName().equals(protocol)) { + return new Local(); + } + else { + return null; + } + } + + public static Uri getUri(String protocol, String input) { + Log.d("TransportFactory", String.format( + "Attempting to discover URI for protocol=%s on input=%s", + protocol, input)); + AbsTransport t = getTransport(protocol); + + if (t == null) return null; + + return t.getUri(input); + } + + public static String[] getTransportNames() { + return transportNames; + } + + public static boolean isSameTransportType(AbsTransport a, AbsTransport b) { + if (a == null || b == null) + return false; + + return a.getClass().equals(b.getClass()); + } + + public static boolean canForwardPorts(String protocol) { + AbsTransport t = getTransport(protocol); + + if (t == null) return false; + + return t.canForwardPorts(); + } + + /** + * @param protocol text name of protocol + * @param context + * @return expanded format hint + */ + public static String getFormatHint(String protocol, Context context) { + AbsTransport t = getTransport(protocol); + + if (t == null) return "???"; + + return t.getFormatHint(context); + } + + /** + * @param hostdb Handle to HostDatabase + * @param uri URI to target server + * @return HostBean or null + */ + public static HostBean findHost(HostDatabase hostdb, Uri uri) { + AbsTransport transport = getTransport(uri.getScheme()); + Map<String, String> selection = new HashMap<String, String>(); + transport.getSelectionArgs(uri, selection); + + if (selection.size() == 0) { + Log.e(TAG, String.format("Transport %s failed to do something useful with URI=%s", + uri.getScheme(), uri.toString())); + throw new IllegalStateException("Failed to get needed selection arguments"); + } + + return hostdb.findHost(selection); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/Colors.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,91 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +/** + * @author Kenny Root + * + */ +public class Colors { + public final static Integer[] defaults = new Integer[] { + 0xff000000, // black // 0 + 0xffcc0000, // red // 1 + 0xff00cc00, // green // 2 + 0xffcccc00, // brown // 3 + 0xff0000cc, // blue // 4 + 0xffcc00cc, // purple // 5 + 0xff00cccc, // cyan // 6 + 0xffcccccc, // light grey // 7 + 0xff444444, // dark grey // 8 + 0xffff4444, // light red // 9 + 0xff44ff44, // light green // a + 0xffffff44, // yellow // b + 0xff4444ff, // light blue // c + 0xffff44ff, // light purple // d + 0xff44ffff, // light cyan // e + 0xffffffff, // white // f + 0xff000000, 0xff00005f, 0xff000087, 0xff0000af, 0xff0000d7, + 0xff0000ff, 0xff005f00, 0xff005f5f, 0xff005f87, 0xff005faf, + 0xff005fd7, 0xff005fff, 0xff008700, 0xff00875f, 0xff008787, + 0xff0087af, 0xff0087d7, 0xff0087ff, 0xff00af00, 0xff00af5f, + 0xff00af87, 0xff00afaf, 0xff00afd7, 0xff00afff, 0xff00d700, + 0xff00d75f, 0xff00d787, 0xff00d7af, 0xff00d7d7, 0xff00d7ff, + 0xff00ff00, 0xff00ff5f, 0xff00ff87, 0xff00ffaf, 0xff00ffd7, + 0xff00ffff, 0xff5f0000, 0xff5f005f, 0xff5f0087, 0xff5f00af, + 0xff5f00d7, 0xff5f00ff, 0xff5f5f00, 0xff5f5f5f, 0xff5f5f87, + 0xff5f5faf, 0xff5f5fd7, 0xff5f5fff, 0xff5f8700, 0xff5f875f, + 0xff5f8787, 0xff5f87af, 0xff5f87d7, 0xff5f87ff, 0xff5faf00, + 0xff5faf5f, 0xff5faf87, 0xff5fafaf, 0xff5fafd7, 0xff5fafff, + 0xff5fd700, 0xff5fd75f, 0xff5fd787, 0xff5fd7af, 0xff5fd7d7, + 0xff5fd7ff, 0xff5fff00, 0xff5fff5f, 0xff5fff87, 0xff5fffaf, + 0xff5fffd7, 0xff5fffff, 0xff870000, 0xff87005f, 0xff870087, + 0xff8700af, 0xff8700d7, 0xff8700ff, 0xff875f00, 0xff875f5f, + 0xff875f87, 0xff875faf, 0xff875fd7, 0xff875fff, 0xff878700, + 0xff87875f, 0xff878787, 0xff8787af, 0xff8787d7, 0xff8787ff, + 0xff87af00, 0xff87af5f, 0xff87af87, 0xff87afaf, 0xff87afd7, + 0xff87afff, 0xff87d700, 0xff87d75f, 0xff87d787, 0xff87d7af, + 0xff87d7d7, 0xff87d7ff, 0xff87ff00, 0xff87ff5f, 0xff87ff87, + 0xff87ffaf, 0xff87ffd7, 0xff87ffff, 0xffaf0000, 0xffaf005f, + 0xffaf0087, 0xffaf00af, 0xffaf00d7, 0xffaf00ff, 0xffaf5f00, + 0xffaf5f5f, 0xffaf5f87, 0xffaf5faf, 0xffaf5fd7, 0xffaf5fff, + 0xffaf8700, 0xffaf875f, 0xffaf8787, 0xffaf87af, 0xffaf87d7, + 0xffaf87ff, 0xffafaf00, 0xffafaf5f, 0xffafaf87, 0xffafafaf, + 0xffafafd7, 0xffafafff, 0xffafd700, 0xffafd75f, 0xffafd787, + 0xffafd7af, 0xffafd7d7, 0xffafd7ff, 0xffafff00, 0xffafff5f, + 0xffafff87, 0xffafffaf, 0xffafffd7, 0xffafffff, 0xffd70000, + 0xffd7005f, 0xffd70087, 0xffd700af, 0xffd700d7, 0xffd700ff, + 0xffd75f00, 0xffd75f5f, 0xffd75f87, 0xffd75faf, 0xffd75fd7, + 0xffd75fff, 0xffd78700, 0xffd7875f, 0xffd78787, 0xffd787af, + 0xffd787d7, 0xffd787ff, 0xffd7af00, 0xffd7af5f, 0xffd7af87, + 0xffd7afaf, 0xffd7afd7, 0xffd7afff, 0xffd7d700, 0xffd7d75f, + 0xffd7d787, 0xffd7d7af, 0xffd7d7d7, 0xffd7d7ff, 0xffd7ff00, + 0xffd7ff5f, 0xffd7ff87, 0xffd7ffaf, 0xffd7ffd7, 0xffd7ffff, + 0xffff0000, 0xffff005f, 0xffff0087, 0xffff00af, 0xffff00d7, + 0xffff00ff, 0xffff5f00, 0xffff5f5f, 0xffff5f87, 0xffff5faf, + 0xffff5fd7, 0xffff5fff, 0xffff8700, 0xffff875f, 0xffff8787, + 0xffff87af, 0xffff87d7, 0xffff87ff, 0xffffaf00, 0xffffaf5f, + 0xffffaf87, 0xffffafaf, 0xffffafd7, 0xffffafff, 0xffffd700, + 0xffffd75f, 0xffffd787, 0xffffd7af, 0xffffd7d7, 0xffffd7ff, + 0xffffff00, 0xffffff5f, 0xffffff87, 0xffffffaf, 0xffffffd7, + 0xffffffff, 0xff080808, 0xff121212, 0xff1c1c1c, 0xff262626, + 0xff303030, 0xff3a3a3a, 0xff444444, 0xff4e4e4e, 0xff585858, + 0xff626262, 0xff6c6c6c, 0xff767676, 0xff808080, 0xff8a8a8a, + 0xff949494, 0xff9e9e9e, 0xffa8a8a8, 0xffb2b2b2, 0xffbcbcbc, + 0xffc6c6c6, 0xffd0d0d0, 0xffdadada, 0xffe4e4e4, 0xffeeeeee, + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/Encryptor.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,189 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +/** + * This class is from: + * + * Encryptor.java + * Copyright 2008 Zach Scrivena + * zachscrivena@gmail.com + * http://zs.freeshell.org/ + */ + +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.Arrays; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + + +/** + * Perform AES-128 encryption. + */ +public final class Encryptor { + /** name of the character set to use for converting between characters and bytes */ + private static final String CHARSET_NAME = "UTF-8"; + + /** random number generator algorithm */ + private static final String RNG_ALGORITHM = "SHA1PRNG"; + + /** message digest algorithm (must be sufficiently long to provide the key and initialization vector) */ + private static final String DIGEST_ALGORITHM = "SHA-256"; + + /** key algorithm (must be compatible with CIPHER_ALGORITHM) */ + private static final String KEY_ALGORITHM = "AES"; + + /** cipher algorithm (must be compatible with KEY_ALGORITHM) */ + private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; + + + /** + * Private constructor that should never be called. + */ + private Encryptor() + {} + + + /** + * Encrypt the specified cleartext using the given password. + * With the correct salt, number of iterations, and password, the decrypt() method reverses + * the effect of this method. + * This method generates and uses a random salt, and the user-specified number of iterations + * and password to create a 16-byte secret key and 16-byte initialization vector. + * The secret key and initialization vector are then used in the AES-128 cipher to encrypt + * the given cleartext. + * + * @param salt + * salt that was used in the encryption (to be populated) + * @param iterations + * number of iterations to use in salting + * @param password + * password to be used for encryption + * @param cleartext + * cleartext to be encrypted + * @return + * ciphertext + * @throws Exception + * on any error encountered in encryption + */ + public static byte[] encrypt( + final byte[] salt, + final int iterations, + final String password, + final byte[] cleartext) + throws Exception { + /* generate salt randomly */ + SecureRandom.getInstance(RNG_ALGORITHM).nextBytes(salt); + /* compute key and initialization vector */ + final MessageDigest shaDigest = MessageDigest.getInstance(DIGEST_ALGORITHM); + byte[] pw = password.getBytes(CHARSET_NAME); + + for (int i = 0; i < iterations; i++) { + /* add salt */ + final byte[] salted = new byte[pw.length + salt.length]; + System.arraycopy(pw, 0, salted, 0, pw.length); + System.arraycopy(salt, 0, salted, pw.length, salt.length); + Arrays.fill(pw, (byte) 0x00); + /* compute SHA-256 digest */ + shaDigest.reset(); + pw = shaDigest.digest(salted); + Arrays.fill(salted, (byte) 0x00); + } + + /* extract the 16-byte key and initialization vector from the SHA-256 digest */ + final byte[] key = new byte[16]; + final byte[] iv = new byte[16]; + System.arraycopy(pw, 0, key, 0, 16); + System.arraycopy(pw, 16, iv, 0, 16); + Arrays.fill(pw, (byte) 0x00); + /* perform AES-128 encryption */ + final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init( + Cipher.ENCRYPT_MODE, + new SecretKeySpec(key, KEY_ALGORITHM), + new IvParameterSpec(iv)); + Arrays.fill(key, (byte) 0x00); + Arrays.fill(iv, (byte) 0x00); + return cipher.doFinal(cleartext); + } + + + /** + * Decrypt the specified ciphertext using the given password. + * With the correct salt, number of iterations, and password, this method reverses the effect + * of the encrypt() method. + * This method uses the user-specified salt, number of iterations, and password + * to recreate the 16-byte secret key and 16-byte initialization vector. + * The secret key and initialization vector are then used in the AES-128 cipher to decrypt + * the given ciphertext. + * + * @param salt + * salt to be used in decryption + * @param iterations + * number of iterations to use in salting + * @param password + * password to be used for decryption + * @param ciphertext + * ciphertext to be decrypted + * @return + * cleartext + * @throws Exception + * on any error encountered in decryption + */ + public static byte[] decrypt( + final byte[] salt, + final int iterations, + final String password, + final byte[] ciphertext) + throws Exception { + /* compute key and initialization vector */ + final MessageDigest shaDigest = MessageDigest.getInstance(DIGEST_ALGORITHM); + byte[] pw = password.getBytes(CHARSET_NAME); + + for (int i = 0; i < iterations; i++) { + /* add salt */ + final byte[] salted = new byte[pw.length + salt.length]; + System.arraycopy(pw, 0, salted, 0, pw.length); + System.arraycopy(salt, 0, salted, pw.length, salt.length); + Arrays.fill(pw, (byte) 0x00); + /* compute SHA-256 digest */ + shaDigest.reset(); + pw = shaDigest.digest(salted); + Arrays.fill(salted, (byte) 0x00); + } + + /* extract the 16-byte key and initialization vector from the SHA-256 digest */ + final byte[] key = new byte[16]; + final byte[] iv = new byte[16]; + System.arraycopy(pw, 0, key, 0, 16); + System.arraycopy(pw, 16, iv, 0, 16); + Arrays.fill(pw, (byte) 0x00); + /* perform AES-128 decryption */ + final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init( + Cipher.DECRYPT_MODE, + new SecretKeySpec(key, KEY_ALGORITHM), + new IvParameterSpec(iv)); + Arrays.fill(key, (byte) 0x00); + Arrays.fill(iv, (byte) 0x00); + return cipher.doFinal(ciphertext); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/EntropyDialog.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,45 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import com.five_ten_sg.connectbot.R; +import android.app.Dialog; +import android.content.Context; +import android.view.View; + +public class EntropyDialog extends Dialog implements OnEntropyGatheredListener { + + public EntropyDialog(Context context) { + super(context); + this.setContentView(R.layout.dia_gatherentropy); + this.setTitle(R.string.pubkey_gather_entropy); + ((EntropyView) findViewById(R.id.entropy)).addOnEntropyGatheredListener(this); + } + + public EntropyDialog(Context context, View view) { + super(context); + this.setContentView(view); + this.setTitle(R.string.pubkey_gather_entropy); + ((EntropyView) findViewById(R.id.entropy)).addOnEntropyGatheredListener(this); + } + + public void onEntropyGathered(byte[] entropy) { + this.dismiss(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/EntropyView.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,167 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import java.util.Vector; + +import com.five_ten_sg.connectbot.R; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.FontMetrics; +import android.graphics.Typeface; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +public class EntropyView extends View { + private static final int SHA1_MAX_BYTES = 20; + private static final int MILLIS_BETWEEN_INPUTS = 50; + + private Paint mPaint; + private FontMetrics mFontMetrics; + private boolean mFlipFlop; + private long mLastTime; + private Vector<OnEntropyGatheredListener> listeners; + + private byte[] mEntropy; + private int mEntropyByteIndex; + private int mEntropyBitIndex; + + private int splitText = 0; + + private float lastX = 0.0f, lastY = 0.0f; + + public EntropyView(Context context) { + super(context); + setUpEntropy(); + } + + public EntropyView(Context context, AttributeSet attrs) { + super(context, attrs); + setUpEntropy(); + } + + private void setUpEntropy() { + mPaint = new Paint(); + mPaint.setAntiAlias(true); + mPaint.setTypeface(Typeface.DEFAULT); + mPaint.setTextAlign(Paint.Align.CENTER); + mPaint.setTextSize(16); + mPaint.setColor(Color.WHITE); + mFontMetrics = mPaint.getFontMetrics(); + mEntropy = new byte[SHA1_MAX_BYTES]; + mEntropyByteIndex = 0; + mEntropyBitIndex = 0; + listeners = new Vector<OnEntropyGatheredListener>(); + } + + public void addOnEntropyGatheredListener(OnEntropyGatheredListener listener) { + listeners.add(listener); + } + + public void removeOnEntropyGatheredListener(OnEntropyGatheredListener listener) { + listeners.remove(listener); + } + + @Override + public void onDraw(Canvas c) { + String prompt = String.format(getResources().getString(R.string.pubkey_touch_prompt), + (int)(100.0 * (mEntropyByteIndex / 20.0)) + (int)(5.0 * (mEntropyBitIndex / 8.0))); + + if (splitText > 0 || + mPaint.measureText(prompt) > (getWidth() * 0.8)) { + if (splitText == 0) + splitText = prompt.indexOf(" ", prompt.length() / 2); + + c.drawText(prompt.substring(0, splitText), + getWidth() / 2.0f, + getHeight() / 2.0f + (mPaint.ascent() + mPaint.descent()), + mPaint); + c.drawText(prompt.substring(splitText), + getWidth() / 2.0f, + getHeight() / 2.0f - (mPaint.ascent() + mPaint.descent()), + mPaint); + } + else { + c.drawText(prompt, + getWidth() / 2.0f, + getHeight() / 2.0f - (mFontMetrics.ascent + mFontMetrics.descent) / 2, + mPaint); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mEntropyByteIndex >= SHA1_MAX_BYTES + || lastX == event.getX() + || lastY == event.getY()) + return true; + + // Only get entropy every 200 milliseconds to ensure the user has moved around. + long now = System.currentTimeMillis(); + + if ((now - mLastTime) < MILLIS_BETWEEN_INPUTS) + return true; + else + mLastTime = now; + + byte input; + lastX = event.getX(); + lastY = event.getY(); + + // Get the lowest 4 bits of each X, Y input and concat to the entropy-gathering + // string. + if (mFlipFlop) + input = (byte)((((int)lastX & 0x0F) << 4) | ((int)lastY & 0x0F)); + else + input = (byte)((((int)lastY & 0x0F) << 4) | ((int)lastX & 0x0F)); + + mFlipFlop = !mFlipFlop; + + for (int i = 0; i < 4 && mEntropyByteIndex < SHA1_MAX_BYTES; i++) { + if ((input & 0x3) == 0x1) { + mEntropy[mEntropyByteIndex] <<= 1; + mEntropy[mEntropyByteIndex] |= 1; + mEntropyBitIndex++; + input >>= 2; + } + else if ((input & 0x3) == 0x2) { + mEntropy[mEntropyByteIndex] <<= 1; + mEntropyBitIndex++; + input >>= 2; + } + + if (mEntropyBitIndex >= 8) { + mEntropyBitIndex = 0; + mEntropyByteIndex++; + } + } + + // SHA1PRNG only keeps 160 bits of entropy. + if (mEntropyByteIndex >= SHA1_MAX_BYTES) { + for (OnEntropyGatheredListener listener : listeners) { + listener.onEntropyGathered(mEntropy); + } + } + + invalidate(); + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/FileChooser.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,127 @@ +/* + * File Chooser Class for VX ConnectBot + * Copyright 2012 Martin Matuska + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.five_ten_sg.connectbot.util; + +import java.io.File; +import java.net.URI; + +import org.openintents.intents.FileManagerIntents; + +import com.five_ten_sg.connectbot.R; +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Environment; +import android.preference.PreferenceManager; +import android.util.Log; +import android.widget.Toast; + +import com.lamerman.FileDialog; +import com.lamerman.SelectionMode; + +public class FileChooser { + public final static String TAG = "ConnectBot.FileChooser"; + + public static final int REQUEST_CODE_SELECT_FILE = 1; + + // Constants for AndExplorer's file picking intent + private static final String ANDEXPLORER_TITLE = "explorer_title"; + private static final String MIME_TYPE_ANDEXPLORER_FILE = "vnd.android.cursor.dir/lysesoft.andexplorer.file"; + + public static void selectFile(Activity source, FileChooserCallback callback, int requestcode) { + selectFile(source, callback, requestcode, null); + } + + public static void selectFile(Activity source, FileChooserCallback callback, int requestcode, String title) { + final File sdcard = Environment.getExternalStorageDirectory(); + + if (title == null) + title = source.getString(R.string.file_chooser_select_file); + + int mode = SelectionMode.MODE_OPEN; + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(source); + Intent intent = null; + String filedialog; + String appString = null; + + if (prefs == null) + return; + + filedialog = prefs.getString(PreferenceConstants.FILE_DIALOG, "built-in"); + + if (filedialog.equals("OI")) { + appString = "OpenIntents File Manager"; + intent = new Intent(FileManagerIntents.ACTION_PICK_FILE); + intent.setData(Uri.fromFile(sdcard)); + intent.putExtra(FileManagerIntents.EXTRA_TITLE, title); + intent.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, source.getString(android.R.string.ok)); + } + else if (filedialog.equals("AE")) { + appString = "AndExplorer"; + intent = new Intent(Intent.ACTION_PICK); + intent.setDataAndType(Uri.fromFile(sdcard), MIME_TYPE_ANDEXPLORER_FILE); + intent.putExtra(ANDEXPLORER_TITLE, title); + } + + if (intent != null && appString != null) { + try { + source.startActivityForResult(intent, requestcode); + return; + } + catch (ActivityNotFoundException e1) { + Toast.makeText(source, + source.getString(R.string.error_starting_app, appString), + Toast.LENGTH_LONG).show(); + } + } + + intent = new Intent(source.getBaseContext(), FileDialog.class); + intent.putExtra(FileDialog.START_PATH, sdcard.toString()); + intent.putExtra(FileDialog.TITLE, title); + intent.putExtra(FileDialog.SELECTION_MODE, mode); + source.startActivityForResult(intent, requestcode); + } + + public static File getSelectedFile(Intent intent) { + File file = null; + + if (intent == null) + return null; + + Uri uri = intent.getData(); + + try { + if (uri != null) { + file = new File(URI.create(uri.toString())); + } + else { + String filename = intent.getDataString(); + + if (filename != null) + file = new File(URI.create(filename)); + } + } + catch (IllegalArgumentException e) { + Log.e(TAG, "Couldn't read selected file", e); + return null; + } + + return file; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/FileChooserCallback.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,23 @@ +/* + * File Chooser Callback Class for VX ConnectBot + * Copyright 2012 Martin Matuska + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.five_ten_sg.connectbot.util; + +import java.io.File; + +public interface FileChooserCallback { + public void fileSelected(File f); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/HelpTopicView.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,61 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import com.five_ten_sg.connectbot.HelpActivity; +import android.content.Context; +import android.util.AttributeSet; +import android.webkit.WebSettings; +import android.webkit.WebView; + +/** + * @author Kenny Root + * + */ +public class HelpTopicView extends WebView { + public final static String HELPDIR = "help"; + public final static String SUFFIX = ".html"; + + public HelpTopicView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initialize(); + } + + public HelpTopicView(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(); + } + + public HelpTopicView(Context context) { + super(context); + initialize(); + } + + private void initialize() { + WebSettings wSet = getSettings(); + wSet.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS); + wSet.setUseWideViewPort(false); + } + + public HelpTopicView setTopic(String topic) { + String path = String.format("file:///android_asset/%s/%s%s", HELPDIR, topic, SUFFIX); + loadUrl(path); + computeScroll(); + return this; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/HostDatabase.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,762 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import java.nio.charset.Charset; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.bean.PortForwardBean; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; +import android.util.Log; + +import ch.ethz.ssh2.KnownHosts; + +/** + * Contains information about various SSH hosts, include public hostkey if known + * from previous sessions. + * + * @author jsharkey + */ +public class HostDatabase extends RobustSQLiteOpenHelper { + + public final static String TAG = "ConnectBot.HostDatabase"; + + public final static String DB_NAME = "hosts"; + public final static int DB_VERSION = 28; + + public final static String TABLE_HOSTS = "hosts"; + public final static String FIELD_HOST_NICKNAME = "nickname"; + public final static String FIELD_HOST_PROTOCOL = "protocol"; + public final static String FIELD_HOST_USERNAME = "username"; + public final static String FIELD_HOST_HOSTNAME = "hostname"; + public final static String FIELD_HOST_PORT = "port"; + public final static String FIELD_HOST_HOSTKEYALGO = "hostkeyalgo"; + public final static String FIELD_HOST_HOSTKEY = "hostkey"; + public final static String FIELD_HOST_LASTCONNECT = "lastconnect"; + public final static String FIELD_HOST_COLOR = "color"; + public final static String FIELD_HOST_USEKEYS = "usekeys"; + public final static String FIELD_HOST_USEAUTHAGENT = "useauthagent"; + public final static String FIELD_HOST_POSTLOGIN = "postlogin"; + public final static String FIELD_HOST_PUBKEYID = "pubkeyid"; + public final static String FIELD_HOST_WANTSESSION = "wantsession"; + public final static String FIELD_HOST_DELKEY = "delkey"; + public final static String FIELD_HOST_FONTSIZE = "fontsize"; + public final static String FIELD_HOST_FIXEDSIZE = "fixed_size"; + public final static String FIELD_HOST_FIXEDWIDTH = "fixed_width"; + public final static String FIELD_HOST_FIXEDHEIGHT = "fixed_height"; + public final static String FIELD_HOST_COMPRESSION = "compression"; + public final static String FIELD_HOST_HTTPPROXY = "httpproxy"; + public final static String FIELD_HOST_ENCODING = "encoding"; + public final static String FIELD_HOST_STAYCONNECTED = "stayconnected"; + public final static String FIELD_HOST_WANTX11FORWARD = "wantx11forward"; + public final static String FIELD_HOST_X11HOST = "x11host"; + public final static String FIELD_HOST_X11PORT = "x11port"; + public final static String FIELD_HOST_MONITOR = "monitor"; + public final static String FIELD_HOST_EMULATION = "emulation"; + public final static String FIELD_HOST_ENCRYPTION5250 = "encryption5250"; + public final static String FIELD_HOST_LIBRARY5250 = "library5250"; + public final static String FIELD_HOST_MENU5250 = "menu5250"; + public final static String FIELD_HOST_PROGRAM5250 = "program5250"; + public final static String CATEGORY_5250 = "5250"; + public final static String CATEGORY_X11 = "x11"; + + public final static String TABLE_PORTFORWARDS = "portforwards"; + public final static String FIELD_PORTFORWARD_HOSTID = "hostid"; + public final static String FIELD_PORTFORWARD_NICKNAME = "nickname"; + public final static String FIELD_PORTFORWARD_TYPE = "type"; + public final static String FIELD_PORTFORWARD_SOURCEPORT = "sourceport"; + public final static String FIELD_PORTFORWARD_DESTADDR = "destaddr"; + public final static String FIELD_PORTFORWARD_DESTPORT = "destport"; + + public final static String TABLE_COLORS = "colors"; + public final static String FIELD_COLOR_SCHEME = "scheme"; + public final static String FIELD_COLOR_NUMBER = "number"; + public final static String FIELD_COLOR_VALUE = "value"; + + public final static String TABLE_COLOR_DEFAULTS = "colorDefaults"; + public final static String FIELD_COLOR_FG = "fg"; + public final static String FIELD_COLOR_BG = "bg"; + + public final static int DEFAULT_FG_COLOR = 7; + public final static int DEFAULT_BG_COLOR = 0; + + public final static String COLOR_RED = "red"; + public final static String COLOR_GREEN = "green"; + public final static String COLOR_BLUE = "blue"; + public final static String COLOR_GRAY = "gray"; + + public final static String PORTFORWARD_LOCAL = "local"; + public final static String PORTFORWARD_REMOTE = "remote"; + public final static String PORTFORWARD_DYNAMIC4 = "dynamic4"; + public final static String PORTFORWARD_DYNAMIC5 = "dynamic5"; + + public final static String DELKEY_DEL = "del"; + public final static String DELKEY_BACKSPACE = "backspace"; + + public final static String AUTHAGENT_NO = "no"; + public final static String AUTHAGENT_CONFIRM = "confirm"; + public final static String AUTHAGENT_YES = "yes"; + + public final static String ENCODING_DEFAULT = Charset.defaultCharset().name(); + + public final static String X11HOST_DEFAULT = "localhost"; + public final static int X11PORT_DEFAULT = 6000; + + public final static long PUBKEYID_NEVER = -2; + public final static long PUBKEYID_ANY = -1; + + public static final int DEFAULT_COLOR_SCHEME = 0; + + // Table creation strings + public static final String CREATE_TABLE_COLOR_DEFAULTS = + "CREATE TABLE " + TABLE_COLOR_DEFAULTS + + " (" + FIELD_COLOR_SCHEME + " INTEGER NOT NULL, " + + FIELD_COLOR_FG + " INTEGER NOT NULL DEFAULT " + DEFAULT_FG_COLOR + ", " + + FIELD_COLOR_BG + " INTEGER NOT NULL DEFAULT " + DEFAULT_BG_COLOR + ")"; + public static final String CREATE_TABLE_COLOR_DEFAULTS_INDEX = + "CREATE INDEX " + TABLE_COLOR_DEFAULTS + FIELD_COLOR_SCHEME + "index ON " + + TABLE_COLOR_DEFAULTS + " (" + FIELD_COLOR_SCHEME + ");"; + + private static final String WHERE_SCHEME_AND_COLOR = FIELD_COLOR_SCHEME + " = ? AND " + + FIELD_COLOR_NUMBER + " = ?"; + + static { + addTableName(TABLE_HOSTS); + addTableName(TABLE_PORTFORWARDS); + addIndexName(TABLE_PORTFORWARDS + FIELD_PORTFORWARD_HOSTID + "index"); + addTableName(TABLE_COLORS); + addIndexName(TABLE_COLORS + FIELD_COLOR_SCHEME + "index"); + addTableName(TABLE_COLOR_DEFAULTS); + addIndexName(TABLE_COLOR_DEFAULTS + FIELD_COLOR_SCHEME + "index"); + } + + public static final Object[] dbLock = new Object[0]; + + public HostDatabase(Context context) { + super(context, DB_NAME, null, DB_VERSION); + getWritableDatabase().close(); + } + + @Override + public void onCreate(SQLiteDatabase db) { + super.onCreate(db); + db.execSQL("CREATE TABLE " + TABLE_HOSTS + + " (_id INTEGER PRIMARY KEY, " + + FIELD_HOST_NICKNAME + " TEXT, " + + FIELD_HOST_PROTOCOL + " TEXT DEFAULT 'ssh', " + + FIELD_HOST_USERNAME + " TEXT, " + + FIELD_HOST_HOSTNAME + " TEXT, " + + FIELD_HOST_PORT + " INTEGER, " + + FIELD_HOST_HOSTKEYALGO + " TEXT, " + + FIELD_HOST_HOSTKEY + " BLOB, " + + FIELD_HOST_LASTCONNECT + " INTEGER, " + + FIELD_HOST_COLOR + " TEXT, " + + FIELD_HOST_USEKEYS + " TEXT, " + + FIELD_HOST_USEAUTHAGENT + " TEXT, " + + FIELD_HOST_POSTLOGIN + " TEXT, " + + FIELD_HOST_PUBKEYID + " INTEGER DEFAULT " + PUBKEYID_ANY + ", " + + FIELD_HOST_DELKEY + " TEXT DEFAULT '" + DELKEY_DEL + "', " + + FIELD_HOST_FONTSIZE + " REAL, " + + FIELD_HOST_FIXEDSIZE + " TEXT DEFAULT '" + Boolean.toString(false) + "', " + + FIELD_HOST_FIXEDWIDTH + " INTEGER, " + + FIELD_HOST_FIXEDHEIGHT + " INTEGER, " + + FIELD_HOST_WANTSESSION + " TEXT DEFAULT '" + Boolean.toString(true) + "', " + + FIELD_HOST_COMPRESSION + " TEXT DEFAULT '" + Boolean.toString(false) + "', " + + FIELD_HOST_HTTPPROXY + " TEXT, " + + FIELD_HOST_ENCODING + " TEXT DEFAULT '" + ENCODING_DEFAULT + "', " + + FIELD_HOST_STAYCONNECTED + " TEXT, " + + FIELD_HOST_WANTX11FORWARD + " TEXT DEFAULT '" + Boolean.toString(false) + "', " + + FIELD_HOST_X11HOST + " TEXT DEFAULT '" + X11HOST_DEFAULT + "', " + + FIELD_HOST_X11PORT + " INTEGER DEFAULT " + X11PORT_DEFAULT + ", " + + FIELD_HOST_MONITOR + " TEXT, " + + FIELD_HOST_EMULATION + " TEXT, " + + FIELD_HOST_ENCRYPTION5250 + " TEXT, " + + FIELD_HOST_LIBRARY5250 + " TEXT, " + + FIELD_HOST_MENU5250 + " TEXT, " + + FIELD_HOST_PROGRAM5250 + " TEXT)"); + db.execSQL("CREATE TABLE " + TABLE_PORTFORWARDS + + " (_id INTEGER PRIMARY KEY, " + + FIELD_PORTFORWARD_HOSTID + " INTEGER, " + + FIELD_PORTFORWARD_NICKNAME + " TEXT, " + + FIELD_PORTFORWARD_TYPE + " TEXT NOT NULL DEFAULT " + PORTFORWARD_LOCAL + ", " + + FIELD_PORTFORWARD_SOURCEPORT + " INTEGER NOT NULL DEFAULT 8080, " + + FIELD_PORTFORWARD_DESTADDR + " TEXT, " + + FIELD_PORTFORWARD_DESTPORT + " TEXT)"); + db.execSQL("CREATE INDEX " + TABLE_PORTFORWARDS + FIELD_PORTFORWARD_HOSTID + "index ON " + + TABLE_PORTFORWARDS + " (" + FIELD_PORTFORWARD_HOSTID + ");"); + db.execSQL("CREATE TABLE " + TABLE_COLORS + + " (_id INTEGER PRIMARY KEY, " + + FIELD_COLOR_NUMBER + " INTEGER, " + + FIELD_COLOR_VALUE + " INTEGER, " + + FIELD_COLOR_SCHEME + " INTEGER)"); + db.execSQL("CREATE INDEX " + TABLE_COLORS + FIELD_COLOR_SCHEME + "index ON " + + TABLE_COLORS + " (" + FIELD_COLOR_SCHEME + ");"); + db.execSQL(CREATE_TABLE_COLOR_DEFAULTS); + db.execSQL(CREATE_TABLE_COLOR_DEFAULTS_INDEX); + } + + @Override + public void onRobustUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLiteException { + // Versions of the database before 510ConnectBot will be shot without warning. + if (oldVersion < 24) { + db.execSQL("DROP TABLE IF EXISTS " + TABLE_HOSTS); + onCreate(db); + return; + } + + switch (oldVersion) { + case 24: + db.execSQL("ALTER TABLE " + TABLE_HOSTS + + " ADD COLUMN " + FIELD_HOST_MONITOR + " TEXT"); + + case 25: + db.execSQL("ALTER TABLE " + TABLE_HOSTS + + " ADD COLUMN " + FIELD_HOST_EMULATION + " TEXT"); + db.execSQL("ALTER TABLE " + TABLE_HOSTS + + " ADD COLUMN " + FIELD_HOST_ENCRYPTION5250 + " TEXT"); + + case 26: + db.execSQL("ALTER TABLE " + TABLE_HOSTS + + " ADD COLUMN " + FIELD_HOST_LIBRARY5250 + " TEXT"); + db.execSQL("ALTER TABLE " + TABLE_HOSTS + + " ADD COLUMN " + FIELD_HOST_MENU5250 + " TEXT"); + db.execSQL("ALTER TABLE " + TABLE_HOSTS + + " ADD COLUMN " + FIELD_HOST_PROGRAM5250 + " TEXT"); + + case 27: + db.execSQL("ALTER TABLE " + TABLE_HOSTS + + " ADD COLUMN " + FIELD_HOST_FIXEDSIZE + " TEXT DEFAULT '" + Boolean.toString(false) + "'"); + db.execSQL("ALTER TABLE " + TABLE_HOSTS + + " ADD COLUMN " + FIELD_HOST_FIXEDWIDTH + " INTEGER"); + db.execSQL("ALTER TABLE " + TABLE_HOSTS + + " ADD COLUMN " + FIELD_HOST_FIXEDHEIGHT + " INTEGER"); + } + } + + /** + * Touch a specific host to update its "last connected" field. + * @param nickname Nickname field of host to update + */ + public void touchHost(HostBean host) { + long now = System.currentTimeMillis() / 1000; + ContentValues values = new ContentValues(); + values.put(FIELD_HOST_LASTCONNECT, now); + + synchronized (dbLock) { + SQLiteDatabase db = this.getWritableDatabase(); + db.update(TABLE_HOSTS, values, "_id = ?", new String[] { String.valueOf(host.getId()) }); + } + } + + /** + * Create a new host using the given parameters. + */ + public HostBean saveHost(HostBean host) { + long id; + + synchronized (dbLock) { + SQLiteDatabase db = this.getWritableDatabase(); + id = db.insert(TABLE_HOSTS, null, host.getValues()); + } + + host.setId(id); + return host; + } + + /** + * Update a field in a host record. + */ + public boolean updateFontSize(HostBean host) { + long id = host.getId(); + + if (id < 0) + return false; + + ContentValues updates = new ContentValues(); + updates.put(FIELD_HOST_FONTSIZE, host.getFontSize()); + + synchronized (dbLock) { + SQLiteDatabase db = getWritableDatabase(); + db.update(TABLE_HOSTS, updates, "_id = ?", + new String[] { String.valueOf(id) }); + } + + return true; + } + + /** + * Delete a specific host by its <code>_id</code> value. + */ + public void deleteHost(HostBean host) { + if (host.getId() < 0) + return; + + synchronized (dbLock) { + SQLiteDatabase db = this.getWritableDatabase(); + db.delete(TABLE_HOSTS, "_id = ?", new String[] { String.valueOf(host.getId()) }); + } + } + + /** + * Return a cursor that contains information about all known hosts. + * @param sortColors If true, sort by color, otherwise sort by nickname. + */ + public List<HostBean> getHosts(boolean sortColors) { + String sortField = sortColors ? FIELD_HOST_COLOR : FIELD_HOST_NICKNAME; + List<HostBean> hosts; + + synchronized (dbLock) { + SQLiteDatabase db = this.getReadableDatabase(); + Cursor c = db.query(TABLE_HOSTS, null, null, null, null, null, sortField + " ASC"); + hosts = createHostBeans(c); + c.close(); + } + + return hosts; + } + + /** + * @param hosts + * @param c + */ + private List<HostBean> createHostBeans(Cursor c) { + List<HostBean> hosts = new LinkedList<HostBean>(); + final int COL_ID = c.getColumnIndexOrThrow("_id"), + COL_NICKNAME = c.getColumnIndexOrThrow(FIELD_HOST_NICKNAME), + COL_PROTOCOL = c.getColumnIndexOrThrow(FIELD_HOST_PROTOCOL), + COL_USERNAME = c.getColumnIndexOrThrow(FIELD_HOST_USERNAME), + COL_HOSTNAME = c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME), + COL_PORT = c.getColumnIndexOrThrow(FIELD_HOST_PORT), + COL_LASTCONNECT = c.getColumnIndexOrThrow(FIELD_HOST_LASTCONNECT), + COL_COLOR = c.getColumnIndexOrThrow(FIELD_HOST_COLOR), + COL_USEKEYS = c.getColumnIndexOrThrow(FIELD_HOST_USEKEYS), + COL_USEAUTHAGENT = c.getColumnIndexOrThrow(FIELD_HOST_USEAUTHAGENT), + COL_POSTLOGIN = c.getColumnIndexOrThrow(FIELD_HOST_POSTLOGIN), + COL_PUBKEYID = c.getColumnIndexOrThrow(FIELD_HOST_PUBKEYID), + COL_WANTSESSION = c.getColumnIndexOrThrow(FIELD_HOST_WANTSESSION), + COL_DELKEY = c.getColumnIndexOrThrow(FIELD_HOST_DELKEY), + COL_FONTSIZE = c.getColumnIndexOrThrow(FIELD_HOST_FONTSIZE), + COL_FIXEDSIZE = c.getColumnIndexOrThrow(FIELD_HOST_FIXEDSIZE), + COL_FIXEDWIDTH = c.getColumnIndexOrThrow(FIELD_HOST_FIXEDWIDTH), + COL_FIXEDHEIGHT = c.getColumnIndexOrThrow(FIELD_HOST_FIXEDHEIGHT), + COL_COMPRESSION = c.getColumnIndexOrThrow(FIELD_HOST_COMPRESSION), + COL_HTTPPROXY = c.getColumnIndexOrThrow(FIELD_HOST_HTTPPROXY), + COL_ENCODING = c.getColumnIndexOrThrow(FIELD_HOST_ENCODING), + COL_STAYCONNECTED = c.getColumnIndexOrThrow(FIELD_HOST_STAYCONNECTED), + COL_WANTX11FORWARD = c.getColumnIndexOrThrow(FIELD_HOST_WANTX11FORWARD), + COL_X11HOST = c.getColumnIndexOrThrow(FIELD_HOST_X11HOST), + COL_X11PORT = c.getColumnIndexOrThrow(FIELD_HOST_X11PORT), + COL_MONITOR = c.getColumnIndexOrThrow(FIELD_HOST_MONITOR), + COL_EMULATION = c.getColumnIndexOrThrow(FIELD_HOST_EMULATION), + COL_ENCRYPTION5250 = c.getColumnIndexOrThrow(FIELD_HOST_ENCRYPTION5250), + COL_LIBRARY5250 = c.getColumnIndexOrThrow(FIELD_HOST_LIBRARY5250), + COL_MENU5250 = c.getColumnIndexOrThrow(FIELD_HOST_MENU5250), + COL_PROGRAM5250 = c.getColumnIndexOrThrow(FIELD_HOST_PROGRAM5250); + + while (c.moveToNext()) { + HostBean host = new HostBean(); + host.setId(c.getLong(COL_ID)); + host.setNickname(c.getString(COL_NICKNAME)); + host.setProtocol(c.getString(COL_PROTOCOL)); + host.setUsername(c.getString(COL_USERNAME)); + host.setHostname(c.getString(COL_HOSTNAME)); + host.setPort(c.getInt(COL_PORT)); + host.setLastConnect(c.getLong(COL_LASTCONNECT)); + host.setColor(c.getString(COL_COLOR)); + host.setUseKeys(Boolean.valueOf(c.getString(COL_USEKEYS))); + host.setUseAuthAgent(c.getString(COL_USEAUTHAGENT)); + host.setPostLogin(c.getString(COL_POSTLOGIN)); + host.setPubkeyId(c.getLong(COL_PUBKEYID)); + host.setDelKey(c.getString(COL_DELKEY)); + host.setFontSize(c.getFloat(COL_FONTSIZE)); + host.setFixedSize(Boolean.valueOf(c.getString(COL_FIXEDSIZE))); + host.setFixedWidth(c.getInt(COL_FIXEDWIDTH)); + host.setFixedHeight(c.getInt(COL_FIXEDHEIGHT)); + host.setWantSession(Boolean.valueOf(c.getString(COL_WANTSESSION))); + host.setCompression(Boolean.valueOf(c.getString(COL_COMPRESSION))); + host.setHttpproxy(c.getString(COL_HTTPPROXY)); + host.setEncoding(c.getString(COL_ENCODING)); + host.setStayConnected(Boolean.valueOf(c.getString(COL_STAYCONNECTED))); + host.setWantX11Forward(Boolean.valueOf(c.getString(COL_WANTX11FORWARD))); + host.setX11Host(c.getString(COL_X11HOST)); + host.setX11Port(c.getInt(COL_X11PORT)); + host.setMonitor(c.getString(COL_MONITOR)); + host.setHostEmulation(c.getString(COL_EMULATION)); + host.setEncryption5250(c.getString(COL_ENCRYPTION5250)); + host.setLibrary(c.getString(COL_LIBRARY5250)); + host.setInitialMenu(c.getString(COL_MENU5250)); + host.setProgram(c.getString(COL_PROGRAM5250)); + hosts.add(host); + } + + return hosts; + } + + /** + * @param c + * @return + */ + private HostBean getFirstHostBean(Cursor c) { + HostBean host = null; + List<HostBean> hosts = createHostBeans(c); + + if (hosts.size() > 0) + host = hosts.get(0); + + c.close(); + return host; + } + + /** + * @param nickname + * @param protocol + * @param username + * @param hostname + * @param hostname2 + * @param port + * @return + */ + public HostBean findHost(Map<String, String> selection) { + StringBuilder selectionBuilder = new StringBuilder(); + Iterator<Entry<String, String>> i = selection.entrySet().iterator(); + List<String> selectionValuesList = new LinkedList<String>(); + int n = 0; + + while (i.hasNext()) { + Entry<String, String> entry = i.next(); + + if (entry.getValue() == null) + continue; + + if (n++ > 0) + selectionBuilder.append(" AND "); + + selectionBuilder.append(entry.getKey()) + .append(" = ?"); + selectionValuesList.add(entry.getValue()); + } + + String selectionValues[] = new String[selectionValuesList.size()]; + selectionValuesList.toArray(selectionValues); + selectionValuesList = null; + HostBean host; + + synchronized (dbLock) { + SQLiteDatabase db = getReadableDatabase(); + Cursor c = db.query(TABLE_HOSTS, null, + selectionBuilder.toString(), + selectionValues, + null, null, null); + host = getFirstHostBean(c); + } + + return host; + } + + /** + * @param hostId + * @return + */ + public HostBean findHostById(long hostId) { + HostBean host; + + synchronized (dbLock) { + SQLiteDatabase db = getReadableDatabase(); + Cursor c = db.query(TABLE_HOSTS, null, + "_id = ?", new String[] { String.valueOf(hostId) }, + null, null, null); + host = getFirstHostBean(c); + } + + return host; + } + + /** + * Record the given hostkey into database under this nickname. + * @param hostname + * @param port + * @param hostkeyalgo + * @param hostkey + */ + public void saveKnownHost(String hostname, int port, String hostkeyalgo, byte[] hostkey) { + ContentValues values = new ContentValues(); + values.put(FIELD_HOST_HOSTKEYALGO, hostkeyalgo); + values.put(FIELD_HOST_HOSTKEY, hostkey); + + synchronized (dbLock) { + SQLiteDatabase db = getReadableDatabase(); + db.update(TABLE_HOSTS, values, + FIELD_HOST_HOSTNAME + " = ? AND " + FIELD_HOST_PORT + " = ?", + new String[] { hostname, String.valueOf(port) }); + Log.d(TAG, String.format("Finished saving hostkey information for '%s'", hostname)); + } + } + + /** + * Build list of known hosts for Trilead library. + * @return + */ + public KnownHosts getKnownHosts() { + KnownHosts known = new KnownHosts(); + + synchronized (dbLock) { + SQLiteDatabase db = this.getReadableDatabase(); + Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_HOSTNAME, + FIELD_HOST_PORT, FIELD_HOST_HOSTKEYALGO, FIELD_HOST_HOSTKEY + }, + null, null, null, null, null); + + if (c != null) { + int COL_HOSTNAME = c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME), + COL_PORT = c.getColumnIndexOrThrow(FIELD_HOST_PORT), + COL_HOSTKEYALGO = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEYALGO), + COL_HOSTKEY = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEY); + + while (c.moveToNext()) { + String hostname = c.getString(COL_HOSTNAME), + hostkeyalgo = c.getString(COL_HOSTKEYALGO); + int port = c.getInt(COL_PORT); + byte[] hostkey = c.getBlob(COL_HOSTKEY); + + if (hostkeyalgo == null || hostkeyalgo.length() == 0) continue; + + if (hostkey == null || hostkey.length == 0) continue; + + try { + known.addHostkey(new String[] { String.format("%s:%d", hostname, port) }, hostkeyalgo, hostkey); + } + catch (Exception e) { + Log.e(TAG, "Problem while adding a known host from database", e); + } + } + + c.close(); + } + } + + return known; + } + + /** + * Unset any hosts using a pubkey ID that has been deleted. + * @param pubkeyId + */ + public void stopUsingPubkey(long pubkeyId) { + if (pubkeyId < 0) return; + + ContentValues values = new ContentValues(); + values.put(FIELD_HOST_PUBKEYID, PUBKEYID_ANY); + + synchronized (dbLock) { + SQLiteDatabase db = this.getWritableDatabase(); + db.update(TABLE_HOSTS, values, FIELD_HOST_PUBKEYID + " = ?", new String[] { String.valueOf(pubkeyId) }); + } + + Log.d(TAG, String.format("Set all hosts using pubkey id %d to -1", pubkeyId)); + } + + /* + * Methods for dealing with port forwards attached to hosts + */ + + /** + * Returns a list of all the port forwards associated with a particular host ID. + * @param host the host for which we want the port forward list + * @return port forwards associated with host ID + */ + public List<PortForwardBean> getPortForwardsForHost(HostBean host) { + List<PortForwardBean> portForwards = new LinkedList<PortForwardBean>(); + + synchronized (dbLock) { + SQLiteDatabase db = this.getReadableDatabase(); + Cursor c = db.query(TABLE_PORTFORWARDS, new String[] { + "_id", FIELD_PORTFORWARD_NICKNAME, FIELD_PORTFORWARD_TYPE, FIELD_PORTFORWARD_SOURCEPORT, + FIELD_PORTFORWARD_DESTADDR, FIELD_PORTFORWARD_DESTPORT + }, + FIELD_PORTFORWARD_HOSTID + " = ?", new String[] { String.valueOf(host.getId()) }, + null, null, null); + + while (c.moveToNext()) { + PortForwardBean pfb = new PortForwardBean( + c.getInt(0), + host.getId(), + c.getString(1), + c.getString(2), + c.getInt(3), + c.getString(4), + c.getInt(5)); + portForwards.add(pfb); + } + + c.close(); + } + + return portForwards; + } + + /** + * Update the parameters of a port forward in the database. + * @param pfb {@link PortForwardBean} to save + * @return true on success + */ + public boolean savePortForward(PortForwardBean pfb) { + boolean success = false; + + synchronized (dbLock) { + SQLiteDatabase db = getWritableDatabase(); + + if (pfb.getId() < 0) { + long id = db.insert(TABLE_PORTFORWARDS, null, pfb.getValues()); + pfb.setId(id); + success = true; + } + else { + if (db.update(TABLE_PORTFORWARDS, pfb.getValues(), "_id = ?", new String[] { String.valueOf(pfb.getId()) }) > 0) + success = true; + } + } + + return success; + } + + /** + * Deletes a port forward from the database. + * @param pfb {@link PortForwardBean} to delete + */ + public void deletePortForward(PortForwardBean pfb) { + if (pfb.getId() < 0) + return; + + synchronized (dbLock) { + SQLiteDatabase db = this.getWritableDatabase(); + db.delete(TABLE_PORTFORWARDS, "_id = ?", new String[] { String.valueOf(pfb.getId()) }); + } + } + + public Integer[] getColorsForScheme(int scheme) { + Integer[] colors = Colors.defaults.clone(); + + synchronized (dbLock) { + SQLiteDatabase db = getReadableDatabase(); + Cursor c = db.query(TABLE_COLORS, new String[] { + FIELD_COLOR_NUMBER, FIELD_COLOR_VALUE + }, + FIELD_COLOR_SCHEME + " = ?", + new String[] { String.valueOf(scheme) }, + null, null, null); + + while (c.moveToNext()) { + colors[c.getInt(0)] = Integer.valueOf(c.getInt(1)); + } + + c.close(); + } + + return colors; + } + + public void setColorForScheme(int scheme, int number, int value) { + final SQLiteDatabase db; + final String[] whereArgs = new String[] { String.valueOf(scheme), String.valueOf(number) }; + + if (value == Colors.defaults[number]) { + synchronized (dbLock) { + db = getWritableDatabase(); + db.delete(TABLE_COLORS, + WHERE_SCHEME_AND_COLOR, whereArgs); + } + } + else { + final ContentValues values = new ContentValues(); + values.put(FIELD_COLOR_VALUE, value); + + synchronized (dbLock) { + db = getWritableDatabase(); + final int rowsAffected = db.update(TABLE_COLORS, values, + WHERE_SCHEME_AND_COLOR, whereArgs); + + if (rowsAffected == 0) { + values.put(FIELD_COLOR_SCHEME, scheme); + values.put(FIELD_COLOR_NUMBER, number); + db.insert(TABLE_COLORS, null, values); + } + } + } + } + + public void setGlobalColor(int number, int value) { + setColorForScheme(DEFAULT_COLOR_SCHEME, number, value); + } + + public int[] getDefaultColorsForScheme(int scheme) { + int[] colors = new int[] { DEFAULT_FG_COLOR, DEFAULT_BG_COLOR }; + + synchronized (dbLock) { + SQLiteDatabase db = getReadableDatabase(); + Cursor c = db.query(TABLE_COLOR_DEFAULTS, + new String[] { FIELD_COLOR_FG, FIELD_COLOR_BG }, + FIELD_COLOR_SCHEME + " = ?", + new String[] { String.valueOf(scheme) }, + null, null, null); + + if (c.moveToFirst()) { + colors[0] = c.getInt(0); + colors[1] = c.getInt(1); + } + + c.close(); + } + + return colors; + } + + public int[] getGlobalDefaultColors() { + return getDefaultColorsForScheme(DEFAULT_COLOR_SCHEME); + } + + public void setDefaultColorsForScheme(int scheme, int fg, int bg) { + SQLiteDatabase db; + String schemeWhere = null; + String[] whereArgs; + schemeWhere = FIELD_COLOR_SCHEME + " = ?"; + whereArgs = new String[] { String.valueOf(scheme) }; + ContentValues values = new ContentValues(); + values.put(FIELD_COLOR_FG, fg); + values.put(FIELD_COLOR_BG, bg); + + synchronized (dbLock) { + db = getWritableDatabase(); + int rowsAffected = db.update(TABLE_COLOR_DEFAULTS, values, + schemeWhere, whereArgs); + + if (rowsAffected == 0) { + values.put(FIELD_COLOR_SCHEME, scheme); + db.insert(TABLE_COLOR_DEFAULTS, null, values); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/OnDbWrittenListener.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,26 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2010 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +/** + * @author kroot + * + */ +public interface OnDbWrittenListener { + public void onDbWritten(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/OnEntropyGatheredListener.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,22 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +public interface OnEntropyGatheredListener { + void onEntropyGathered(byte[] entropy); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/PreferenceConstants.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,117 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import android.os.Build; + + +/** + * @author Kenny Root + * + */ +public class PreferenceConstants { + public static final boolean PRE_HONEYCOMB = + (Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.HONEYCOMB); + + public static final String CATEGORY_UI = "category_ui"; + + public static final String MEMKEYS = "memkeys"; + public static final String SCROLLBACK = "scrollback"; + public static final String EMULATION = "emulation"; + public static final String ROTATION = "rotation"; + + public static final String ROTATION_DEFAULT = "Default"; + public static final String ROTATION_LANDSCAPE = "Force landscape"; + public static final String ROTATION_PORTRAIT = "Force portrait"; + public static final String ROTATION_AUTOMATIC = "Automatic"; + + public static final String KEYMODE = "keymode"; + + public static final String KEYMODE_RIGHT = "Use right-side keys"; + public static final String KEYMODE_LEFT = "Use left-side keys"; + + // must match android:key values in preferences.xml + public static final String CAMERA = "camera"; + public static final String VOLUP = "volup"; + public static final String VOLDN = "voldn"; + public static final String SEARCH = "search"; + public static final String PTT = "ptt"; + + // must match arrays.xml/list_hw_button_values + public static final String HWBUTTON_CTRL = "CTRL"; + public static final String HWBUTTON_ESC = "Esc"; + public static final String HWBUTTON_TAB = "Tab"; + public static final String HWBUTTON_SCREEN_CAPTURE = "Screen Capture"; + public static final String HWBUTTON_CTRLA_SPACE = "Ctrl+A then Space"; + public static final String HWBUTTON_CTRLA = "Ctrl+A"; + public static final String HWBUTTON_ESC_A = "Esc+A"; + public static final String HWBUTTON_MONITOR = "Monitor Key"; + public static final String HWBUTTON_FUNCTION_KEYS = "Soft Function Keypad"; + public static final String HWBUTTON_INCREASE_FONTSIZE = "Increase Font Size"; + public static final String HWBUTTON_DECREASE_FONTSIZE = "Decrease Font Size"; + public static final String HWBUTTON_NONE = "None"; + + public static final String KEEP_ALIVE = "keepalive"; + + public static final String WIFI_LOCK = "wifilock"; + + public static final String BUMPY_ARROWS = "bumpyarrows"; + + public static final String EULA = "eula"; + + public static final String SORT_BY_COLOR = "sortByColor"; + + public static final String BELL = "bell"; + public static final String BELL_VOLUME = "bellVolume"; + public static final String BELL_VIBRATE = "bellVibrate"; + public static final String BELL_NOTIFICATION = "bellNotification"; + public static final float DEFAULT_BELL_VOLUME = 0.25f; + + public static final String CONNECTION_PERSIST = "connPersist"; + + public static final String SHIFT_FKEYS = "shiftfkeys"; + public static final String CTRL_FKEYS = "ctrlfkeys"; + + /* Backup identifiers */ + public static final String BACKUP_PREF_KEY = "prefs"; + + public static final String CTRL_STRING = "ctrl_string"; + public static final String PICKER_STRING = "picker_string"; + public static final String PICKER_KEEP_OPEN = "picker_keep_open"; + public static final String EXTENDED_LONGPRESS = "extended_longpress"; + public static final String SCREEN_CAPTURE_POPUP = "screen_capture_popup"; + public static final String SCREEN_CAPTURE_FOLDER = "screen_capture_folder"; + public static final String FILE_DIALOG = "file_dialog"; + public static final String DOWNLOAD_FOLDER = "download_folder"; + public static final String REMOTE_UPLOAD_FOLDER = "remote_upload_folder"; + public static final String BACKGROUND_FILE_TRANSFER = "background_file_transfer"; + public static final String UPLOAD_DESTINATION_PROMPT = "upload_dest_prompt"; + + /* Debug */ + public static final String DEBUG_KEYCODES = "debug_keycodes"; + + /* Device keyboard mapping */ + public static final String CUSTOM_KEYMAP = "list_custom_keymap"; + // must match arrays.xml/list_custom_keymap_values + public static final String CUSTOM_KEYMAP_DISABLED = "none"; + public static final String CUSTOM_KEYMAP_FULL = "full"; + public static final String CUSTOM_KEYMAP_ASUS_TF = "asus_tf"; + public static final String CUSTOM_KEYMAP_SGH_I927 = "sgh_i927"; + public static final String CUSTOM_KEYMAP_SGH_I927_ICS = "sgh_i927_ics"; + public static final String CUSTOM_KEYMAP_SE_XPPRO = "se_xppro"; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/PubkeyDatabase.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,311 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import java.util.LinkedList; +import java.util.List; + +import com.five_ten_sg.connectbot.bean.PubkeyBean; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; + +/** + * Public Key Encryption database. Contains private and public key pairs + * for public key authentication. + * + * @author Kenny Root + */ +public class PubkeyDatabase extends RobustSQLiteOpenHelper { + public final static String TAG = "ConnectBot.PubkeyDatabase"; + + public final static String DB_NAME = "pubkeys"; + public final static int DB_VERSION = 2; + + public final static String TABLE_PUBKEYS = "pubkeys"; + public final static String FIELD_PUBKEY_NICKNAME = "nickname"; + public final static String FIELD_PUBKEY_TYPE = "type"; + public final static String FIELD_PUBKEY_PRIVATE = "private"; + public final static String FIELD_PUBKEY_PUBLIC = "public"; + public final static String FIELD_PUBKEY_ENCRYPTED = "encrypted"; + public final static String FIELD_PUBKEY_STARTUP = "startup"; + public final static String FIELD_PUBKEY_CONFIRMUSE = "confirmuse"; + public final static String FIELD_PUBKEY_LIFETIME = "lifetime"; + + public final static String KEY_TYPE_RSA = "RSA", + KEY_TYPE_DSA = "DSA", + KEY_TYPE_IMPORTED = "IMPORTED", + KEY_TYPE_EC = "EC"; + + private Context context; + + static { + addTableName(TABLE_PUBKEYS); + } + + public PubkeyDatabase(Context context) { + super(context, DB_NAME, null, DB_VERSION); + this.context = context; + } + + @Override + public void onCreate(SQLiteDatabase db) { + super.onCreate(db); + db.execSQL("CREATE TABLE " + TABLE_PUBKEYS + + " (_id INTEGER PRIMARY KEY, " + + FIELD_PUBKEY_NICKNAME + " TEXT, " + + FIELD_PUBKEY_TYPE + " TEXT, " + + FIELD_PUBKEY_PRIVATE + " BLOB, " + + FIELD_PUBKEY_PUBLIC + " BLOB, " + + FIELD_PUBKEY_ENCRYPTED + " INTEGER, " + + FIELD_PUBKEY_STARTUP + " INTEGER, " + + FIELD_PUBKEY_CONFIRMUSE + " INTEGER DEFAULT 0, " + + FIELD_PUBKEY_LIFETIME + " INTEGER DEFAULT 0)"); + } + + @Override + public void onRobustUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLiteException { + switch (oldVersion) { + case 1: + db.execSQL("ALTER TABLE " + TABLE_PUBKEYS + + " ADD COLUMN " + FIELD_PUBKEY_CONFIRMUSE + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + TABLE_PUBKEYS + + " ADD COLUMN " + FIELD_PUBKEY_LIFETIME + " INTEGER DEFAULT 0"); + } + } + + /** + * Delete a specific host by its <code>_id</code> value. + */ + public void deletePubkey(PubkeyBean pubkey) { + HostDatabase hostdb = new HostDatabase(context); + hostdb.stopUsingPubkey(pubkey.getId()); + hostdb.close(); + SQLiteDatabase db = getWritableDatabase(); + db.delete(TABLE_PUBKEYS, "_id = ?", new String[] { Long.toString(pubkey.getId()) }); + db.close(); + } + + /** + * Return a cursor that contains information about all known hosts. + */ + /* + public Cursor allPubkeys() { + SQLiteDatabase db = this.getReadableDatabase(); + return db.query(TABLE_PUBKEYS, new String[] { "_id", + FIELD_PUBKEY_NICKNAME, FIELD_PUBKEY_TYPE, FIELD_PUBKEY_PRIVATE, + FIELD_PUBKEY_PUBLIC, FIELD_PUBKEY_ENCRYPTED, FIELD_PUBKEY_STARTUP }, + null, null, null, null, null); + }*/ + + public List<PubkeyBean> allPubkeys() { + return getPubkeys(null, null); + } + + public List<PubkeyBean> getAllStartPubkeys() { + return getPubkeys(FIELD_PUBKEY_STARTUP + " = 1 AND " + FIELD_PUBKEY_ENCRYPTED + " = 0", null); + } + + private List<PubkeyBean> getPubkeys(String selection, String[] selectionArgs) { + SQLiteDatabase db = getReadableDatabase(); + List<PubkeyBean> pubkeys = new LinkedList<PubkeyBean>(); + Cursor c = db.query(TABLE_PUBKEYS, null, selection, selectionArgs, null, null, null); + + if (c != null) { + final int COL_ID = c.getColumnIndexOrThrow("_id"), + COL_NICKNAME = c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME), + COL_TYPE = c.getColumnIndexOrThrow(FIELD_PUBKEY_TYPE), + COL_PRIVATE = c.getColumnIndexOrThrow(FIELD_PUBKEY_PRIVATE), + COL_PUBLIC = c.getColumnIndexOrThrow(FIELD_PUBKEY_PUBLIC), + COL_ENCRYPTED = c.getColumnIndexOrThrow(FIELD_PUBKEY_ENCRYPTED), + COL_STARTUP = c.getColumnIndexOrThrow(FIELD_PUBKEY_STARTUP), + COL_CONFIRMUSE = c.getColumnIndexOrThrow(FIELD_PUBKEY_CONFIRMUSE), + COL_LIFETIME = c.getColumnIndexOrThrow(FIELD_PUBKEY_LIFETIME); + + while (c.moveToNext()) { + PubkeyBean pubkey = new PubkeyBean(); + pubkey.setId(c.getLong(COL_ID)); + pubkey.setNickname(c.getString(COL_NICKNAME)); + pubkey.setType(c.getString(COL_TYPE)); + pubkey.setPrivateKey(c.getBlob(COL_PRIVATE)); + pubkey.setPublicKey(c.getBlob(COL_PUBLIC)); + pubkey.setEncrypted(c.getInt(COL_ENCRYPTED) > 0); + pubkey.setStartup(c.getInt(COL_STARTUP) > 0); + pubkey.setConfirmUse(c.getInt(COL_CONFIRMUSE) > 0); + pubkey.setLifetime(c.getInt(COL_LIFETIME)); + pubkeys.add(pubkey); + } + + c.close(); + } + + db.close(); + return pubkeys; + } + + /** + * @param hostId + * @return + */ + public PubkeyBean findPubkeyById(long pubkeyId) { + SQLiteDatabase db = getReadableDatabase(); + Cursor c = db.query(TABLE_PUBKEYS, null, + "_id = ?", new String[] { String.valueOf(pubkeyId) }, + null, null, null); + PubkeyBean pubkey = null; + + if (c != null) { + if (c.moveToFirst()) + pubkey = createPubkeyBean(c); + + c.close(); + } + + db.close(); + return pubkey; + } + + private PubkeyBean createPubkeyBean(Cursor c) { + PubkeyBean pubkey = new PubkeyBean(); + pubkey.setId(c.getLong(c.getColumnIndexOrThrow("_id"))); + pubkey.setNickname(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME))); + pubkey.setType(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_TYPE))); + pubkey.setPrivateKey(c.getBlob(c.getColumnIndexOrThrow(FIELD_PUBKEY_PRIVATE))); + pubkey.setPublicKey(c.getBlob(c.getColumnIndexOrThrow(FIELD_PUBKEY_PUBLIC))); + pubkey.setEncrypted(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_ENCRYPTED)) > 0); + pubkey.setStartup(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_STARTUP)) > 0); + pubkey.setConfirmUse(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_CONFIRMUSE)) > 0); + pubkey.setLifetime(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_LIFETIME))); + return pubkey; + } + + /** + * Pull all values for a given column as a list of Strings, probably for use + * in a ListPreference. Sorted by <code>_id</code> ascending. + */ + public List<CharSequence> allValues(String column) { + List<CharSequence> list = new LinkedList<CharSequence>(); + SQLiteDatabase db = this.getReadableDatabase(); + Cursor c = db.query(TABLE_PUBKEYS, new String[] { "_id", column }, + null, null, null, null, "_id ASC"); + + if (c != null) { + int COL = c.getColumnIndexOrThrow(column); + + while (c.moveToNext()) + list.add(c.getString(COL)); + + c.close(); + } + + db.close(); + return list; + } + + public String getNickname(long id) { + String nickname = null; + SQLiteDatabase db = this.getReadableDatabase(); + Cursor c = db.query(TABLE_PUBKEYS, new String[] { "_id", + FIELD_PUBKEY_NICKNAME + }, "_id = ?", + new String[] { Long.toString(id) }, null, null, null); + + if (c != null) { + if (c.moveToFirst()) + nickname = c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME)); + + c.close(); + } + + db.close(); + return nickname; + } + + /* + public void setOnStart(long id, boolean onStart) { + + SQLiteDatabase db = this.getWritableDatabase(); + + ContentValues values = new ContentValues(); + values.put(FIELD_PUBKEY_STARTUP, onStart ? 1 : 0); + + db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { Long.toString(id) }); + + } + + public boolean changePassword(long id, String oldPassword, String newPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException { + SQLiteDatabase db = this.getWritableDatabase(); + + Cursor c = db.query(TABLE_PUBKEYS, new String[] { FIELD_PUBKEY_TYPE, + FIELD_PUBKEY_PRIVATE, FIELD_PUBKEY_ENCRYPTED }, + "_id = ?", new String[] { String.valueOf(id) }, + null, null, null); + + if (!c.moveToFirst()) + return false; + + String keyType = c.getString(0); + byte[] encPriv = c.getBlob(1); + c.close(); + + PrivateKey priv; + try { + priv = PubkeyUtils.decodePrivate(encPriv, keyType, oldPassword); + } catch (InvalidKeyException e) { + return false; + } catch (BadPaddingException e) { + return false; + } catch (InvalidKeySpecException e) { + return false; + } + + ContentValues values = new ContentValues(); + values.put(FIELD_PUBKEY_PRIVATE, PubkeyUtils.getEncodedPrivate(priv, newPassword)); + values.put(FIELD_PUBKEY_ENCRYPTED, newPassword.length() > 0 ? 1 : 0); + db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(id) }); + + return true; + } + */ + + /** + * @param pubkey + */ + public PubkeyBean savePubkey(PubkeyBean pubkey) { + SQLiteDatabase db = this.getWritableDatabase(); + boolean success = false; + ContentValues values = pubkey.getValues(); + + if (pubkey.getId() > 0) { + values.remove("_id"); + + if (db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(pubkey.getId()) }) > 0) + success = true; + } + + if (!success) { + long id = db.insert(TABLE_PUBKEYS, null, pubkey.getValues()); + pubkey.setId(id); + } + + db.close(); + return pubkey; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/PubkeyUtils.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,392 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; +import java.security.spec.KeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.RSAPublicKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.EncryptedPrivateKeyInfo; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.keyczar.jce.EcCore; + +import com.five_ten_sg.connectbot.bean.PubkeyBean; +import android.util.Log; + +import ch.ethz.ssh2.crypto.Base64; +import ch.ethz.ssh2.crypto.SecureRandomFix; +import ch.ethz.ssh2.crypto.SimpleDERReader; +import ch.ethz.ssh2.signature.DSASHA1Verify; +import ch.ethz.ssh2.signature.ECDSASHA2Verify; +import ch.ethz.ssh2.signature.RSASHA1Verify; + +public class PubkeyUtils { + private static final String TAG = "PubkeyUtils"; + + public static final String PKCS8_START = "-----BEGIN PRIVATE KEY-----"; + public static final String PKCS8_END = "-----END PRIVATE KEY-----"; + + // Size in bytes of salt to use. + private static final int SALT_SIZE = 8; + + // Number of iterations for password hashing. PKCS#5 recommends 1000 + private static final int ITERATIONS = 1000; + + // Cannot be instantiated + private PubkeyUtils() { + } + + public static String formatKey(Key key) { + String algo = key.getAlgorithm(); + String fmt = key.getFormat(); + byte[] encoded = key.getEncoded(); + return "Key[algorithm=" + algo + ", format=" + fmt + + ", bytes=" + encoded.length + "]"; + } + + public static byte[] sha256(byte[] data) throws NoSuchAlgorithmException { + return MessageDigest.getInstance("SHA-256").digest(data); + } + + public static byte[] cipher(int mode, byte[] data, byte[] secret) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + SecretKeySpec secretKeySpec = new SecretKeySpec(sha256(secret), "AES"); + Cipher c = Cipher.getInstance("AES"); + c.init(mode, secretKeySpec); + return c.doFinal(data); + } + + public static byte[] encrypt(byte[] cleartext, String secret) throws Exception { + byte[] salt = new byte[SALT_SIZE]; + byte[] ciphertext = Encryptor.encrypt(salt, ITERATIONS, secret, cleartext); + byte[] complete = new byte[salt.length + ciphertext.length]; + System.arraycopy(salt, 0, complete, 0, salt.length); + System.arraycopy(ciphertext, 0, complete, salt.length, ciphertext.length); + Arrays.fill(salt, (byte) 0x00); + Arrays.fill(ciphertext, (byte) 0x00); + return complete; + } + + public static byte[] decrypt(byte[] saltAndCiphertext, String secret) throws Exception { + try { + byte[] salt = new byte[SALT_SIZE]; + byte[] ciphertext = new byte[saltAndCiphertext.length - salt.length]; + System.arraycopy(saltAndCiphertext, 0, salt, 0, salt.length); + System.arraycopy(saltAndCiphertext, salt.length, ciphertext, 0, ciphertext.length); + return Encryptor.decrypt(salt, ITERATIONS, secret, ciphertext); + } + catch (Exception e) { + Log.d("decrypt", "Could not decrypt with new method", e); + // We might be using the old encryption method. + return cipher(Cipher.DECRYPT_MODE, saltAndCiphertext, secret.getBytes()); + } + } + + public static byte[] getEncodedPrivate(PrivateKey pk, String secret) throws Exception { + final byte[] encoded = pk.getEncoded(); + + if (secret == null || secret.length() == 0) { + return encoded; + } + + return encrypt(pk.getEncoded(), secret); + } + + public static PrivateKey decodePrivate(byte[] encoded, String keyType) throws NoSuchAlgorithmException, InvalidKeySpecException { + PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(encoded); + KeyFactory kf = KeyFactory.getInstance(keyType); + return kf.generatePrivate(privKeySpec); + } + + public static PrivateKey decodePrivate(byte[] encoded, String keyType, String secret) throws Exception { + if (secret != null && secret.length() > 0) + return decodePrivate(decrypt(encoded, secret), keyType); + else + return decodePrivate(encoded, keyType); + } + + public static PublicKey decodePublic(byte[] encoded, String keyType) throws NoSuchAlgorithmException, InvalidKeySpecException { + X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encoded); + KeyFactory kf = KeyFactory.getInstance(keyType); + return kf.generatePublic(pubKeySpec); + } + + static String getAlgorithmForOid(String oid) throws NoSuchAlgorithmException { + if ("1.2.840.10045.2.1".equals(oid)) { + return "EC"; + } + else if ("1.2.840.113549.1.1.1".equals(oid)) { + return "RSA"; + } + else if ("1.2.840.10040.4.1".equals(oid)) { + return "DSA"; + } + else { + throw new NoSuchAlgorithmException("Unknown algorithm OID " + oid); + } + } + + static String getOidFromPkcs8Encoded(byte[] encoded) throws NoSuchAlgorithmException { + if (encoded == null) { + throw new NoSuchAlgorithmException("encoding is null"); + } + + try { + SimpleDERReader reader = new SimpleDERReader(encoded); + reader.resetInput(reader.readSequenceAsByteArray()); + reader.readInt(); + reader.resetInput(reader.readSequenceAsByteArray()); + return reader.readOid(); + } + catch (IOException e) { + Log.w(TAG, "Could not read OID", e); + throw new NoSuchAlgorithmException("Could not read key", e); + } + } + + public static KeyPair recoverKeyPair(byte[] encoded) throws NoSuchAlgorithmException, + InvalidKeySpecException { + final String algo = getAlgorithmForOid(getOidFromPkcs8Encoded(encoded)); + final KeySpec privKeySpec = new PKCS8EncodedKeySpec(encoded); + final KeyFactory kf = KeyFactory.getInstance(algo); + final PrivateKey priv = kf.generatePrivate(privKeySpec); + return new KeyPair(recoverPublicKey(kf, priv), priv); + } + + + static PublicKey recoverPublicKey(KeyFactory kf, PrivateKey priv) + throws NoSuchAlgorithmException, InvalidKeySpecException { + if (priv instanceof RSAPrivateCrtKey) { + RSAPrivateCrtKey rsaPriv = (RSAPrivateCrtKey) priv; + return kf.generatePublic(new RSAPublicKeySpec(rsaPriv.getModulus(), rsaPriv + .getPublicExponent())); + } + else if (priv instanceof DSAPrivateKey) { + DSAPrivateKey dsaPriv = (DSAPrivateKey) priv; + DSAParams params = dsaPriv.getParams(); + // Calculate public key Y + BigInteger y = params.getG().modPow(dsaPriv.getX(), params.getP()); + return kf.generatePublic(new DSAPublicKeySpec(y, params.getP(), params.getQ(), params + .getG())); + } + else if (priv instanceof ECPrivateKey) { + ECPrivateKey ecPriv = (ECPrivateKey) priv; + ECParameterSpec params = ecPriv.getParams(); + // Calculate public key Y + ECPoint generator = params.getGenerator(); + BigInteger[] wCoords = EcCore.multiplyPointA(new BigInteger[] { generator.getAffineX(), + generator.getAffineY() + }, ecPriv.getS(), params); + ECPoint w = new ECPoint(wCoords[0], wCoords[1]); + return kf.generatePublic(new ECPublicKeySpec(w, params)); + } + else { + throw new NoSuchAlgorithmException("Key type must be RSA, DSA, or EC"); + } + } + + /* + * OpenSSH compatibility methods + */ + + public static String convertToOpenSSHFormat(PublicKey pk, String origNickname) throws IOException, InvalidKeyException { + String nickname = origNickname; + + if (nickname == null) + nickname = "connectbot@android"; + + if (pk instanceof RSAPublicKey) { + String data = "ssh-rsa "; + data += String.valueOf(Base64.encode(RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey) pk))); + return data + " " + nickname; + } + else if (pk instanceof DSAPublicKey) { + String data = "ssh-dss "; + data += String.valueOf(Base64.encode(DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey) pk))); + return data + " " + nickname; + } + else if (pk instanceof ECPublicKey) { + ECPublicKey ecPub = (ECPublicKey) pk; + String keyType = ECDSASHA2Verify.getCurveName(ecPub.getParams().getCurve().getField().getFieldSize()); + String keyData = String.valueOf(Base64.encode(ECDSASHA2Verify.encodeSSHECDSAPublicKey(ecPub))); + return ECDSASHA2Verify.ECDSA_SHA2_PREFIX + keyType + " " + keyData + " " + nickname; + } + + throw new InvalidKeyException("Unknown key type"); + } + + /* + * OpenSSH compatibility methods + */ + + /** + * @param pair + * @return OpenSSH-encoded pubkey + */ + public static byte[] extractOpenSSHPublic(KeyPair pair) { + try { + PublicKey pubKey = pair.getPublic(); + + if (pubKey instanceof RSAPublicKey) { + return RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey) pair.getPublic()); + } + else if (pubKey instanceof DSAPublicKey) { + return DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey) pair.getPublic()); + } + else if (pubKey instanceof ECPublicKey) { + return ECDSASHA2Verify.encodeSSHECDSAPublicKey((ECPublicKey) pair.getPublic()); + } + else { + return null; + } + } + catch (IOException e) { + return null; + } + } + + public static String exportPEM(PrivateKey key, String secret) throws NoSuchAlgorithmException, InvalidParameterSpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, InvalidKeySpecException, IllegalBlockSizeException, IOException { + StringBuilder sb = new StringBuilder(); + byte[] data = key.getEncoded(); + sb.append(PKCS8_START); + sb.append('\n'); + + if (secret != null) { + byte[] salt = new byte[8]; + SecureRandomFix random = new SecureRandomFix(); + random.nextBytes(salt); + PBEParameterSpec defParams = new PBEParameterSpec(salt, 1); + AlgorithmParameters params = AlgorithmParameters.getInstance(key.getAlgorithm()); + params.init(defParams); + PBEKeySpec pbeSpec = new PBEKeySpec(secret.toCharArray()); + SecretKeyFactory keyFact = SecretKeyFactory.getInstance(key.getAlgorithm()); + Cipher cipher = Cipher.getInstance(key.getAlgorithm()); + cipher.init(Cipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), params); + byte[] wrappedKey = cipher.wrap(key); + EncryptedPrivateKeyInfo pinfo = new EncryptedPrivateKeyInfo(params, wrappedKey); + data = pinfo.getEncoded(); + sb.append("Proc-Type: 4,ENCRYPTED\n"); + sb.append("DEK-Info: DES-EDE3-CBC,"); + sb.append(encodeHex(salt)); + sb.append("\n\n"); + } + + int i = sb.length(); + sb.append(Base64.encode(data)); + + for (i += 63; i < sb.length(); i += 64) { + sb.insert(i, "\n"); + } + + sb.append('\n'); + sb.append(PKCS8_END); + sb.append('\n'); + return sb.toString(); + } + + private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', + '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + protected static String encodeHex(byte[] bytes) { + final char[] hex = new char[bytes.length * 2]; + int i = 0; + + for (byte b : bytes) { + hex[i++] = HEX_DIGITS[(b >> 4) & 0x0f]; + hex[i++] = HEX_DIGITS[b & 0x0f]; + } + + return String.valueOf(hex); + } + + public static String getPubkeyString(PubkeyBean pubkey) { + try { + PublicKey pk = decodePublic(pubkey.getPublicKey(), pubkey.getType()); + return convertToOpenSSHFormat(pk, pubkey.getNickname()); + } + catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + public static String getPrivkeyString(PubkeyBean pubkey, String passphrase) { + String data = null; + boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType()); + + if (imported) + try { + data = new String(pubkey.getPrivateKey()); + } + catch (Exception e) { + e.printStackTrace(); + } + else { + try { + PrivateKey pk = null; + + if (passphrase == null) + pk = decodePrivate(pubkey.getPrivateKey(), pubkey.getType()); + else + pk = decodePrivate(pubkey.getPrivateKey(), pubkey.getType(), passphrase); + + data = exportPEM(pk, passphrase); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + return data; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/RobustSQLiteOpenHelper.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,135 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import java.util.LinkedList; +import java.util.List; + +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDatabase.CursorFactory; +import android.database.sqlite.SQLiteException; +import android.database.sqlite.SQLiteOpenHelper; + +/** + * @author Kenny Root + * + */ +public abstract class RobustSQLiteOpenHelper extends SQLiteOpenHelper { + private static List<String> mTableNames = new LinkedList<String>(); + private static List<String> mIndexNames = new LinkedList<String>(); + + public RobustSQLiteOpenHelper(Context context, String name, + CursorFactory factory, int version) { + super(context, name, factory, version); + } + + protected static void addTableName(String tableName) { + mTableNames.add(tableName); + } + + protected static void addIndexName(String indexName) { + mIndexNames.add(indexName); + } + + @Override + public void onCreate(SQLiteDatabase db) { + dropAllTables(db); + } + + @Override + public final void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + try { + onRobustUpgrade(db, oldVersion, newVersion); + } + catch (SQLiteException e) { + // The database has entered an unknown state. Try to recover. + try { + regenerateTables(db); + } + catch (SQLiteException e2) { + dropAndCreateTables(db); + } + } + } + + public abstract void onRobustUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLiteException; + + private void regenerateTables(SQLiteDatabase db) { + dropAllTablesWithPrefix(db, "OLD_"); + + for (String tableName : mTableNames) + db.execSQL("ALTER TABLE " + tableName + " RENAME TO OLD_" + + tableName); + + onCreate(db); + + for (String tableName : mTableNames) + repopulateTable(db, tableName); + + dropAllTablesWithPrefix(db, "OLD_"); + } + + private void repopulateTable(SQLiteDatabase db, String tableName) { + String columns = getTableColumnNames(db, tableName); + StringBuilder sb = new StringBuilder(); + sb.append("INSERT INTO ") + .append(tableName) + .append(" (") + .append(columns) + .append(") SELECT ") + .append(columns) + .append(" FROM OLD_") + .append(tableName); + String sql = sb.toString(); + db.execSQL(sql); + } + + private String getTableColumnNames(SQLiteDatabase db, String tableName) { + StringBuilder sb = new StringBuilder(); + Cursor fields = db.rawQuery("PRAGMA table_info(" + tableName + ")", null); + + while (fields.moveToNext()) { + if (!fields.isFirst()) + sb.append(", "); + + sb.append(fields.getString(1)); + } + + fields.close(); + return sb.toString(); + } + + private void dropAndCreateTables(SQLiteDatabase db) { + dropAllTables(db); + onCreate(db); + } + + private void dropAllTablesWithPrefix(SQLiteDatabase db, String prefix) { + for (String indexName : mIndexNames) + db.execSQL("DROP INDEX IF EXISTS " + prefix + indexName); + + for (String tableName : mTableNames) + db.execSQL("DROP TABLE IF EXISTS " + prefix + tableName); + } + + private void dropAllTables(SQLiteDatabase db) { + dropAllTablesWithPrefix(db, ""); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/StringPickerDialog.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import com.five_ten_sg.connectbot.R; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.text.*; +import android.view.LayoutInflater; +import android.view.View.OnClickListener; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.GridView; + +/** + * Dialog for choosing accented characters related to a base character. + */ +public class StringPickerDialog extends Dialog + implements OnItemClickListener, OnClickListener { + private View mView; + private Editable mText; + private String []mOptions; + private boolean mInsert; + private LayoutInflater mInflater; + private Button mCancelButton; + + /** + * Creates a new StringPickerDialog that presents the specified + * <code>options</code> for insertion or replacement (depending on + * the sense of <code>insert</code>) into <code>text</code>. + */ + public StringPickerDialog(Context context, View view, + Editable text, String []options, + boolean insert) { + //super(context, com.android.internal.R.style.Theme_Panel); + //Resources res = Resources.getSystem(); + //int id = res.getIdentifier("Theme_Panel", "style", "android"); + //int id = android.R.style.Theme_Panel; + super(context, android.R.style.Theme_Panel); + mView = view; + mText = text; + mOptions = options; + mInsert = insert; + mInflater = LayoutInflater.from(context); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.token = mView.getApplicationWindowToken(); + params.type = params.TYPE_APPLICATION_ATTACHED_DIALOG; + params.flags = params.flags | Window.FEATURE_NO_TITLE; + setContentView(R.layout.string_picker); + GridView grid = (GridView) findViewById(R.id.stringPicker); + grid.setAdapter(new OptionsAdapter(getContext())); + grid.setOnItemClickListener(this); + mCancelButton = (Button) findViewById(R.id.cancel); + mCancelButton.setOnClickListener(this); + } + + /** + * Handles clicks on the character buttons. + */ + public void onItemClick(AdapterView parent, View view, int position, long id) { + String result = mOptions[position]; + replaceCharacterAndClose(result); + } + + private void replaceCharacterAndClose(CharSequence replace) { + int selEnd = Selection.getSelectionEnd(mText); + + if (mInsert || selEnd == 0) { + mText.insert(selEnd, replace); + } + else { + mText.replace(selEnd - 1, selEnd, replace); + } + + dismiss(); + } + + /** + * Handles clicks on the Cancel button. + */ + public void onClick(View v) { + if (v == mCancelButton) { + dismiss(); + } + else if (v instanceof Button) { + CharSequence result = ((Button) v).getText(); + replaceCharacterAndClose(result); + } + } + + private class OptionsAdapter extends BaseAdapter { + + public OptionsAdapter(Context context) { + super(); + } + + public View getView(int position, View convertView, ViewGroup parent) { + Button b = (Button) + mInflater.inflate(R.layout.string_picker_button, null); + b.setText(mOptions[position]); + b.setOnClickListener(StringPickerDialog.this); + return b; + } + + public final int getCount() { + return mOptions.length; + } + + public final Object getItem(int position) { + return mOptions[position]; + } + + public final long getItemId(int position) { + return position; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/TransferThread.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,150 @@ +/* + * TransferThread Class for VX ConnectBot + * Copyright 2012 Martin Matuska + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.five_ten_sg.connectbot.util; + +import java.util.StringTokenizer; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.os.Handler; +import android.preference.PreferenceManager; +import android.util.Log; +import android.widget.Toast; + +public class TransferThread extends Thread { + public final static String TAG = "ConnectBot.TransferThread"; + private final Activity activity; + private final SharedPreferences prefs; + private String dialogMessage = null; + private Handler handler = new Handler(); + private TerminalBridge bridge; + private String files, destName, destFolder; + private ProgressDialog progress = null; + private boolean upload; + private Toast progressToast = null; + + public TransferThread(Activity activity, Handler handler) { + this.activity = activity; +// this.handler = handler; + this.prefs = PreferenceManager.getDefaultSharedPreferences(this.activity); + } + + public void setProgressDialogMessage(String message) { + this.dialogMessage = message; + } + + public void download(TerminalBridge bridge, String files, String destName, String destFolder) { + this.bridge = bridge; + this.files = files; + this.destName = destName; + this.destFolder = destFolder; + this.upload = false; + this.configureProgressDialog(); + this.start(); + } + + public void upload(TerminalBridge bridge, String files, String destName, String destFolder) { + this.bridge = bridge; + this.files = files; + this.destName = destName; + this.destFolder = destFolder; + this.upload = true; + this.configureProgressDialog(); + this.start(); + } + + @Override + public void run() { + if (this.activity == null || this.handler == null || this.bridge == null) + return; + + Log.d(TAG, "Requested " + (upload ? "upload" : "download") + " of [" + files + "]"); + Resources res = activity.getResources(); + String fail = ""; + + try { + StringTokenizer fileSet = new StringTokenizer(files, "\n"); + + while (fileSet.hasMoreTokens()) { + String file = fileSet.nextToken(); + final String newMessage = res.getString(upload ? R.string.transfer_uploading_file : R.string.transfer_downloading_file, file); + handler.post(new Runnable() { + public void run() { + if (prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) { + if (progressToast == null) + progressToast = Toast.makeText(activity, newMessage, Toast.LENGTH_LONG); + else + progressToast.setText(newMessage); + + progressToast.show(); + } + else if (progress != null) { + progress.setMessage(newMessage); + } + } + }); + boolean success = (upload ? bridge.uploadFile(file, destName, destFolder, null) : bridge.downloadFile(file, destFolder)); + + if (! success) + fail += " " + file; + } + } + finally { + final String failMessage = (fail.length() == 0 ? null : res.getString(upload ? R.string.transfer_upload_failed : R.string.transfer_download_failed, fail)); + final String sucMessage = (res.getString(upload ? R.string.transfer_upload_complete : R.string.transfer_download_complete)); + handler.post(new Runnable() { + public void run() { + if (progress != null) + progress.dismiss(); + + if (prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) { + Toast.makeText(activity, + failMessage != null ? failMessage : sucMessage, + Toast.LENGTH_LONG) + .show(); + } + else if (failMessage != null) { + new AlertDialog.Builder(activity) + .setMessage(failMessage) + .setNegativeButton(android.R.string.ok, null).create().show(); + } + } + }); + } + } + + private void configureProgressDialog() { + if (dialogMessage != null) + progress = fileProgressDialog(activity, this.dialogMessage); + else + progress = null; + } + + private ProgressDialog fileProgressDialog(Activity activity, String message) { + ProgressDialog progress = new ProgressDialog(activity); + progress.setIndeterminate(true); + progress.setMessage(message); + progress.setCancelable(false); + progress.show(); + return progress; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/UberColorPickerDialog.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,947 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * 090408 + * Keith Wiley + * kwiley@keithwiley.com + * http://keithwiley.com + * + * UberColorPickerDialog v1.1 + * + * This color picker was implemented as a (significant) extension of the + * ColorPickerDialog class provided in the Android API Demos. You are free + * to drop it unchanged into your own projects or to modify it as you see + * fit. I would appreciate it if this comment block were let intact, + * merely for credit's sake. + * + * Enjoy! + */ + +package com.five_ten_sg.connectbot.util; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorMatrix; +import android.graphics.ComposeShader; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RadialGradient; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.SweepGradient; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.GradientDrawable.Orientation; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.util.FloatMath; +import android.view.MotionEvent; +import android.view.View; + +/** + * UberColorPickerDialog is a seriously enhanced version of the UberColorPickerDialog + * class provided in the Android API Demos.<p> + * + * NOTE (from Kenny Root): This is a VERY slimmed down version custom for ConnectBot. + * Visit Keith's site for the full version at the URL listed in the author line.<p> + * + * @author Keith Wiley, kwiley@keithwiley.com, http://keithwiley.com + */ +public class UberColorPickerDialog extends Dialog { + private final OnColorChangedListener mListener; + private final int mInitialColor; + + /** + * Callback to the creator of the dialog, informing the creator of a new color and notifying that the dialog is about to dismiss. + */ + public interface OnColorChangedListener { + void colorChanged(int color); + } + + /** + * Ctor + * @param context + * @param listener + * @param initialColor + * @param showTitle If true, a title is shown across the top of the dialog. If false a toast is shown instead. + */ + public UberColorPickerDialog(Context context, + OnColorChangedListener listener, + int initialColor) { + super(context); + mListener = listener; + mInitialColor = initialColor; + } + + /** + * Activity entry point + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + OnColorChangedListener l = new OnColorChangedListener() { + public void colorChanged(int color) { + mListener.colorChanged(color); + dismiss(); + } + }; + DisplayMetrics dm = new DisplayMetrics(); + getWindow().getWindowManager().getDefaultDisplay().getMetrics(dm); + int screenWidth = dm.widthPixels; + int screenHeight = dm.heightPixels; + setTitle("Pick a color (try the trackball)"); + + try { + setContentView(new ColorPickerView(getContext(), l, screenWidth, screenHeight, mInitialColor)); + } + catch (Exception e) { + //There is currently only one kind of ctor exception, that where no methods are enabled. + dismiss(); //This doesn't work! The dialog is still shown (its title at least, the layout is empty from the exception being thrown). <sigh> + } + } + + /** + * ColorPickerView is the meat of this color picker (as opposed to the enclosing class). + * All the heavy lifting is done directly by this View subclass. + * <P> + * You can enable/disable whichever color chooser methods you want by modifying the ENABLED_METHODS switches. They *should* + * do all the work required to properly enable/disable methods without losing track of what goes with what and what maps to what. + * <P> + * If you add a new color chooser method, do a text search for "NEW_METHOD_WORK_NEEDED_HERE". That tag indicates all + * the locations in the code that will have to be amended in order to properly add a new color chooser method. + * I highly recommend adding new methods to the end of the list. If you want to try to reorder the list, you're on your own. + */ + private static class ColorPickerView extends View { + private static int SWATCH_WIDTH = 95; + private static final int SWATCH_HEIGHT = 60; + + private static int PALETTE_POS_X = 0; + private static int PALETTE_POS_Y = SWATCH_HEIGHT; + private static final int PALETTE_DIM = SWATCH_WIDTH * 2; + private static final int PALETTE_RADIUS = PALETTE_DIM / 2; + private static final int PALETTE_CENTER_X = PALETTE_RADIUS; + private static final int PALETTE_CENTER_Y = PALETTE_RADIUS; + + private static final int SLIDER_THICKNESS = 40; + + private static int VIEW_DIM_X = PALETTE_DIM; + private static int VIEW_DIM_Y = SWATCH_HEIGHT; + + //NEW_METHOD_WORK_NEEDED_HERE + private static final int METHOD_HS_V_PALETTE = 0; + + //NEW_METHOD_WORK_NEEDED_HERE + //Add a new entry to the list for each controller in the new method + private static final int TRACKED_NONE = -1; //No object on screen is currently being tracked + private static final int TRACK_SWATCH_OLD = 10; + private static final int TRACK_SWATCH_NEW = 11; + private static final int TRACK_HS_PALETTE = 30; + private static final int TRACK_VER_VALUE_SLIDER = 31; + + private static final int TEXT_SIZE = 12; + private static int[] TEXT_HSV_POS = new int[2]; + private static int[] TEXT_RGB_POS = new int[2]; + private static int[] TEXT_YUV_POS = new int[2]; + private static int[] TEXT_HEX_POS = new int[2]; + + private static final float PI = 3.141592653589793f; + + private int mMethod = METHOD_HS_V_PALETTE; + private int mTracking = TRACKED_NONE; //What object on screen is currently being tracked for movement + + //Zillions of persistant Paint objecs for drawing the View + + private Paint mSwatchOld, mSwatchNew; + + //NEW_METHOD_WORK_NEEDED_HERE + //Add Paints to represent the palettes of the new method's UI controllers + private Paint mOvalHueSat; + + private Bitmap mVerSliderBM; + private Canvas mVerSliderCv; + + private Bitmap[] mHorSlidersBM = new Bitmap[3]; + private Canvas[] mHorSlidersCv = new Canvas[3]; + + private Paint mValDimmer; + + //NEW_METHOD_WORK_NEEDED_HERE + //Add Paints to represent the icon for the new method + private Paint mOvalHueSatSmall; + + private Paint mPosMarker; + private Paint mText; + + private Rect mOldSwatchRect = new Rect(); + private Rect mNewSwatchRect = new Rect(); + private Rect mPaletteRect = new Rect(); + private Rect mVerSliderRect = new Rect(); + + private int[] mSpectrumColorsRev; + private int mOriginalColor = 0; //The color passed in at the beginning, which can be reverted to at any time by tapping the old swatch. + private float[] mHSV = new float[3]; + private int[] mRGB = new int[3]; + private float[] mYUV = new float[3]; + private String mHexStr = ""; + private boolean mHSVenabled = true; //Only true if an HSV method is enabled + private boolean mRGBenabled = true; //Only true if an RGB method is enabled + private boolean mYUVenabled = true; //Only true if a YUV method is enabled + private boolean mHexenabled = true; //Only true if an RGB method is enabled + private int[] mCoord = new int[3]; //For drawing slider/palette markers + private int mFocusedControl = -1; //Which control receives trackball events. + private OnColorChangedListener mListener; + + /** + * Ctor. + * @param c + * @param l + * @param width Used to determine orientation and adjust layout accordingly + * @param height Used to determine orientation and adjust layout accordingly + * @param color The initial color + * @throws Exception + */ + ColorPickerView(Context c, OnColorChangedListener l, int width, int height, int color) + throws Exception { + super(c); + //We need to make the dialog focusable to retrieve trackball events. + setFocusable(true); + mListener = l; + mOriginalColor = color; + Color.colorToHSV(color, mHSV); + updateAllFromHSV(); + + //Setup the layout based on whether this is a portrait or landscape orientation. + if (width <= height) { //Portrait layout + SWATCH_WIDTH = (PALETTE_DIM + SLIDER_THICKNESS) / 2; + PALETTE_POS_X = 0; + PALETTE_POS_Y = TEXT_SIZE * 4 + SWATCH_HEIGHT; + //Set more rects, lots of rects + mOldSwatchRect.set(0, TEXT_SIZE * 4, SWATCH_WIDTH, TEXT_SIZE * 4 + SWATCH_HEIGHT); + mNewSwatchRect.set(SWATCH_WIDTH, TEXT_SIZE * 4, SWATCH_WIDTH * 2, TEXT_SIZE * 4 + SWATCH_HEIGHT); + mPaletteRect.set(0, PALETTE_POS_Y, PALETTE_DIM, PALETTE_POS_Y + PALETTE_DIM); + mVerSliderRect.set(PALETTE_DIM, PALETTE_POS_Y, PALETTE_DIM + SLIDER_THICKNESS, PALETTE_POS_Y + PALETTE_DIM); + TEXT_HSV_POS[0] = 3; + TEXT_HSV_POS[1] = 0; + TEXT_RGB_POS[0] = TEXT_HSV_POS[0] + 50; + TEXT_RGB_POS[1] = TEXT_HSV_POS[1]; + TEXT_YUV_POS[0] = TEXT_HSV_POS[0] + 100; + TEXT_YUV_POS[1] = TEXT_HSV_POS[1]; + TEXT_HEX_POS[0] = TEXT_HSV_POS[0] + 150; + TEXT_HEX_POS[1] = TEXT_HSV_POS[1]; + VIEW_DIM_X = PALETTE_DIM + SLIDER_THICKNESS; + VIEW_DIM_Y = SWATCH_HEIGHT + PALETTE_DIM + TEXT_SIZE * 4; + } + else { //Landscape layout + SWATCH_WIDTH = 110; + PALETTE_POS_X = SWATCH_WIDTH; + PALETTE_POS_Y = 0; + //Set more rects, lots of rects + mOldSwatchRect.set(0, TEXT_SIZE * 7, SWATCH_WIDTH, TEXT_SIZE * 7 + SWATCH_HEIGHT); + mNewSwatchRect.set(0, TEXT_SIZE * 7 + SWATCH_HEIGHT, SWATCH_WIDTH, TEXT_SIZE * 7 + SWATCH_HEIGHT * 2); + mPaletteRect.set(SWATCH_WIDTH, PALETTE_POS_Y, SWATCH_WIDTH + PALETTE_DIM, PALETTE_POS_Y + PALETTE_DIM); + mVerSliderRect.set(SWATCH_WIDTH + PALETTE_DIM, PALETTE_POS_Y, SWATCH_WIDTH + PALETTE_DIM + SLIDER_THICKNESS, PALETTE_POS_Y + PALETTE_DIM); + TEXT_HSV_POS[0] = 3; + TEXT_HSV_POS[1] = 0; + TEXT_RGB_POS[0] = TEXT_HSV_POS[0]; + TEXT_RGB_POS[1] = (int)(TEXT_HSV_POS[1] + TEXT_SIZE * 3.5); + TEXT_YUV_POS[0] = TEXT_HSV_POS[0] + 50; + TEXT_YUV_POS[1] = (int)(TEXT_HSV_POS[1] + TEXT_SIZE * 3.5); + TEXT_HEX_POS[0] = TEXT_HSV_POS[0] + 50; + TEXT_HEX_POS[1] = TEXT_HSV_POS[1]; + VIEW_DIM_X = PALETTE_POS_X + PALETTE_DIM + SLIDER_THICKNESS; + VIEW_DIM_Y = Math.max(mNewSwatchRect.bottom, PALETTE_DIM); + } + + //Rainbows make everybody happy! + mSpectrumColorsRev = new int[] { + 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF, + 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000, + }; + //Setup all the Paint and Shader objects. There are lots of them! + //NEW_METHOD_WORK_NEEDED_HERE + //Add Paints to represent the palettes of the new method's UI controllers + mSwatchOld = new Paint(Paint.ANTI_ALIAS_FLAG); + mSwatchOld.setStyle(Paint.Style.FILL); + mSwatchOld.setColor(Color.HSVToColor(mHSV)); + mSwatchNew = new Paint(Paint.ANTI_ALIAS_FLAG); + mSwatchNew.setStyle(Paint.Style.FILL); + mSwatchNew.setColor(Color.HSVToColor(mHSV)); + Shader shaderA = new SweepGradient(0, 0, mSpectrumColorsRev, null); + Shader shaderB = new RadialGradient(0, 0, PALETTE_CENTER_X, 0xFFFFFFFF, 0xFF000000, Shader.TileMode.CLAMP); + Shader shader = new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SCREEN); + mOvalHueSat = new Paint(Paint.ANTI_ALIAS_FLAG); + mOvalHueSat.setShader(shader); + mOvalHueSat.setStyle(Paint.Style.FILL); + mOvalHueSat.setDither(true); + mVerSliderBM = Bitmap.createBitmap(SLIDER_THICKNESS, PALETTE_DIM, Bitmap.Config.RGB_565); + mVerSliderCv = new Canvas(mVerSliderBM); + + for (int i = 0; i < 3; i++) { + mHorSlidersBM[i] = Bitmap.createBitmap(PALETTE_DIM, SLIDER_THICKNESS, Bitmap.Config.RGB_565); + mHorSlidersCv[i] = new Canvas(mHorSlidersBM[i]); + } + + mValDimmer = new Paint(Paint.ANTI_ALIAS_FLAG); + mValDimmer.setStyle(Paint.Style.FILL); + mValDimmer.setDither(true); + mValDimmer.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); + //Whew, we're done making the big Paints and Shaders for the swatches, palettes, and sliders. + //Now we need to make the Paints and Shaders that will draw the little method icons in the method selector list. + //NEW_METHOD_WORK_NEEDED_HERE + //Add Paints to represent the icon for the new method + shaderA = new SweepGradient(0, 0, mSpectrumColorsRev, null); + shaderB = new RadialGradient(0, 0, PALETTE_DIM / 2, 0xFFFFFFFF, 0xFF000000, Shader.TileMode.CLAMP); + shader = new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SCREEN); + mOvalHueSatSmall = new Paint(Paint.ANTI_ALIAS_FLAG); + mOvalHueSatSmall.setShader(shader); + mOvalHueSatSmall.setStyle(Paint.Style.FILL); + //Make a simple stroking Paint for drawing markers and borders and stuff like that. + mPosMarker = new Paint(Paint.ANTI_ALIAS_FLAG); + mPosMarker.setStyle(Paint.Style.STROKE); + mPosMarker.setStrokeWidth(2); + //Make a basic text Paint. + mText = new Paint(Paint.ANTI_ALIAS_FLAG); + mText.setTextSize(TEXT_SIZE); + mText.setColor(Color.WHITE); + //Kickstart + initUI(); + } + + /** + * Draw the entire view (the entire dialog). + */ + @Override + protected void onDraw(Canvas canvas) { + //Draw the old and new swatches + drawSwatches(canvas); + //Write the text + writeColorParams(canvas); + + //Draw the palette and sliders (the UI) + if (mMethod == METHOD_HS_V_PALETTE) + drawHSV1Palette(canvas); + } + + /** + * Draw the old and new swatches. + * @param canvas + */ + private void drawSwatches(Canvas canvas) { + float[] hsv = new float[3]; + mText.setTextSize(16); + //Draw the original swatch + canvas.drawRect(mOldSwatchRect, mSwatchOld); + Color.colorToHSV(mOriginalColor, hsv); + + //if (UberColorPickerDialog.isGray(mColor)) //Don't need this right here, but imp't to note + // hsv[1] = 0; + if (hsv[2] > .5) + mText.setColor(Color.BLACK); + + canvas.drawText("Revert", mOldSwatchRect.left + SWATCH_WIDTH / 2 - mText.measureText("Revert") / 2, mOldSwatchRect.top + 16, mText); + mText.setColor(Color.WHITE); + //Draw the new swatch + canvas.drawRect(mNewSwatchRect, mSwatchNew); + + if (mHSV[2] > .5) + mText.setColor(Color.BLACK); + + canvas.drawText("Accept", mNewSwatchRect.left + SWATCH_WIDTH / 2 - mText.measureText("Accept") / 2, mNewSwatchRect.top + 16, mText); + mText.setColor(Color.WHITE); + mText.setTextSize(TEXT_SIZE); + } + + /** + * Write the color parametes (HSV, RGB, YUV, Hex, etc.). + * @param canvas + */ + private void writeColorParams(Canvas canvas) { + if (mHSVenabled) { + canvas.drawText("H: " + Integer.toString((int)(mHSV[0] / 360.0f * 255)), TEXT_HSV_POS[0], TEXT_HSV_POS[1] + TEXT_SIZE, mText); + canvas.drawText("S: " + Integer.toString((int)(mHSV[1] * 255)), TEXT_HSV_POS[0], TEXT_HSV_POS[1] + TEXT_SIZE * 2, mText); + canvas.drawText("V: " + Integer.toString((int)(mHSV[2] * 255)), TEXT_HSV_POS[0], TEXT_HSV_POS[1] + TEXT_SIZE * 3, mText); + } + + if (mRGBenabled) { + canvas.drawText("R: " + mRGB[0], TEXT_RGB_POS[0], TEXT_RGB_POS[1] + TEXT_SIZE, mText); + canvas.drawText("G: " + mRGB[1], TEXT_RGB_POS[0], TEXT_RGB_POS[1] + TEXT_SIZE * 2, mText); + canvas.drawText("B: " + mRGB[2], TEXT_RGB_POS[0], TEXT_RGB_POS[1] + TEXT_SIZE * 3, mText); + } + + if (mYUVenabled) { + canvas.drawText("Y: " + Integer.toString((int)(mYUV[0] * 255)), TEXT_YUV_POS[0], TEXT_YUV_POS[1] + TEXT_SIZE, mText); + canvas.drawText("U: " + Integer.toString((int)((mYUV[1] + .5f) * 255)), TEXT_YUV_POS[0], TEXT_YUV_POS[1] + TEXT_SIZE * 2, mText); + canvas.drawText("V: " + Integer.toString((int)((mYUV[2] + .5f) * 255)), TEXT_YUV_POS[0], TEXT_YUV_POS[1] + TEXT_SIZE * 3, mText); + } + + if (mHexenabled) + canvas.drawText("#" + mHexStr, TEXT_HEX_POS[0], TEXT_HEX_POS[1] + TEXT_SIZE, mText); + } + + /** + * Place a small circle on the 2D palette to indicate the current values. + * @param canvas + * @param markerPosX + * @param markerPosY + */ + private void mark2DPalette(Canvas canvas, int markerPosX, int markerPosY) { + mPosMarker.setColor(Color.BLACK); + canvas.drawOval(new RectF(markerPosX - 5, markerPosY - 5, markerPosX + 5, markerPosY + 5), mPosMarker); + mPosMarker.setColor(Color.WHITE); + canvas.drawOval(new RectF(markerPosX - 3, markerPosY - 3, markerPosX + 3, markerPosY + 3), mPosMarker); + } + + /** + * Draw a line across the slider to indicate its current value. + * @param canvas + * @param markerPos + */ + private void markVerSlider(Canvas canvas, int markerPos) { + mPosMarker.setColor(Color.BLACK); + canvas.drawRect(new Rect(0, markerPos - 2, SLIDER_THICKNESS, markerPos + 3), mPosMarker); + mPosMarker.setColor(Color.WHITE); + canvas.drawRect(new Rect(0, markerPos, SLIDER_THICKNESS, markerPos + 1), mPosMarker); + } + + /** + * Frame the slider to indicate that it has trackball focus. + * @param canvas + */ + private void hilightFocusedVerSlider(Canvas canvas) { + mPosMarker.setColor(Color.WHITE); + canvas.drawRect(new Rect(0, 0, SLIDER_THICKNESS, PALETTE_DIM), mPosMarker); + mPosMarker.setColor(Color.BLACK); + canvas.drawRect(new Rect(2, 2, SLIDER_THICKNESS - 2, PALETTE_DIM - 2), mPosMarker); + } + + /** + * Frame the 2D palette to indicate that it has trackball focus. + * @param canvas + */ + private void hilightFocusedOvalPalette(Canvas canvas) { + mPosMarker.setColor(Color.WHITE); + canvas.drawOval(new RectF(-PALETTE_RADIUS, -PALETTE_RADIUS, PALETTE_RADIUS, PALETTE_RADIUS), mPosMarker); + mPosMarker.setColor(Color.BLACK); + canvas.drawOval(new RectF(-PALETTE_RADIUS + 2, -PALETTE_RADIUS + 2, PALETTE_RADIUS - 2, PALETTE_RADIUS - 2), mPosMarker); + } + + //NEW_METHOD_WORK_NEEDED_HERE + //To add a new method, replicate the basic draw functions here. Use the 2D palette or 1D sliders as templates for the new method. + /** + * Draw the UI for HSV with angular H and radial S combined in 2D and a 1D V slider. + * @param canvas + */ + private void drawHSV1Palette(Canvas canvas) { + canvas.save(); + canvas.translate(PALETTE_POS_X, PALETTE_POS_Y); + //Draw the 2D palette + canvas.translate(PALETTE_CENTER_X, PALETTE_CENTER_Y); + canvas.drawOval(new RectF(-PALETTE_RADIUS, -PALETTE_RADIUS, PALETTE_RADIUS, PALETTE_RADIUS), mOvalHueSat); + canvas.drawOval(new RectF(-PALETTE_RADIUS, -PALETTE_RADIUS, PALETTE_RADIUS, PALETTE_RADIUS), mValDimmer); + + if (mFocusedControl == 0) + hilightFocusedOvalPalette(canvas); + + mark2DPalette(canvas, mCoord[0], mCoord[1]); + canvas.translate(-PALETTE_CENTER_X, -PALETTE_CENTER_Y); + //Draw the 1D slider + canvas.translate(PALETTE_DIM, 0); + canvas.drawBitmap(mVerSliderBM, 0, 0, null); + + if (mFocusedControl == 1) + hilightFocusedVerSlider(canvas); + + markVerSlider(canvas, mCoord[2]); + canvas.restore(); + } + + /** + * Initialize the current color chooser's UI (set its color parameters and set its palette and slider values accordingly). + */ + private void initUI() { + initHSV1Palette(); + //Focus on the first controller (arbitrary). + mFocusedControl = 0; + } + + //NEW_METHOD_WORK_NEEDED_HERE + //To add a new method, replicate and extend the last init function shown below + /** + * Initialize a color chooser. + */ + private void initHSV1Palette() { + setOvalValDimmer(); + setVerValSlider(); + float angle = 2 * PI - mHSV[0] / (180 / 3.1415927f); + float radius = mHSV[1] * PALETTE_RADIUS; + mCoord[0] = (int)(FloatMath.cos(angle) * radius); + mCoord[1] = (int)(FloatMath.sin(angle) * radius); + mCoord[2] = PALETTE_DIM - (int)(mHSV[2] * PALETTE_DIM); + } + + //NEW_METHOD_WORK_NEEDED_HERE + //To add a new method, replicate and extend the set functions below, one per UI controller in the new method + /** + * Adjust a Paint which, when painted, dims its underlying object to show the effects of varying value (brightness). + */ + private void setOvalValDimmer() { + float[] hsv = new float[3]; + hsv[0] = mHSV[0]; + hsv[1] = 0; + hsv[2] = mHSV[2]; + int gray = Color.HSVToColor(hsv); + mValDimmer.setColor(gray); + } + + /** + * Create a linear gradient shader to show variations in value. + */ + private void setVerValSlider() { + float[] hsv = new float[3]; + hsv[0] = mHSV[0]; + hsv[1] = mHSV[1]; + hsv[2] = 1; + int col = Color.HSVToColor(hsv); + int colors[] = new int[2]; + colors[0] = col; + colors[1] = 0xFF000000; + GradientDrawable gradDraw = new GradientDrawable(Orientation.TOP_BOTTOM, colors); + gradDraw.setDither(true); + gradDraw.setLevel(10000); + gradDraw.setBounds(0, 0, SLIDER_THICKNESS, PALETTE_DIM); + gradDraw.draw(mVerSliderCv); + } + + /** + * Report the correct tightly bounded dimensions of the view. + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(VIEW_DIM_X, VIEW_DIM_Y); + } + + /** + * Wrap Math.round(). I'm not a Java expert. Is this the only way to avoid writing "(int)Math.round" everywhere? + * @param x + * @return + */ + private int round(double x) { + return (int)Math.round(x); + } + + /** + * Limit a value to the range [0,1]. + * @param n + * @return + */ + private float pinToUnit(float n) { + if (n < 0) { + n = 0; + } + else if (n > 1) { + n = 1; + } + + return n; + } + + /** + * Limit a value to the range [0,max]. + * @param n + * @param max + * @return + */ + private float pin(float n, float max) { + if (n < 0) { + n = 0; + } + else if (n > max) { + n = max; + } + + return n; + } + + /** + * Limit a value to the range [min,max]. + * @param n + * @param min + * @param max + * @return + */ + private float pin(float n, float min, float max) { + if (n < min) { + n = min; + } + else if (n > max) { + n = max; + } + + return n; + } + + /** + * No clue what this does (some sort of average/mean I presume). It came with the original UberColorPickerDialog + * in the API Demos and wasn't documented. I don't feel like spending any time figuring it out, I haven't looked at it at all. + * @param s + * @param d + * @param p + * @return + */ + private int ave(int s, int d, float p) { + return s + round(p * (d - s)); + } + + /** + * Came with the original UberColorPickerDialog in the API Demos, wasn't documented. I believe it takes an array of + * colors and a value in the range [0,1] and interpolates a resulting color in a seemingly predictable manner. + * I haven't looked at it at all. + * @param colors + * @param unit + * @return + */ + private int interpColor(int colors[], float unit) { + if (unit <= 0) { + return colors[0]; + } + + if (unit >= 1) { + return colors[colors.length - 1]; + } + + float p = unit * (colors.length - 1); + int i = (int)p; + p -= i; + // now p is just the fractional part [0...1) and i is the index + int c0 = colors[i]; + int c1 = colors[i + 1]; + int a = ave(Color.alpha(c0), Color.alpha(c1), p); + int r = ave(Color.red(c0), Color.red(c1), p); + int g = ave(Color.green(c0), Color.green(c1), p); + int b = ave(Color.blue(c0), Color.blue(c1), p); + return Color.argb(a, r, g, b); + } + + /** + * A standard point-in-rect routine. + * @param x + * @param y + * @param r + * @return true if point x,y is in rect r + */ + public boolean ptInRect(int x, int y, Rect r) { + return x > r.left && x < r.right && y > r.top && y < r.bottom; + } + + /** + * Process trackball events. Used mainly for fine-tuned color adjustment, or alternatively to switch between slider controls. + */ + @Override + public boolean dispatchTrackballEvent(MotionEvent event) { + float x = event.getX(); + float y = event.getY(); + //A longer event history implies faster trackball movement. + //Use it to infer a larger jump and therefore faster palette/slider adjustment. + int jump = event.getHistorySize() + 1; + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + } + break; + + case MotionEvent.ACTION_MOVE: { + //NEW_METHOD_WORK_NEEDED_HERE + //To add a new method, replicate and extend the appropriate entry in this list, + //depending on whether you use 1D or 2D controllers + switch (mMethod) { + case METHOD_HS_V_PALETTE: + if (mFocusedControl == 0) { + changeHSPalette(x, y, jump); + } + else if (mFocusedControl == 1) { + if (y < 0) + changeSlider(mFocusedControl, true, jump); + else if (y > 0) + changeSlider(mFocusedControl, false, jump); + } + + break; + } + } + break; + + case MotionEvent.ACTION_UP: { + } + break; + } + + return true; + } + + //NEW_METHOD_WORK_NEEDED_HERE + //To add a new method, replicate and extend the appropriate functions below, + //one per UI controller in the new method + /** + * Effect a trackball change to a 2D palette. + * @param x -1: negative x change, 0: no x change, +1: positive x change. + * @param y -1: negative y change, 0, no y change, +1: positive y change. + * @param jump the amount by which to change. + */ + private void changeHSPalette(float x, float y, int jump) { + int x2 = 0, y2 = 0; + + if (x < 0) + x2 = -jump; + else if (x > 0) + x2 = jump; + + if (y < 0) + y2 = -jump; + else if (y > 0) + y2 = jump; + + mCoord[0] += x2; + mCoord[1] += y2; + + if (mCoord[0] < -PALETTE_RADIUS) + mCoord[0] = -PALETTE_RADIUS; + else if (mCoord[0] > PALETTE_RADIUS) + mCoord[0] = PALETTE_RADIUS; + + if (mCoord[1] < -PALETTE_RADIUS) + mCoord[1] = -PALETTE_RADIUS; + else if (mCoord[1] > PALETTE_RADIUS) + mCoord[1] = PALETTE_RADIUS; + + float radius = FloatMath.sqrt(mCoord[0] * mCoord[0] + mCoord[1] * mCoord[1]); + + if (radius > PALETTE_RADIUS) + radius = PALETTE_RADIUS; + + float angle = (float)Math.atan2(mCoord[1], mCoord[0]); + // need to turn angle [-PI ... PI] into unit [0....1] + float unit = angle / (2 * PI); + + if (unit < 0) { + unit += 1; + } + + mCoord[0] = round(FloatMath.cos(angle) * radius); + mCoord[1] = round(FloatMath.sin(angle) * radius); + int c = interpColor(mSpectrumColorsRev, unit); + float[] hsv = new float[3]; + Color.colorToHSV(c, hsv); + mHSV[0] = hsv[0]; + mHSV[1] = radius / PALETTE_RADIUS; + updateAllFromHSV(); + mSwatchNew.setColor(Color.HSVToColor(mHSV)); + setVerValSlider(); + invalidate(); + } + + /** + * Effect a trackball change to a 1D slider. + * @param slider id of the slider to be effected + * @param increase true if the change is an increase, false if a decrease + * @param jump the amount by which to change in units of the range [0,255] + */ + private void changeSlider(int slider, boolean increase, int jump) { + //NEW_METHOD_WORK_NEEDED_HERE + //It is only necessary to add an entry here for a new method if the new method uses a 1D slider. + //Note, some sliders are horizontal and others are vertical. + //They differ a bit, especially in a sign flip on the vertical axis. + if (mMethod == METHOD_HS_V_PALETTE) { + //slider *must* equal 1 + mHSV[2] += (increase ? jump : -jump) / 256.0f; + mHSV[2] = pinToUnit(mHSV[2]); + updateAllFromHSV(); + mCoord[2] = PALETTE_DIM - (int)(mHSV[2] * PALETTE_DIM); + mSwatchNew.setColor(Color.HSVToColor(mHSV)); + setOvalValDimmer(); + invalidate(); + } + } + + /** + * Keep all colorspace representations in sync. + */ + private void updateRGBfromHSV() { + int color = Color.HSVToColor(mHSV); + mRGB[0] = Color.red(color); + mRGB[1] = Color.green(color); + mRGB[2] = Color.blue(color); + } + + /** + * Keep all colorspace representations in sync. + */ + private void updateYUVfromRGB() { + float r = mRGB[0] / 255.0f; + float g = mRGB[1] / 255.0f; + float b = mRGB[2] / 255.0f; + ColorMatrix cm = new ColorMatrix(); + cm.setRGB2YUV(); + final float[] a = cm.getArray(); + mYUV[0] = a[0] * r + a[1] * g + a[2] * b; + mYUV[0] = pinToUnit(mYUV[0]); + mYUV[1] = a[5] * r + a[6] * g + a[7] * b; + mYUV[1] = pin(mYUV[1], -.5f, .5f); + mYUV[2] = a[10] * r + a[11] * g + a[12] * b; + mYUV[2] = pin(mYUV[2], -.5f, .5f); + } + + /** + * Keep all colorspace representations in sync. + */ + private void updateHexFromHSV() { + //For now, assume 100% opacity + mHexStr = Integer.toHexString(Color.HSVToColor(mHSV)).toUpperCase(); + mHexStr = mHexStr.substring(2, mHexStr.length()); + } + + /** + * Keep all colorspace representations in sync. + */ + private void updateAllFromHSV() { + //Update mRGB + if (mRGBenabled || mYUVenabled) + updateRGBfromHSV(); + + //Update mYUV + if (mYUVenabled) + updateYUVfromRGB(); + + //Update mHexStr + if (mRGBenabled) + updateHexFromHSV(); + } + + /** + * Process touch events: down, move, and up + */ + @Override + public boolean onTouchEvent(MotionEvent event) { + float x = event.getX(); + float y = event.getY(); + //Generate coordinates which are palette=local with the origin at the upper left of the main 2D palette + int y2 = (int)(pin(round(y - PALETTE_POS_Y), PALETTE_DIM)); + //Generate coordinates which are palette-local with the origin at the center of the main 2D palette + float circlePinnedX = x - PALETTE_POS_X - PALETTE_CENTER_X; + float circlePinnedY = y - PALETTE_POS_Y - PALETTE_CENTER_Y; + //Is the event in a swatch? + boolean inSwatchOld = ptInRect(round(x), round(y), mOldSwatchRect); + boolean inSwatchNew = ptInRect(round(x), round(y), mNewSwatchRect); + //Get the event's distance from the center of the main 2D palette + float radius = FloatMath.sqrt(circlePinnedX * circlePinnedX + circlePinnedY * circlePinnedY); + //Is the event in a circle-pinned 2D palette? + boolean inOvalPalette = radius <= PALETTE_RADIUS; + + //Pin the radius + if (radius > PALETTE_RADIUS) + radius = PALETTE_RADIUS; + + //Is the event in a vertical slider to the right of the main 2D palette + boolean inVerSlider = ptInRect(round(x), round(y), mVerSliderRect); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + mTracking = TRACKED_NONE; + + if (inSwatchOld) + mTracking = TRACK_SWATCH_OLD; + else if (inSwatchNew) + mTracking = TRACK_SWATCH_NEW; + //NEW_METHOD_WORK_NEEDED_HERE + //To add a new method, replicate and extend the last entry in this list + else if (mMethod == METHOD_HS_V_PALETTE) { + if (inOvalPalette) { + mTracking = TRACK_HS_PALETTE; + mFocusedControl = 0; + } + else if (inVerSlider) { + mTracking = TRACK_VER_VALUE_SLIDER; + mFocusedControl = 1; + } + } + + case MotionEvent.ACTION_MOVE: + + //NEW_METHOD_WORK_NEEDED_HERE + //To add a new method, replicate and extend the entries in this list, + //one per UI controller the new method requires. + if (mTracking == TRACK_HS_PALETTE) { + float angle = (float)java.lang.Math.atan2(circlePinnedY, circlePinnedX); + // need to turn angle [-PI ... PI] into unit [0....1] + float unit = angle / (2 * PI); + + if (unit < 0) { + unit += 1; + } + + mCoord[0] = round(FloatMath.cos(angle) * radius); + mCoord[1] = round(FloatMath.sin(angle) * radius); + int c = interpColor(mSpectrumColorsRev, unit); + float[] hsv = new float[3]; + Color.colorToHSV(c, hsv); + mHSV[0] = hsv[0]; + mHSV[1] = radius / PALETTE_RADIUS; + updateAllFromHSV(); + mSwatchNew.setColor(Color.HSVToColor(mHSV)); + setVerValSlider(); + invalidate(); + } + else if (mTracking == TRACK_VER_VALUE_SLIDER) { + if (mCoord[2] != y2) { + mCoord[2] = y2; + float value = 1.0f - (float)y2 / (float)PALETTE_DIM; + mHSV[2] = value; + updateAllFromHSV(); + mSwatchNew.setColor(Color.HSVToColor(mHSV)); + setOvalValDimmer(); + invalidate(); + } + } + + break; + + case MotionEvent.ACTION_UP: + + //NEW_METHOD_WORK_NEEDED_HERE + //To add a new method, replicate and extend the last entry in this list. + if (mTracking == TRACK_SWATCH_OLD && inSwatchOld) { + Color.colorToHSV(mOriginalColor, mHSV); + mSwatchNew.setColor(mOriginalColor); + initUI(); + invalidate(); + } + else if (mTracking == TRACK_SWATCH_NEW && inSwatchNew) { + mListener.colorChanged(mSwatchNew.getColor()); + invalidate(); + } + + mTracking = TRACKED_NONE; + break; + } + + return true; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/VolumePreference.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,68 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import android.content.Context; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.view.View; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; + +/** + * @author kenny + * + */ +public class VolumePreference extends DialogPreference implements OnSeekBarChangeListener { + /** + * @param context + * @param attrs + */ + public VolumePreference(Context context, AttributeSet attrs) { + super(context, attrs); + setupLayout(context, attrs); + } + + public VolumePreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setupLayout(context, attrs); + } + + private void setupLayout(Context context, AttributeSet attrs) { + setPersistent(true); + } + + @Override + protected View onCreateDialogView() { + SeekBar sb = new SeekBar(getContext()); + sb.setMax(100); + sb.setProgress((int)(getPersistedFloat( + PreferenceConstants.DEFAULT_BELL_VOLUME) * 100)); + sb.setPadding(10, 10, 10, 10); + sb.setOnSeekBarChangeListener(this); + return sb; + } + + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + persistFloat(progress / 100f); + } + + public void onStartTrackingTouch(SeekBar seekBar) { } + + public void onStopTrackingTouch(SeekBar seekBar) { } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/five_ten_sg/connectbot/util/XmlBuilder.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,76 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.five_ten_sg.connectbot.util; + +import ch.ethz.ssh2.crypto.Base64; + +/** + * @author Kenny Root + * + */ +public class XmlBuilder { + private StringBuilder sb; + + public XmlBuilder() { + sb = new StringBuilder(); + } + + public XmlBuilder append(String data) { + sb.append(data); + return this; + } + + public XmlBuilder append(String field, Object data) { + if (data == null) { + sb.append(String.format("<%s/>", field)); + } + else if (data instanceof String) { + String input = (String) data; + boolean binary = false; + + for (byte b : input.getBytes()) { + if (b < 0x20 || b > 0x7e) { + binary = true; + break; + } + } + + sb.append(String.format("<%s>%s</%s>", field, + binary ? new String(Base64.encode(input.getBytes())) : input, field)); + } + else if (data instanceof Integer) { + sb.append(String.format("<%s>%d</%s>", field, data, field)); + } + else if (data instanceof Long) { + sb.append(String.format("<%s>%d</%s>", field, data, field)); + } + else if (data instanceof byte[]) { + sb.append(String.format("<%s>%s</%s>", field, new String(Base64.encode((byte[]) data)), field)); + } + else if (data instanceof Boolean) { + sb.append(String.format("<%s>%s</%s>", field, data, field)); + } + + return this; + } + + @Override + public String toString() { + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/google/ase/Exec.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.ase; + +import java.io.FileDescriptor; + +/** + * Tools for executing commands. + */ +public class Exec { + /** + * @param cmd + * The command to execute + * @param arg0 + * The first argument to the command, may be null + * @param arg1 + * the second argument to the command, may be null + * @return the file descriptor of the started process. + * + */ + public static FileDescriptor createSubprocess(String cmd, String arg0, String arg1) { + return createSubprocess(cmd, arg0, arg1, null); + } + + /** + * @param cmd + * The command to execute + * @param arg0 + * The first argument to the command, may be null + * @param arg1 + * the second argument to the command, may be null + * @param processId + * A one-element array to which the process ID of the started process will be written. + * @return the file descriptor of the started process. + * + */ + public static native FileDescriptor createSubprocess(String cmd, String arg0, String arg1, + int[] processId); + + public static native void setPtyWindowSize(FileDescriptor fd, int row, int col, int xpixel, + int ypixel); + + /** + * Causes the calling thread to wait for the process associated with the receiver to finish + * executing. + * + * @return The exit value of the Process being waited on + * + */ + public static native int waitFor(int processId); + + static { + System.loadLibrary("com_google_ase_Exec"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/Adler32.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,139 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class Adler32 implements Checksum { + + // largest prime smaller than 65536 + static final private int BASE=65521; + // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 + static final private int NMAX=5552; + + private long s1=1L; + private long s2=0L; + + public void reset(long init){ + s1=init&0xffff; + s2=(init>>16)&0xffff; + } + + public void reset(){ + s1=1L; + s2=0L; + } + + public long getValue(){ + return ((s2<<16)|s1); + } + + public void update(byte[] buf, int index, int len){ + + if(len==1){ + s1+=buf[index++]&0xff; s2+=s1; + s1%=BASE; + s2%=BASE; + return; + } + + int len1 = len/NMAX; + int len2 = len%NMAX; + while(len1-->0) { + int k=NMAX; + len-=k; + while(k-->0){ + s1+=buf[index++]&0xff; s2+=s1; + } + s1%=BASE; + s2%=BASE; + } + + int k=len2; + len-=k; + while(k-->0){ + s1+=buf[index++]&0xff; s2+=s1; + } + s1%=BASE; + s2%=BASE; + } + + public Adler32 copy(){ + Adler32 foo = new Adler32(); + foo.s1 = this.s1; + foo.s2 = this.s2; + return foo; + } + + // The following logic has come from zlib.1.2. + static long combine(long adler1, long adler2, long len2){ + long BASEL = (long)BASE; + long sum1; + long sum2; + long rem; // unsigned int + + rem = len2 % BASEL; + sum1 = adler1 & 0xffffL; + sum2 = rem * sum1; + sum2 %= BASEL; // MOD(sum2); + sum1 += (adler2 & 0xffffL) + BASEL - 1; + sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem; + if (sum1 >= BASEL) sum1 -= BASEL; + if (sum1 >= BASEL) sum1 -= BASEL; + if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1); + if (sum2 >= BASEL) sum2 -= BASEL; + return sum1 | (sum2 << 16); + } + +/* + private java.util.zip.Adler32 adler=new java.util.zip.Adler32(); + public void update(byte[] buf, int index, int len){ + if(buf==null) {adler.reset();} + else{adler.update(buf, index, len);} + } + public void reset(){ + adler.reset(); + } + public void reset(long init){ + if(init==1L){ + adler.reset(); + } + else{ + System.err.println("unsupported operation"); + } + } + public long getValue(){ + return adler.getValue(); + } +*/ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/CRC32.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,179 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class CRC32 implements Checksum { + + /* + * The following logic has come from RFC1952. + */ + private int v = 0; + private static int[] crc_table = null; + static { + crc_table = new int[256]; + for (int n = 0; n < 256; n++) { + int c = n; + for (int k = 8; --k >= 0; ) { + if ((c & 1) != 0) + c = 0xedb88320 ^ (c >>> 1); + else + c = c >>> 1; + } + crc_table[n] = c; + } + } + + public void update (byte[] buf, int index, int len) { + int c = ~v; + while (--len >= 0) + c = crc_table[(c^buf[index++])&0xff]^(c >>> 8); + v = ~c; + } + + public void reset(){ + v = 0; + } + + public void reset(long vv){ + v = (int)(vv&0xffffffffL); + } + + public long getValue(){ + return (long)(v&0xffffffffL); + } + + // The following logic has come from zlib.1.2. + private static final int GF2_DIM = 32; + static long combine(long crc1, long crc2, long len2){ + long row; + long[] even = new long[GF2_DIM]; + long[] odd = new long[GF2_DIM]; + + // degenerate case (also disallow negative lengths) + if (len2 <= 0) + return crc1; + + // put operator for one zero bit in odd + odd[0] = 0xedb88320L; // CRC-32 polynomial + row = 1; + for (int n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + // put operator for two zero bits in even + gf2_matrix_square(even, odd); + + // put operator for four zero bits in odd + gf2_matrix_square(odd, even); + + // apply len2 zeros to crc1 (first square will put the operator for one + // zero byte, eight zero bits, in even) + do { + // apply zeros operator for this bit of len2 + gf2_matrix_square(even, odd); + if ((len2 & 1)!=0) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + // if no more bits set, then done + if (len2 == 0) + break; + + // another iteration of the loop with odd and even swapped + gf2_matrix_square(odd, even); + if ((len2 & 1)!=0) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + // if no more bits set, then done + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; + } + + private static long gf2_matrix_times(long[] mat, long vec){ + long sum = 0; + int index = 0; + while (vec!=0) { + if ((vec & 1)!=0) + sum ^= mat[index]; + vec >>= 1; + index++; + } + return sum; + } + + static final void gf2_matrix_square(long[] square, long[] mat) { + for (int n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); + } + + /* + private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32(); + + public void update(byte[] buf, int index, int len){ + if(buf==null) {crc32.reset();} + else{crc32.update(buf, index, len);} + } + public void reset(){ + crc32.reset(); + } + public void reset(long init){ + if(init==0L){ + crc32.reset(); + } + else{ + System.err.println("unsupported operation"); + } + } + public long getValue(){ + return crc32.getValue(); + } +*/ + public CRC32 copy(){ + CRC32 foo = new CRC32(); + foo.v = this.v; + return foo; + } + + public static int[] getCRC32Table(){ + int[] tmp = new int[crc_table.length]; + System.arraycopy(crc_table, 0, tmp, 0, tmp.length); + return tmp; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/Checksum.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,43 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +interface Checksum { + void update(byte[] buf, int index, int len); + void reset(); + void reset(long init); + long getValue(); + Checksum copy(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/Deflate.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1757 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +public +final class Deflate implements Cloneable { + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_DEFAULT_COMPRESSION=-1; + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_MEM_LEVEL=8; + + static class Config{ + int good_length; // reduce lazy search above this match length + int max_lazy; // do not perform lazy search above this match length + int nice_length; // quit search above this match length + int max_chain; + int func; + Config(int good_length, int max_lazy, + int nice_length, int max_chain, int func){ + this.good_length=good_length; + this.max_lazy=max_lazy; + this.nice_length=nice_length; + this.max_chain=max_chain; + this.func=func; + } + } + + static final private int STORED=0; + static final private int FAST=1; + static final private int SLOW=2; + static final private Config[] config_table; + static{ + config_table=new Config[10]; + // good lazy nice chain + config_table[0]=new Config(0, 0, 0, 0, STORED); + config_table[1]=new Config(4, 4, 8, 4, FAST); + config_table[2]=new Config(4, 5, 16, 8, FAST); + config_table[3]=new Config(4, 6, 32, 32, FAST); + + config_table[4]=new Config(4, 4, 16, 16, SLOW); + config_table[5]=new Config(8, 16, 32, 32, SLOW); + config_table[6]=new Config(8, 16, 128, 128, SLOW); + config_table[7]=new Config(8, 32, 128, 256, SLOW); + config_table[8]=new Config(32, 128, 258, 1024, SLOW); + config_table[9]=new Config(32, 258, 258, 4096, SLOW); + } + + static final private String[] z_errmsg = { + "need dictionary", // Z_NEED_DICT 2 + "stream end", // Z_STREAM_END 1 + "", // Z_OK 0 + "file error", // Z_ERRNO (-1) + "stream error", // Z_STREAM_ERROR (-2) + "data error", // Z_DATA_ERROR (-3) + "insufficient memory", // Z_MEM_ERROR (-4) + "buffer error", // Z_BUF_ERROR (-5) + "incompatible version",// Z_VERSION_ERROR (-6) + "" + }; + + // block not completed, need more input or more output + static final private int NeedMore=0; + + // block flush performed + static final private int BlockDone=1; + + // finish started, need only more output at next deflate + static final private int FinishStarted=2; + + // finish done, accept no more input or output + static final private int FinishDone=3; + + // preset dictionary flag in zlib header + static final private int PRESET_DICT=0x20; + + static final private int Z_FILTERED=1; + static final private int Z_HUFFMAN_ONLY=2; + static final private int Z_DEFAULT_STRATEGY=0; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + static final private int INIT_STATE=42; + static final private int BUSY_STATE=113; + static final private int FINISH_STATE=666; + + // The deflate compression method + static final private int Z_DEFLATED=8; + + static final private int STORED_BLOCK=0; + static final private int STATIC_TREES=1; + static final private int DYN_TREES=2; + + // The three kinds of block type + static final private int Z_BINARY=0; + static final private int Z_ASCII=1; + static final private int Z_UNKNOWN=2; + + static final private int Buf_size=8*2; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + static final private int REP_3_6=16; + + // repeat a zero length 3-10 times (3 bits of repeat count) + static final private int REPZ_3_10=17; + + // repeat a zero length 11-138 times (7 bits of repeat count) + static final private int REPZ_11_138=18; + + static final private int MIN_MATCH=3; + static final private int MAX_MATCH=258; + static final private int MIN_LOOKAHEAD=(MAX_MATCH+MIN_MATCH+1); + + static final private int MAX_BITS=15; + static final private int D_CODES=30; + static final private int BL_CODES=19; + static final private int LENGTH_CODES=29; + static final private int LITERALS=256; + static final private int L_CODES=(LITERALS+1+LENGTH_CODES); + static final private int HEAP_SIZE=(2*L_CODES+1); + + static final private int END_BLOCK=256; + + ZStream strm; // pointer back to this zlib stream + int status; // as the name implies + byte[] pending_buf; // output still pending + int pending_buf_size; // size of pending_buf + int pending_out; // next pending byte to output to the stream + int pending; // nb of bytes in the pending buffer + int wrap = 1; + byte data_type; // UNKNOWN, BINARY or ASCII + byte method; // STORED (for zip only) or DEFLATED + int last_flush; // value of flush param for previous deflate call + + int w_size; // LZ77 window size (32K by default) + int w_bits; // log2(w_size) (8..16) + int w_mask; // w_size - 1 + + byte[] window; + // Sliding window. Input bytes are read into the second half of the window, + // and move to the first half later to keep a dictionary of at least wSize + // bytes. With this organization, matches are limited to a distance of + // wSize-MAX_MATCH bytes, but this ensures that IO is always + // performed with a length multiple of the block size. Also, it limits + // the window size to 64K, which is quite useful on MSDOS. + // To do: use the user input buffer as sliding window. + + int window_size; + // Actual size of window: 2*wSize, except when the user input buffer + // is directly used as sliding window. + + short[] prev; + // Link to older string with same hash index. To limit the size of this + // array to 64K, this link is maintained only for the last 32K strings. + // An index in this array is thus a window index modulo 32K. + + short[] head; // Heads of the hash chains or NIL. + + int ins_h; // hash index of string to be inserted + int hash_size; // number of elements in hash table + int hash_bits; // log2(hash_size) + int hash_mask; // hash_size-1 + + // Number of bits by which ins_h must be shifted at each input + // step. It must be such that after MIN_MATCH steps, the oldest + // byte no longer takes part in the hash key, that is: + // hash_shift * MIN_MATCH >= hash_bits + int hash_shift; + + // Window position at the beginning of the current output block. Gets + // negative when the window is moved backwards. + + int block_start; + + int match_length; // length of best match + int prev_match; // previous match + int match_available; // set if previous match exists + int strstart; // start of string to insert + int match_start; // start of matching string + int lookahead; // number of valid bytes ahead in window + + // Length of the best match at previous step. Matches not greater than this + // are discarded. This is used in the lazy match evaluation. + int prev_length; + + // To speed up deflation, hash chains are never searched beyond this + // length. A higher limit improves compression ratio but degrades the speed. + int max_chain_length; + + // Attempt to find a better match only when the current match is strictly + // smaller than this value. This mechanism is used only for compression + // levels >= 4. + int max_lazy_match; + + // Insert new strings in the hash table only if the match length is not + // greater than this length. This saves time but degrades compression. + // max_insert_length is used only for compression levels <= 3. + + int level; // compression level (1..9) + int strategy; // favor or force Huffman coding + + // Use a faster search when the previous match is longer than this + int good_match; + + // Stop searching when current match exceeds this + int nice_match; + + short[] dyn_ltree; // literal and length tree + short[] dyn_dtree; // distance tree + short[] bl_tree; // Huffman tree for bit lengths + + Tree l_desc=new Tree(); // desc for literal tree + Tree d_desc=new Tree(); // desc for distance tree + Tree bl_desc=new Tree(); // desc for bit length tree + + // number of codes at each bit length for an optimal tree + short[] bl_count=new short[MAX_BITS+1]; + // working area to be used in Tree#gen_codes() + short[] next_code=new short[MAX_BITS+1]; + + // heap used to build the Huffman trees + int[] heap=new int[2*L_CODES+1]; + + int heap_len; // number of elements in the heap + int heap_max; // element of largest frequency + // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + // The same heap array is used to build all trees. + + // Depth of each subtree used as tie breaker for trees of equal frequency + byte[] depth=new byte[2*L_CODES+1]; + + byte[] l_buf; // index for literals or lengths */ + + // Size of match buffer for literals/lengths. There are 4 reasons for + // limiting lit_bufsize to 64K: + // - frequencies can be kept in 16 bit counters + // - if compression is not successful for the first block, all input + // data is still in the window so we can still emit a stored block even + // when input comes from standard input. (This can also be done for + // all blocks if lit_bufsize is not greater than 32K.) + // - if compression is not successful for a file smaller than 64K, we can + // even emit a stored file instead of a stored block (saving 5 bytes). + // This is applicable only for zip (not gzip or zlib). + // - creating new Huffman trees less frequently may not provide fast + // adaptation to changes in the input data statistics. (Take for + // example a binary file with poorly compressible code followed by + // a highly compressible string table.) Smaller buffer sizes give + // fast adaptation but have of course the overhead of transmitting + // trees more frequently. + // - I can't count above 4 + int lit_bufsize; + + int last_lit; // running index in l_buf + + // Buffer for distances. To simplify the code, d_buf and l_buf have + // the same number of elements. To use different lengths, an extra flag + // array would be necessary. + + int d_buf; // index of pendig_buf + + int opt_len; // bit length of current block with optimal trees + int static_len; // bit length of current block with static trees + int matches; // number of string matches in current block + int last_eob_len; // bit length of EOB code for last block + + // Output buffer. bits are inserted starting at the bottom (least + // significant bits). + short bi_buf; + + // Number of valid bits in bi_buf. All bits above the last valid bit + // are always zero. + int bi_valid; + + GZIPHeader gheader = null; + + Deflate(ZStream strm){ + this.strm=strm; + dyn_ltree=new short[HEAP_SIZE*2]; + dyn_dtree=new short[(2*D_CODES+1)*2]; // distance tree + bl_tree=new short[(2*BL_CODES+1)*2]; // Huffman tree for bit lengths + } + + void lm_init() { + window_size=2*w_size; + + head[hash_size-1]=0; + for(int i=0; i<hash_size-1; i++){ + head[i]=0; + } + + // Set the default configuration parameters: + max_lazy_match = Deflate.config_table[level].max_lazy; + good_match = Deflate.config_table[level].good_length; + nice_match = Deflate.config_table[level].nice_length; + max_chain_length = Deflate.config_table[level].max_chain; + + strstart = 0; + block_start = 0; + lookahead = 0; + match_length = prev_length = MIN_MATCH-1; + match_available = 0; + ins_h = 0; + } + + // Initialize the tree data structures for a new zlib stream. + void tr_init(){ + + l_desc.dyn_tree = dyn_ltree; + l_desc.stat_desc = StaticTree.static_l_desc; + + d_desc.dyn_tree = dyn_dtree; + d_desc.stat_desc = StaticTree.static_d_desc; + + bl_desc.dyn_tree = bl_tree; + bl_desc.stat_desc = StaticTree.static_bl_desc; + + bi_buf = 0; + bi_valid = 0; + last_eob_len = 8; // enough lookahead for inflate + + // Initialize the first block of the first file: + init_block(); + } + + void init_block(){ + // Initialize the trees. + for(int i = 0; i < L_CODES; i++) dyn_ltree[i*2] = 0; + for(int i= 0; i < D_CODES; i++) dyn_dtree[i*2] = 0; + for(int i= 0; i < BL_CODES; i++) bl_tree[i*2] = 0; + + dyn_ltree[END_BLOCK*2] = 1; + opt_len = static_len = 0; + last_lit = matches = 0; + } + + // Restore the heap property by moving down the tree starting at node k, + // exchanging a node with the smallest of its two sons if necessary, stopping + // when the heap property is re-established (each father smaller than its + // two sons). + void pqdownheap(short[] tree, // the tree to restore + int k // node to move down + ){ + int v = heap[k]; + int j = k << 1; // left son of k + while (j <= heap_len) { + // Set j to the smallest of the two sons: + if (j < heap_len && + smaller(tree, heap[j+1], heap[j], depth)){ + j++; + } + // Exit if v is smaller than both sons + if(smaller(tree, v, heap[j], depth)) break; + + // Exchange v with the smallest son + heap[k]=heap[j]; k = j; + // And continue down the tree, setting j to the left son of k + j <<= 1; + } + heap[k] = v; + } + + static boolean smaller(short[] tree, int n, int m, byte[] depth){ + short tn2=tree[n*2]; + short tm2=tree[m*2]; + return (tn2<tm2 || + (tn2==tm2 && depth[n] <= depth[m])); + } + + // Scan a literal or distance tree to determine the frequencies of the codes + // in the bit length tree. + void scan_tree (short[] tree,// the tree to be scanned + int max_code // and its largest code of non zero frequency + ){ + int n; // iterates over all tree elements + int prevlen = -1; // last emitted length + int curlen; // length of current code + int nextlen = tree[0*2+1]; // length of next code + int count = 0; // repeat count of the current code + int max_count = 7; // max repeat count + int min_count = 4; // min repeat count + + if (nextlen == 0){ max_count = 138; min_count = 3; } + tree[(max_code+1)*2+1] = (short)0xffff; // guard + + for(n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[(n+1)*2+1]; + if(++count < max_count && curlen == nextlen) { + continue; + } + else if(count < min_count) { + bl_tree[curlen*2] += count; + } + else if(curlen != 0) { + if(curlen != prevlen) bl_tree[curlen*2]++; + bl_tree[REP_3_6*2]++; + } + else if(count <= 10) { + bl_tree[REPZ_3_10*2]++; + } + else{ + bl_tree[REPZ_11_138*2]++; + } + count = 0; prevlen = curlen; + if(nextlen == 0) { + max_count = 138; min_count = 3; + } + else if(curlen == nextlen) { + max_count = 6; min_count = 3; + } + else{ + max_count = 7; min_count = 4; + } + } + } + + // Construct the Huffman tree for the bit lengths and return the index in + // bl_order of the last bit length code to send. + int build_bl_tree(){ + int max_blindex; // index of last bit length code of non zero freq + + // Determine the bit length frequencies for literal and distance trees + scan_tree(dyn_ltree, l_desc.max_code); + scan_tree(dyn_dtree, d_desc.max_code); + + // Build the bit length tree: + bl_desc.build_tree(this); + // opt_len now includes the length of the tree representations, except + // the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + + // Determine the number of bit length codes to send. The pkzip format + // requires that at least 4 bit length codes be sent. (appnote.txt says + // 3 but the actual value used is 4.) + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (bl_tree[Tree.bl_order[max_blindex]*2+1] != 0) break; + } + // Update opt_len to include the bit length tree and counts + opt_len += 3*(max_blindex+1) + 5+5+4; + + return max_blindex; + } + + + // Send the header for a block using dynamic Huffman trees: the counts, the + // lengths of the bit length codes, the literal tree and the distance tree. + // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + void send_all_trees(int lcodes, int dcodes, int blcodes){ + int rank; // index in bl_order + + send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt + send_bits(dcodes-1, 5); + send_bits(blcodes-4, 4); // not -3 as stated in appnote.txt + for (rank = 0; rank < blcodes; rank++) { + send_bits(bl_tree[Tree.bl_order[rank]*2+1], 3); + } + send_tree(dyn_ltree, lcodes-1); // literal tree + send_tree(dyn_dtree, dcodes-1); // distance tree + } + + // Send a literal or distance tree in compressed form, using the codes in + // bl_tree. + void send_tree (short[] tree,// the tree to be sent + int max_code // and its largest code of non zero frequency + ){ + int n; // iterates over all tree elements + int prevlen = -1; // last emitted length + int curlen; // length of current code + int nextlen = tree[0*2+1]; // length of next code + int count = 0; // repeat count of the current code + int max_count = 7; // max repeat count + int min_count = 4; // min repeat count + + if (nextlen == 0){ max_count = 138; min_count = 3; } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[(n+1)*2+1]; + if(++count < max_count && curlen == nextlen) { + continue; + } + else if(count < min_count) { + do { send_code(curlen, bl_tree); } while (--count != 0); + } + else if(curlen != 0){ + if(curlen != prevlen){ + send_code(curlen, bl_tree); count--; + } + send_code(REP_3_6, bl_tree); + send_bits(count-3, 2); + } + else if(count <= 10){ + send_code(REPZ_3_10, bl_tree); + send_bits(count-3, 3); + } + else{ + send_code(REPZ_11_138, bl_tree); + send_bits(count-11, 7); + } + count = 0; prevlen = curlen; + if(nextlen == 0){ + max_count = 138; min_count = 3; + } + else if(curlen == nextlen){ + max_count = 6; min_count = 3; + } + else{ + max_count = 7; min_count = 4; + } + } + } + + // Output a byte on the stream. + // IN assertion: there is enough room in pending_buf. + final void put_byte(byte[] p, int start, int len){ + System.arraycopy(p, start, pending_buf, pending, len); + pending+=len; + } + + final void put_byte(byte c){ + pending_buf[pending++]=c; + } + final void put_short(int w) { + put_byte((byte)(w/*&0xff*/)); + put_byte((byte)(w>>>8)); + } + final void putShortMSB(int b){ + put_byte((byte)(b>>8)); + put_byte((byte)(b/*&0xff*/)); + } + + final void send_code(int c, short[] tree){ + int c2=c*2; + send_bits((tree[c2]&0xffff), (tree[c2+1]&0xffff)); + } + + void send_bits(int value, int length){ + int len = length; + if (bi_valid > (int)Buf_size - len) { + int val = value; +// bi_buf |= (val << bi_valid); + bi_buf |= ((val << bi_valid)&0xffff); + put_short(bi_buf); + bi_buf = (short)(val >>> (Buf_size - bi_valid)); + bi_valid += len - Buf_size; + } else { +// bi_buf |= (value) << bi_valid; + bi_buf |= (((value) << bi_valid)&0xffff); + bi_valid += len; + } + } + + // Send one empty static block to give enough lookahead for inflate. + // This takes 10 bits, of which 7 may remain in the bit buffer. + // The current inflate code requires 9 bits of lookahead. If the + // last two codes for the previous block (real code plus EOB) were coded + // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + // the last real code. In this case we send two empty static blocks instead + // of one. (There are no problems if the previous block is stored or fixed.) + // To simplify the code, we assume the worst case of last real code encoded + // on one bit only. + void _tr_align(){ + send_bits(STATIC_TREES<<1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + + bi_flush(); + + // Of the 10 bits for the empty block, we have already sent + // (10 - bi_valid) bits. The lookahead for the last real code (before + // the EOB of the previous block) was thus at least one plus the length + // of the EOB plus what we have just sent of the empty static block. + if (1 + last_eob_len + 10 - bi_valid < 9) { + send_bits(STATIC_TREES<<1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + bi_flush(); + } + last_eob_len = 7; + } + + + // Save the match info and tally the frequency counts. Return true if + // the current block must be flushed. + boolean _tr_tally (int dist, // distance of matched string + int lc // match length-MIN_MATCH or unmatched char (if dist==0) + ){ + + pending_buf[d_buf+last_lit*2] = (byte)(dist>>>8); + pending_buf[d_buf+last_lit*2+1] = (byte)dist; + + l_buf[last_lit] = (byte)lc; last_lit++; + + if (dist == 0) { + // lc is the unmatched char + dyn_ltree[lc*2]++; + } + else { + matches++; + // Here, lc is the match length - MIN_MATCH + dist--; // dist = match distance - 1 + dyn_ltree[(Tree._length_code[lc]+LITERALS+1)*2]++; + dyn_dtree[Tree.d_code(dist)*2]++; + } + + if ((last_lit & 0x1fff) == 0 && level > 2) { + // Compute an upper bound for the compressed length + int out_length = last_lit*8; + int in_length = strstart - block_start; + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (int)dyn_dtree[dcode*2] * + (5L+Tree.extra_dbits[dcode]); + } + out_length >>>= 3; + if ((matches < (last_lit/2)) && out_length < in_length/2) return true; + } + + return (last_lit == lit_bufsize-1); + // We avoid equality with lit_bufsize because of wraparound at 64K + // on 16 bit machines and because stored blocks are restricted to + // 64K-1 bytes. + } + + // Send the block data compressed using the given Huffman trees + void compress_block(short[] ltree, short[] dtree){ + int dist; // distance of matched string + int lc; // match length or unmatched char (if dist == 0) + int lx = 0; // running index in l_buf + int code; // the code to send + int extra; // number of extra bits to send + + if (last_lit != 0){ + do{ + dist=((pending_buf[d_buf+lx*2]<<8)&0xff00)| + (pending_buf[d_buf+lx*2+1]&0xff); + lc=(l_buf[lx])&0xff; lx++; + + if(dist == 0){ + send_code(lc, ltree); // send a literal byte + } + else{ + // Here, lc is the match length - MIN_MATCH + code = Tree._length_code[lc]; + + send_code(code+LITERALS+1, ltree); // send the length code + extra = Tree.extra_lbits[code]; + if(extra != 0){ + lc -= Tree.base_length[code]; + send_bits(lc, extra); // send the extra length bits + } + dist--; // dist is now the match distance - 1 + code = Tree.d_code(dist); + + send_code(code, dtree); // send the distance code + extra = Tree.extra_dbits[code]; + if (extra != 0) { + dist -= Tree.base_dist[code]; + send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + + // Check that the overlay between pending_buf and d_buf+l_buf is ok: + } + while (lx < last_lit); + } + + send_code(END_BLOCK, ltree); + last_eob_len = ltree[END_BLOCK*2+1]; + } + + // Set the data type to ASCII or BINARY, using a crude approximation: + // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + // IN assertion: the fields freq of dyn_ltree are set and the total of all + // frequencies does not exceed 64K (to fit in an int on 16 bit machines). + void set_data_type(){ + int n = 0; + int ascii_freq = 0; + int bin_freq = 0; + while(n<7){ bin_freq += dyn_ltree[n*2]; n++;} + while(n<128){ ascii_freq += dyn_ltree[n*2]; n++;} + while(n<LITERALS){ bin_freq += dyn_ltree[n*2]; n++;} + data_type=(byte)(bin_freq > (ascii_freq >>> 2) ? Z_BINARY : Z_ASCII); + } + + // Flush the bit buffer, keeping at most 7 bits in it. + void bi_flush(){ + if (bi_valid == 16) { + put_short(bi_buf); + bi_buf=0; + bi_valid=0; + } + else if (bi_valid >= 8) { + put_byte((byte)bi_buf); + bi_buf>>>=8; + bi_valid-=8; + } + } + + // Flush the bit buffer and align the output on a byte boundary + void bi_windup(){ + if (bi_valid > 8) { + put_short(bi_buf); + } else if (bi_valid > 0) { + put_byte((byte)bi_buf); + } + bi_buf = 0; + bi_valid = 0; + } + + // Copy a stored block, storing first the length and its + // one's complement if requested. + void copy_block(int buf, // the input data + int len, // its length + boolean header // true if block header must be written + ){ + int index=0; + bi_windup(); // align on byte boundary + last_eob_len = 8; // enough lookahead for inflate + + if (header) { + put_short((short)len); + put_short((short)~len); + } + + // while(len--!=0) { + // put_byte(window[buf+index]); + // index++; + // } + put_byte(window, buf, len); + } + + void flush_block_only(boolean eof){ + _tr_flush_block(block_start>=0 ? block_start : -1, + strstart-block_start, + eof); + block_start=strstart; + strm.flush_pending(); + } + + // Copy without compression as much as possible from the input stream, return + // the current block state. + // This function does not insert new strings in the dictionary since + // uncompressible data is probably not useful. This function is used + // only for the level=0 compression option. + // NOTE: this function should be optimized to avoid extra copying from + // window to pending_buf. + int deflate_stored(int flush){ + // Stored blocks are limited to 0xffff bytes, pending_buf is limited + // to pending_buf_size, and each stored block has a 5 byte header: + + int max_block_size = 0xffff; + int max_start; + + if(max_block_size > pending_buf_size - 5) { + max_block_size = pending_buf_size - 5; + } + + // Copy as much as possible from input to output: + while(true){ + // Fill the window as much as possible: + if(lookahead<=1){ + fill_window(); + if(lookahead==0 && flush==Z_NO_FLUSH) return NeedMore; + if(lookahead==0) break; // flush the current block + } + + strstart+=lookahead; + lookahead=0; + + // Emit a stored block if pending_buf will be full: + max_start=block_start+max_block_size; + if(strstart==0|| strstart>=max_start) { + // strstart == 0 is possible when wraparound on 16-bit machine + lookahead = (int)(strstart-max_start); + strstart = (int)max_start; + + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + + } + + // Flush if we may have to slide, otherwise block_start may become + // negative and the data will be gone: + if(strstart-block_start >= w_size-MIN_LOOKAHEAD) { + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + if(strm.avail_out==0) + return (flush == Z_FINISH) ? FinishStarted : NeedMore; + + return flush == Z_FINISH ? FinishDone : BlockDone; + } + + // Send a stored block + void _tr_stored_block(int buf, // input block + int stored_len, // length of input block + boolean eof // true if this is the last block for a file + ){ + send_bits((STORED_BLOCK<<1)+(eof?1:0), 3); // send block type + copy_block(buf, stored_len, true); // with header + } + + // Determine the best encoding for the current block: dynamic trees, static + // trees or store, and output the encoded block to the zip file. + void _tr_flush_block(int buf, // input block, or NULL if too old + int stored_len, // length of input block + boolean eof // true if this is the last block for a file + ) { + int opt_lenb, static_lenb;// opt_len and static_len in bytes + int max_blindex = 0; // index of last bit length code of non zero freq + + // Build the Huffman trees unless a stored block is forced + if(level > 0) { + // Check if the file is ascii or binary + if(data_type == Z_UNKNOWN) set_data_type(); + + // Construct the literal and distance trees + l_desc.build_tree(this); + + d_desc.build_tree(this); + + // At this point, opt_len and static_len are the total bit lengths of + // the compressed block data, excluding the tree representations. + + // Build the bit length tree for the above two trees, and get the index + // in bl_order of the last bit length code to send. + max_blindex=build_bl_tree(); + + // Determine the best encoding. Compute first the block length in bytes + opt_lenb=(opt_len+3+7)>>>3; + static_lenb=(static_len+3+7)>>>3; + + if(static_lenb<=opt_lenb) opt_lenb=static_lenb; + } + else { + opt_lenb=static_lenb=stored_len+5; // force a stored block + } + + if(stored_len+4<=opt_lenb && buf != -1){ + // 4: two words for the lengths + // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + // Otherwise we can't have processed more than WSIZE input bytes since + // the last block flush, because compression would have been + // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + // transform a block into a stored block. + _tr_stored_block(buf, stored_len, eof); + } + else if(static_lenb == opt_lenb){ + send_bits((STATIC_TREES<<1)+(eof?1:0), 3); + compress_block(StaticTree.static_ltree, StaticTree.static_dtree); + } + else{ + send_bits((DYN_TREES<<1)+(eof?1:0), 3); + send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); + compress_block(dyn_ltree, dyn_dtree); + } + + // The above check is made mod 2^32, for files larger than 512 MB + // and uLong implemented on 32 bits. + + init_block(); + + if(eof){ + bi_windup(); + } + } + + // Fill the window when the lookahead becomes insufficient. + // Updates strstart and lookahead. + // + // IN assertion: lookahead < MIN_LOOKAHEAD + // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + // At least one byte has been read, or avail_in == 0; reads are + // performed for at least two bytes (required for the zip translate_eol + // option -- not supported here). + void fill_window(){ + int n, m; + int p; + int more; // Amount of free space at the end of the window. + + do{ + more = (window_size-lookahead-strstart); + + // Deal with !@#$% 64K limit: + if(more==0 && strstart==0 && lookahead==0){ + more = w_size; + } + else if(more==-1) { + // Very unlikely, but possible on 16 bit machine if strstart == 0 + // and lookahead == 1 (input done one byte at time) + more--; + + // If the window is almost full and there is insufficient lookahead, + // move the upper half to the lower one to make room in the upper half. + } + else if(strstart >= w_size+ w_size-MIN_LOOKAHEAD) { + System.arraycopy(window, w_size, window, 0, w_size); + match_start-=w_size; + strstart-=w_size; // we now have strstart >= MAX_DIST + block_start-=w_size; + + // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). We slide even when level == 0 + // to keep the hash table consistent if we switch back to level > 0 + // later. (Using level 0 permanently is not an optimal usage of + // zlib, so we don't care about this pathological case.) + + n = hash_size; + p=n; + do { + m = (head[--p]&0xffff); + head[p]=(m>=w_size ? (short)(m-w_size) : 0); + } + while (--n != 0); + + n = w_size; + p = n; + do { + m = (prev[--p]&0xffff); + prev[p] = (m >= w_size ? (short)(m-w_size) : 0); + // If n is not on any hash chain, prev[n] is garbage but + // its value will never be used. + } + while (--n!=0); + more += w_size; + } + + if (strm.avail_in == 0) return; + + // If there was no sliding: + // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + // more == window_size - lookahead - strstart + // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + // => more >= window_size - 2*WSIZE + 2 + // In the BIG_MEM or MMAP case (not yet supported), + // window_size == input_size + MIN_LOOKAHEAD && + // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + // Otherwise, window_size == 2*WSIZE so more >= 2. + // If there was sliding, more >= WSIZE. So in all cases, more >= 2. + + n = strm.read_buf(window, strstart + lookahead, more); + lookahead += n; + + // Initialize the hash value now that we have some input: + if(lookahead >= MIN_MATCH) { + ins_h = window[strstart]&0xff; + ins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask; + } + // If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + // but this is not important since only literal bytes will be emitted. + } + while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0); + } + + // Compress as much as possible from the input stream, return the current + // block state. + // This function does not perform lazy evaluation of matches and inserts + // new strings in the dictionary only for unmatched strings or for short + // matches. It is used only for the fast compression options. + int deflate_fast(int flush){ +// short hash_head = 0; // head of the hash chain + int hash_head = 0; // head of the hash chain + boolean bflush; // set if current block must be flushed + + while(true){ + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + if(lookahead < MIN_LOOKAHEAD){ + fill_window(); + if(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH){ + return NeedMore; + } + if(lookahead == 0) break; // flush the current block + } + + // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + if(lookahead >= MIN_MATCH){ + ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask; + +// prev[strstart&w_mask]=hash_head=head[ins_h]; + hash_head=(head[ins_h]&0xffff); + prev[strstart&w_mask]=head[ins_h]; + head[ins_h]=(short)strstart; + } + + // Find the longest match, discarding those <= prev_length. + // At this point we have always match_length < MIN_MATCH + + if(hash_head!=0L && + ((strstart-hash_head)&0xffff) <= w_size-MIN_LOOKAHEAD + ){ + // To simplify the code, we prevent matches with the string + // of window index 0 (in particular we have to avoid a match + // of the string with itself at the start of the input file). + if(strategy != Z_HUFFMAN_ONLY){ + match_length=longest_match (hash_head); + } + // longest_match() sets match_start + } + if(match_length>=MIN_MATCH){ + // check_match(strstart, match_start, match_length); + + bflush=_tr_tally(strstart-match_start, match_length-MIN_MATCH); + + lookahead -= match_length; + + // Insert new strings in the hash table only if the match length + // is not too large. This saves time but degrades compression. + if(match_length <= max_lazy_match && + lookahead >= MIN_MATCH) { + match_length--; // string at strstart already in hash table + do{ + strstart++; + + ins_h=((ins_h<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask; +// prev[strstart&w_mask]=hash_head=head[ins_h]; + hash_head=(head[ins_h]&0xffff); + prev[strstart&w_mask]=head[ins_h]; + head[ins_h]=(short)strstart; + + // strstart never exceeds WSIZE-MAX_MATCH, so there are + // always MIN_MATCH bytes ahead. + } + while (--match_length != 0); + strstart++; + } + else{ + strstart += match_length; + match_length = 0; + ins_h = window[strstart]&0xff; + + ins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask; + // If lookahead < MIN_MATCH, ins_h is garbage, but it does not + // matter since it will be recomputed at next deflate call. + } + } + else { + // No match, output a literal byte + + bflush=_tr_tally(0, window[strstart]&0xff); + lookahead--; + strstart++; + } + if (bflush){ + + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + if(strm.avail_out==0){ + if(flush == Z_FINISH) return FinishStarted; + else return NeedMore; + } + return flush==Z_FINISH ? FinishDone : BlockDone; + } + + // Same as above, but achieves better compression. We use a lazy + // evaluation for matches: a match is finally adopted only if there is + // no better match at the next window position. + int deflate_slow(int flush){ +// short hash_head = 0; // head of hash chain + int hash_head = 0; // head of hash chain + boolean bflush; // set if current block must be flushed + + // Process the input block. + while(true){ + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + + if (lookahead < MIN_LOOKAHEAD) { + fill_window(); + if(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return NeedMore; + } + if(lookahead == 0) break; // flush the current block + } + + // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + + if(lookahead >= MIN_MATCH) { + ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff)) & hash_mask; +// prev[strstart&w_mask]=hash_head=head[ins_h]; + hash_head=(head[ins_h]&0xffff); + prev[strstart&w_mask]=head[ins_h]; + head[ins_h]=(short)strstart; + } + + // Find the longest match, discarding those <= prev_length. + prev_length = match_length; prev_match = match_start; + match_length = MIN_MATCH-1; + + if (hash_head != 0 && prev_length < max_lazy_match && + ((strstart-hash_head)&0xffff) <= w_size-MIN_LOOKAHEAD + ){ + // To simplify the code, we prevent matches with the string + // of window index 0 (in particular we have to avoid a match + // of the string with itself at the start of the input file). + + if(strategy != Z_HUFFMAN_ONLY) { + match_length = longest_match(hash_head); + } + // longest_match() sets match_start + + if (match_length <= 5 && (strategy == Z_FILTERED || + (match_length == MIN_MATCH && + strstart - match_start > 4096))) { + + // If prev_match is also MIN_MATCH, match_start is garbage + // but we will ignore the current match anyway. + match_length = MIN_MATCH-1; + } + } + + // If there was a match at the previous step and the current + // match is not better, output the previous match: + if(prev_length >= MIN_MATCH && match_length <= prev_length) { + int max_insert = strstart + lookahead - MIN_MATCH; + // Do not insert strings in hash table beyond this. + + // check_match(strstart-1, prev_match, prev_length); + + bflush=_tr_tally(strstart-1-prev_match, prev_length - MIN_MATCH); + + // Insert in hash table all strings up to the end of the match. + // strstart-1 and strstart are already inserted. If there is not + // enough lookahead, the last two strings are not inserted in + // the hash table. + lookahead -= prev_length-1; + prev_length -= 2; + do{ + if(++strstart <= max_insert) { + ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask; + //prev[strstart&w_mask]=hash_head=head[ins_h]; + hash_head=(head[ins_h]&0xffff); + prev[strstart&w_mask]=head[ins_h]; + head[ins_h]=(short)strstart; + } + } + while(--prev_length != 0); + match_available = 0; + match_length = MIN_MATCH-1; + strstart++; + + if (bflush){ + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + } + } else if (match_available!=0) { + + // If there was no match at the previous position, output a + // single literal. If there was a match but the current match + // is longer, truncate the previous match to a single literal. + + bflush=_tr_tally(0, window[strstart-1]&0xff); + + if (bflush) { + flush_block_only(false); + } + strstart++; + lookahead--; + if(strm.avail_out == 0) return NeedMore; + } else { + // There is no previous match to compare with, wait for + // the next step to decide. + + match_available = 1; + strstart++; + lookahead--; + } + } + + if(match_available!=0) { + bflush=_tr_tally(0, window[strstart-1]&0xff); + match_available = 0; + } + flush_block_only(flush == Z_FINISH); + + if(strm.avail_out==0){ + if(flush == Z_FINISH) return FinishStarted; + else return NeedMore; + } + + return flush == Z_FINISH ? FinishDone : BlockDone; + } + + int longest_match(int cur_match){ + int chain_length = max_chain_length; // max hash chain length + int scan = strstart; // current string + int match; // matched string + int len; // length of current match + int best_len = prev_length; // best match length so far + int limit = strstart>(w_size-MIN_LOOKAHEAD) ? + strstart-(w_size-MIN_LOOKAHEAD) : 0; + int nice_match=this.nice_match; + + // Stop when cur_match becomes <= limit. To simplify the code, + // we prevent matches with the string of window index 0. + + int wmask = w_mask; + + int strend = strstart + MAX_MATCH; + byte scan_end1 = window[scan+best_len-1]; + byte scan_end = window[scan+best_len]; + + // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + // It is easy to get rid of this optimization if necessary. + + // Do not waste too much time if we already have a good match: + if (prev_length >= good_match) { + chain_length >>= 2; + } + + // Do not look for matches beyond the end of the input. This is necessary + // to make deflate deterministic. + if (nice_match > lookahead) nice_match = lookahead; + + do { + match = cur_match; + + // Skip to next match if the match length cannot increase + // or if the match length is less than 2: + if (window[match+best_len] != scan_end || + window[match+best_len-1] != scan_end1 || + window[match] != window[scan] || + window[++match] != window[scan+1]) continue; + + // The check at best_len-1 can be removed because it will be made + // again later. (This heuristic is not always a win.) + // It is not necessary to compare scan[2] and match[2] since they + // are always equal when the other bytes match, given that + // the hash keys are equal and that HASH_BITS >= 8. + scan += 2; match++; + + // We check for insufficient lookahead only every 8th comparison; + // the 256th check will be made at strstart+258. + do { + } while (window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + scan < strend); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + + if(len>best_len) { + match_start = cur_match; + best_len = len; + if (len >= nice_match) break; + scan_end1 = window[scan+best_len-1]; + scan_end = window[scan+best_len]; + } + + } while ((cur_match = (prev[cur_match & wmask]&0xffff)) > limit + && --chain_length != 0); + + if (best_len <= lookahead) return best_len; + return lookahead; + } + + int deflateInit(int level, int bits, int memlevel){ + return deflateInit(level, Z_DEFLATED, bits, memlevel, + Z_DEFAULT_STRATEGY); + } + + int deflateInit(int level, int bits){ + return deflateInit(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY); + } + int deflateInit(int level){ + return deflateInit(level, MAX_WBITS); + } + private int deflateInit(int level, int method, int windowBits, + int memLevel, int strategy){ + int wrap = 1; + // byte[] my_version=ZLIB_VERSION; + + // + // if (version == null || version[0] != my_version[0] + // || stream_size != sizeof(z_stream)) { + // return Z_VERSION_ERROR; + // } + + strm.msg = null; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; + + if (windowBits < 0) { // undocumented feature: suppress zlib header + wrap = 0; + windowBits = -windowBits; + } + else if(windowBits > 15){ + wrap = 2; + windowBits -= 16; + strm.adler=new CRC32(); + } + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || + method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + strm.dstate = (Deflate)this; + + this.wrap = wrap; + w_bits = windowBits; + w_size = 1 << w_bits; + w_mask = w_size - 1; + + hash_bits = memLevel + 7; + hash_size = 1 << hash_bits; + hash_mask = hash_size - 1; + hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH); + + window = new byte[w_size*2]; + prev = new short[w_size]; + head = new short[hash_size]; + + lit_bufsize = 1 << (memLevel + 6); // 16K elements by default + + // We overlay pending_buf and d_buf+l_buf. This works since the average + // output size for (length,distance) codes is <= 24 bits. + pending_buf = new byte[lit_bufsize*3]; + pending_buf_size = lit_bufsize*3; + + d_buf = lit_bufsize; + l_buf = new byte[lit_bufsize]; + + this.level = level; + + this.strategy = strategy; + this.method = (byte)method; + + return deflateReset(); + } + + int deflateReset(){ + strm.total_in = strm.total_out = 0; + strm.msg = null; // + strm.data_type = Z_UNKNOWN; + + pending = 0; + pending_out = 0; + + if(wrap < 0){ + wrap = -wrap; + } + status = (wrap==0) ? BUSY_STATE : INIT_STATE; + strm.adler.reset(); + + last_flush = Z_NO_FLUSH; + + tr_init(); + lm_init(); + return Z_OK; + } + + int deflateEnd(){ + if(status!=INIT_STATE && status!=BUSY_STATE && status!=FINISH_STATE){ + return Z_STREAM_ERROR; + } + // Deallocate in reverse order of allocations: + pending_buf=null; + l_buf=null; + head=null; + prev=null; + window=null; + // free + // dstate=null; + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; + } + + int deflateParams(int _level, int _strategy){ + int err=Z_OK; + + if(_level == Z_DEFAULT_COMPRESSION){ + _level = 6; + } + if(_level < 0 || _level > 9 || + _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + if(config_table[level].func!=config_table[_level].func && + strm.total_in != 0) { + // Flush the last buffer: + err = strm.deflate(Z_PARTIAL_FLUSH); + } + + if(level != _level) { + level = _level; + max_lazy_match = config_table[level].max_lazy; + good_match = config_table[level].good_length; + nice_match = config_table[level].nice_length; + max_chain_length = config_table[level].max_chain; + } + strategy = _strategy; + return err; + } + + int deflateSetDictionary (byte[] dictionary, int dictLength){ + int length = dictLength; + int index=0; + + if(dictionary == null || status != INIT_STATE) + return Z_STREAM_ERROR; + + strm.adler.update(dictionary, 0, dictLength); + + if(length < MIN_MATCH) return Z_OK; + if(length > w_size-MIN_LOOKAHEAD){ + length = w_size-MIN_LOOKAHEAD; + index=dictLength-length; // use the tail of the dictionary + } + System.arraycopy(dictionary, index, window, 0, length); + strstart = length; + block_start = length; + + // Insert all strings in the hash table (except for the last two bytes). + // s->lookahead stays null, so s->ins_h will be recomputed at the next + // call of fill_window. + + ins_h = window[0]&0xff; + ins_h=(((ins_h)<<hash_shift)^(window[1]&0xff))&hash_mask; + + for(int n=0; n<=length-MIN_MATCH; n++){ + ins_h=(((ins_h)<<hash_shift)^(window[(n)+(MIN_MATCH-1)]&0xff))&hash_mask; + prev[n&w_mask]=head[ins_h]; + head[ins_h]=(short)n; + } + return Z_OK; + } + + int deflate(int flush){ + int old_flush; + + if(flush>Z_FINISH || flush<0){ + return Z_STREAM_ERROR; + } + + if(strm.next_out == null || + (strm.next_in == null && strm.avail_in != 0) || + (status == FINISH_STATE && flush != Z_FINISH)) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)]; + return Z_STREAM_ERROR; + } + if(strm.avail_out == 0){ + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + old_flush = last_flush; + last_flush = flush; + + // Write the zlib header + if(status == INIT_STATE) { + if(wrap == 2){ + getGZIPHeader().put(this); + status=BUSY_STATE; + strm.adler.reset(); + } + else{ + int header = (Z_DEFLATED+((w_bits-8)<<4))<<8; + int level_flags=((level-1)&0xff)>>1; + + if(level_flags>3) level_flags=3; + header |= (level_flags<<6); + if(strstart!=0) header |= PRESET_DICT; + header+=31-(header % 31); + + status=BUSY_STATE; + putShortMSB(header); + + + // Save the adler32 of the preset dictionary: + if(strstart!=0){ + long adler=strm.adler.getValue(); + putShortMSB((int)(adler>>>16)); + putShortMSB((int)(adler&0xffff)); + } + strm.adler.reset(); + } + } + + // Flush as much pending output as possible + if(pending != 0) { + strm.flush_pending(); + if(strm.avail_out == 0) { + // Since avail_out is 0, deflate will be called again with + // more output space, but possibly with both pending and + // avail_in equal to zero. There won't be anything to do, + // but this is not an error situation so make sure we + // return OK instead of BUF_ERROR at next call of deflate: + last_flush = -1; + return Z_OK; + } + + // Make sure there is something to do and avoid duplicate consecutive + // flushes. For repeated and useless calls with Z_FINISH, we keep + // returning Z_STREAM_END instead of Z_BUFF_ERROR. + } + else if(strm.avail_in==0 && flush <= old_flush && + flush != Z_FINISH) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // User must not provide more input after the first FINISH: + if(status == FINISH_STATE && strm.avail_in != 0) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // Start a new block or continue the current one. + if(strm.avail_in!=0 || lookahead!=0 || + (flush != Z_NO_FLUSH && status != FINISH_STATE)) { + int bstate=-1; + switch(config_table[level].func){ + case STORED: + bstate = deflate_stored(flush); + break; + case FAST: + bstate = deflate_fast(flush); + break; + case SLOW: + bstate = deflate_slow(flush); + break; + default: + } + + if (bstate==FinishStarted || bstate==FinishDone) { + status = FINISH_STATE; + } + if (bstate==NeedMore || bstate==FinishStarted) { + if(strm.avail_out == 0) { + last_flush = -1; // avoid BUF_ERROR next call, see above + } + return Z_OK; + // If flush != Z_NO_FLUSH && avail_out == 0, the next call + // of deflate should use the same flush parameter to make sure + // that the flush is complete. So we don't have to output an + // empty block here, this will be done at next call. This also + // ensures that for a very small output buffer, we emit at most + // one empty block. + } + + if (bstate==BlockDone) { + if(flush == Z_PARTIAL_FLUSH) { + _tr_align(); + } + else { // FULL_FLUSH or SYNC_FLUSH + _tr_stored_block(0, 0, false); + // For a full flush, this empty block will be recognized + // as a special marker by inflate_sync(). + if(flush == Z_FULL_FLUSH) { + //state.head[s.hash_size-1]=0; + for(int i=0; i<hash_size/*-1*/; i++) // forget history + head[i]=0; + } + } + strm.flush_pending(); + if(strm.avail_out == 0) { + last_flush = -1; // avoid BUF_ERROR at next call, see above + return Z_OK; + } + } + } + + if(flush!=Z_FINISH) return Z_OK; + if(wrap<=0) return Z_STREAM_END; + + if(wrap==2){ + long adler=strm.adler.getValue(); + put_byte((byte)(adler&0xff)); + put_byte((byte)((adler>>8)&0xff)); + put_byte((byte)((adler>>16)&0xff)); + put_byte((byte)((adler>>24)&0xff)); + put_byte((byte)(strm.total_in&0xff)); + put_byte((byte)((strm.total_in>>8)&0xff)); + put_byte((byte)((strm.total_in>>16)&0xff)); + put_byte((byte)((strm.total_in>>24)&0xff)); + + getGZIPHeader().setCRC(adler); + } + else{ + // Write the zlib trailer (adler32) + long adler=strm.adler.getValue(); + putShortMSB((int)(adler>>>16)); + putShortMSB((int)(adler&0xffff)); + } + + strm.flush_pending(); + + // If avail_out is zero, the application will call deflate again + // to flush the rest. + + if(wrap > 0) wrap = -wrap; // write the trailer only once! + return pending != 0 ? Z_OK : Z_STREAM_END; + } + + static int deflateCopy(ZStream dest, ZStream src){ + + if(src.dstate == null){ + return Z_STREAM_ERROR; + } + + if(src.next_in!=null){ + dest.next_in = new byte[src.next_in.length]; + System.arraycopy(src.next_in, 0, dest.next_in, 0, src.next_in.length); + } + dest.next_in_index = src.next_in_index; + dest.avail_in = src.avail_in; + dest.total_in = src.total_in; + + if(src.next_out!=null){ + dest.next_out = new byte[src.next_out.length]; + System.arraycopy(src.next_out, 0, dest.next_out ,0 , src.next_out.length); + } + + dest.next_out_index = src.next_out_index; + dest.avail_out = src.avail_out; + dest.total_out = src.total_out; + + dest.msg = src.msg; + dest.data_type = src.data_type; + dest.adler = src.adler.copy(); + + try{ + dest.dstate = (Deflate)src.dstate.clone(); + dest.dstate.strm = dest; + } + catch(CloneNotSupportedException e){ + // + } + return Z_OK; + } + + public Object clone() throws CloneNotSupportedException { + Deflate dest = (Deflate)super.clone(); + + dest.pending_buf = dup(dest.pending_buf); + dest.d_buf = dest.d_buf; + dest.l_buf = dup(dest.l_buf); + dest.window = dup(dest.window); + + dest.prev = dup(dest.prev); + dest.head = dup(dest.head); + dest.dyn_ltree = dup(dest.dyn_ltree); + dest.dyn_dtree = dup(dest.dyn_dtree); + dest.bl_tree = dup(dest.bl_tree); + + dest.bl_count = dup(dest.bl_count); + dest.next_code = dup(dest.next_code); + dest.heap = dup(dest.heap); + dest.depth = dup(dest.depth); + + dest.l_desc.dyn_tree = dest.dyn_ltree; + dest.d_desc.dyn_tree = dest.dyn_dtree; + dest.bl_desc.dyn_tree = dest.bl_tree; + + /* + dest.l_desc.stat_desc = StaticTree.static_l_desc; + dest.d_desc.stat_desc = StaticTree.static_d_desc; + dest.bl_desc.stat_desc = StaticTree.static_bl_desc; + */ + + if(dest.gheader!=null){ + dest.gheader = (GZIPHeader)dest.gheader.clone(); + } + + return dest; + } + + private byte[] dup(byte[] buf){ + byte[] foo = new byte[buf.length]; + System.arraycopy(buf, 0, foo, 0, foo.length); + return foo; + } + private short[] dup(short[] buf){ + short[] foo = new short[buf.length]; + System.arraycopy(buf, 0, foo, 0, foo.length); + return foo; + } + private int[] dup(int[] buf){ + int[] foo = new int[buf.length]; + System.arraycopy(buf, 0, foo, 0, foo.length); + return foo; + } + + synchronized GZIPHeader getGZIPHeader(){ + if(gheader==null){ + gheader = new GZIPHeader(); + } + return gheader; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/Deflater.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,171 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class Deflater extends ZStream{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_WBITS=MAX_WBITS; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + private boolean finished = false; + + public Deflater(){ + super(); + } + + public Deflater(int level) throws GZIPException { + this(level, MAX_WBITS); + } + + public Deflater(int level, boolean nowrap) throws GZIPException { + this(level, MAX_WBITS, nowrap); + } + + public Deflater(int level, int bits) throws GZIPException { + this(level, bits, false); + } + + public Deflater(int level, int bits, boolean nowrap) throws GZIPException { + super(); + int ret = init(level, bits, nowrap); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public Deflater(int level, int bits, int memlevel, JZlib.WrapperType wrapperType) throws GZIPException { + super(); + int ret = init(level, bits, memlevel, wrapperType); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public Deflater(int level, int bits, int memlevel) throws GZIPException { + super(); + int ret = init(level, bits, memlevel); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public int init(int level){ + return init(level, MAX_WBITS); + } + public int init(int level, boolean nowrap){ + return init(level, MAX_WBITS, nowrap); + } + public int init(int level, int bits){ + return init(level, bits, false); + } + public int init(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){ + if(bits < 9 || bits > 15){ + return Z_STREAM_ERROR; + } + if(wrapperType == JZlib.W_NONE) { + bits *= -1; + } + else if(wrapperType == JZlib.W_GZIP) { + bits += 16; + } + else if(wrapperType == JZlib.W_ANY) { + return Z_STREAM_ERROR; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return init(level, bits, memlevel); + } + public int init(int level, int bits, int memlevel){ + finished = false; + dstate=new Deflate(this); + return dstate.deflateInit(level, bits, memlevel); + } + public int init(int level, int bits, boolean nowrap){ + finished = false; + dstate=new Deflate(this); + return dstate.deflateInit(level, nowrap?-bits:bits); + } + + public int deflate(int flush){ + if(dstate==null){ + return Z_STREAM_ERROR; + } + int ret = dstate.deflate(flush); + if(ret == Z_STREAM_END) + finished = true; + return ret; + } + public int end(){ + finished = true; + if(dstate==null) return Z_STREAM_ERROR; + int ret=dstate.deflateEnd(); + dstate=null; + free(); + return ret; + } + public int params(int level, int strategy){ + if(dstate==null) return Z_STREAM_ERROR; + return dstate.deflateParams(level, strategy); + } + public int setDictionary (byte[] dictionary, int dictLength){ + if(dstate == null) + return Z_STREAM_ERROR; + return dstate.deflateSetDictionary(dictionary, dictLength); + } + + public boolean finished(){ + return finished; + } + + public int copy(Deflater src){ + this.finished = src.finished; + return Deflate.deflateCopy(this, src); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/DeflaterOutputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,181 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +public class DeflaterOutputStream extends FilterOutputStream { + + protected final Deflater deflater; + + protected byte[] buffer; + + private boolean closed = false; + + private boolean syncFlush = false; + + private final byte[] buf1 = new byte[1]; + + protected boolean mydeflater = false; + + private boolean close_out = true; + + protected static final int DEFAULT_BUFSIZE = 512; + + public DeflaterOutputStream(OutputStream out) throws IOException { + this(out, + new Deflater(JZlib.Z_DEFAULT_COMPRESSION), + DEFAULT_BUFSIZE, true); + mydeflater = true; + } + + public DeflaterOutputStream(OutputStream out, Deflater def) throws IOException { + this(out, def, DEFAULT_BUFSIZE, true); + } + + public DeflaterOutputStream(OutputStream out, + Deflater deflater, + int size) throws IOException { + this(out, deflater, size, true); + } + public DeflaterOutputStream(OutputStream out, + Deflater deflater, + int size, + boolean close_out) throws IOException { + super(out); + if (out == null || deflater == null) { + throw new NullPointerException(); + } + else if (size <= 0) { + throw new IllegalArgumentException("buffer size must be greater than 0"); + } + this.deflater = deflater; + buffer = new byte[size]; + this.close_out = close_out; + } + + public void write(int b) throws IOException { + buf1[0] = (byte)(b & 0xff); + write(buf1, 0, 1); + } + + public void write(byte[] b, int off, int len) throws IOException { + if (deflater.finished()) { + throw new IOException("finished"); + } + else if (off<0 | len<0 | off+len>b.length) { + throw new IndexOutOfBoundsException(); + } + else if (len == 0) { + return; + } + else { + int flush = syncFlush ? JZlib.Z_SYNC_FLUSH : JZlib.Z_NO_FLUSH; + deflater.setInput(b, off, len, true); + while (deflater.avail_in>0) { + int err = deflate(flush); + if (err == JZlib.Z_STREAM_END) + break; + } + } + } + + public void finish() throws IOException { + while (!deflater.finished()) { + deflate(JZlib.Z_FINISH); + } + } + + public void close() throws IOException { + if (!closed) { + finish(); + if (mydeflater){ + deflater.end(); + } + if(close_out) + out.close(); + closed = true; + } + } + + protected int deflate(int flush) throws IOException { + deflater.setOutput(buffer, 0, buffer.length); + int err = deflater.deflate(flush); + switch(err) { + case JZlib.Z_OK: + case JZlib.Z_STREAM_END: + break; + case JZlib.Z_BUF_ERROR: + if(deflater.avail_in<=0 && flush!=JZlib.Z_FINISH){ + // flush() without any data + break; + } + default: + throw new IOException("failed to deflate: error="+err+" avail_out="+deflater.avail_out); + } + int len = deflater.next_out_index; + if (len > 0) { + out.write(buffer, 0, len); + } + return err; + } + + public void flush() throws IOException { + if (syncFlush && !deflater.finished()) { + while (true) { + int err = deflate(JZlib.Z_SYNC_FLUSH); + if (deflater.next_out_index < buffer.length) + break; + if (err == JZlib.Z_STREAM_END) + break; + } + } + out.flush(); + } + + public long getTotalIn() { + return deflater.getTotalIn(); + } + + public long getTotalOut() { + return deflater.getTotalOut(); + } + + public void setSyncFlush(boolean syncFlush){ + this.syncFlush = syncFlush; + } + + public boolean getSyncFlush(){ + return this.syncFlush; + } + + public Deflater getDeflater(){ + return deflater; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/GZIPException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,44 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +public class GZIPException extends java.io.IOException { + public GZIPException() { + super(); + } + public GZIPException(String s) { + super(s); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/GZIPHeader.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,214 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +import java.io.UnsupportedEncodingException; + +/** + * @see "http://www.ietf.org/rfc/rfc1952.txt" + */ +public class GZIPHeader implements Cloneable { + + public static final byte OS_MSDOS = (byte) 0x00; + public static final byte OS_AMIGA = (byte) 0x01; + public static final byte OS_VMS = (byte) 0x02; + public static final byte OS_UNIX = (byte) 0x03; + public static final byte OS_ATARI = (byte) 0x05; + public static final byte OS_OS2 = (byte) 0x06; + public static final byte OS_MACOS = (byte) 0x07; + public static final byte OS_TOPS20 = (byte) 0x0a; + public static final byte OS_WIN32 = (byte) 0x0b; + public static final byte OS_VMCMS = (byte) 0x04; + public static final byte OS_ZSYSTEM = (byte) 0x08; + public static final byte OS_CPM = (byte) 0x09; + public static final byte OS_QDOS = (byte) 0x0c; + public static final byte OS_RISCOS = (byte) 0x0d; + public static final byte OS_UNKNOWN = (byte) 0xff; + + boolean text = false; + private boolean fhcrc = false; + long time; + int xflags; + int os = 255; + byte[] extra; + byte[] name; + byte[] comment; + int hcrc; + long crc; + boolean done = false; + long mtime = 0; + + public void setModifiedTime(long mtime) { + this.mtime = mtime; + } + + public long getModifiedTime() { + return mtime; + } + + public void setOS(int os) { + if((0<=os && os <=13) || os==255) + this.os=os; + else + throw new IllegalArgumentException("os: "+os); + } + + public int getOS(){ + return os; + } + + public void setName(String name) { + try{ + this.name=name.getBytes("ISO-8859-1"); + } + catch(UnsupportedEncodingException e){ + throw new IllegalArgumentException("name must be in ISO-8859-1 "+name); + } + } + + public String getName(){ + if(name==null) return ""; + try { + return new String(name, "ISO-8859-1"); + } + catch (UnsupportedEncodingException e) { + throw new InternalError(e.toString()); + } + } + + public void setComment(String comment) { + try{ + this.comment=comment.getBytes("ISO-8859-1"); + } + catch(UnsupportedEncodingException e){ + throw new IllegalArgumentException("comment must be in ISO-8859-1 "+name); + } + } + + public String getComment(){ + if(comment==null) return ""; + try { + return new String(comment, "ISO-8859-1"); + } + catch (UnsupportedEncodingException e) { + throw new InternalError(e.toString()); + } + } + + public void setCRC(long crc){ + this.crc = crc; + } + + public long getCRC(){ + return crc; + } + + void put(Deflate d){ + int flag = 0; + if(text){ + flag |= 1; // FTEXT + } + if(fhcrc){ + flag |= 2; // FHCRC + } + if(extra!=null){ + flag |= 4; // FEXTRA + } + if(name!=null){ + flag |= 8; // FNAME + } + if(comment!=null){ + flag |= 16; // FCOMMENT + } + int xfl = 0; + if(d.level == JZlib.Z_BEST_SPEED){ + xfl |= 4; + } + else if (d.level == JZlib.Z_BEST_COMPRESSION){ + xfl |= 2; + } + + d.put_short((short)0x8b1f); // ID1 ID2 + d.put_byte((byte)8); // CM(Compression Method) + d.put_byte((byte)flag); + d.put_byte((byte)mtime); + d.put_byte((byte)(mtime>>8)); + d.put_byte((byte)(mtime>>16)); + d.put_byte((byte)(mtime>>24)); + d.put_byte((byte)xfl); + d.put_byte((byte)os); + + if(extra!=null){ + d.put_byte((byte)extra.length); + d.put_byte((byte)(extra.length>>8)); + d.put_byte(extra, 0, extra.length); + } + + if(name!=null){ + d.put_byte(name, 0, name.length); + d.put_byte((byte)0); + } + + if(comment!=null){ + d.put_byte(comment, 0, comment.length); + d.put_byte((byte)0); + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + GZIPHeader gheader = (GZIPHeader)super.clone(); + byte[] tmp; + if(gheader.extra!=null){ + tmp=new byte[gheader.extra.length]; + System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length); + gheader.extra = tmp; + } + + if(gheader.name!=null){ + tmp=new byte[gheader.name.length]; + System.arraycopy(gheader.name, 0, tmp, 0, tmp.length); + gheader.name = tmp; + } + + if(gheader.comment!=null){ + tmp=new byte[gheader.comment.length]; + System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length); + gheader.comment = tmp; + } + + return gheader; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/GZIPInputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,145 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +public class GZIPInputStream extends InflaterInputStream { + + public GZIPInputStream(InputStream in) throws IOException { + this(in, DEFAULT_BUFSIZE, true); + } + + public GZIPInputStream(InputStream in, + int size, + boolean close_in) throws IOException { + this(in, new Inflater(15+16), size, close_in); + myinflater = true; + } + + public GZIPInputStream(InputStream in, + Inflater inflater, + int size, + boolean close_in) throws IOException { + super(in, inflater, size, close_in); + } + + public long getModifiedtime() { + return inflater.istate.getGZIPHeader().getModifiedTime(); + } + + public int getOS() { + return inflater.istate.getGZIPHeader().getOS(); + } + + public String getName() { + return inflater.istate.getGZIPHeader().getName(); + } + + public String getComment() { + return inflater.istate.getGZIPHeader().getComment(); + } + + public long getCRC() throws GZIPException { + if(inflater.istate.mode != 12 /*DONE*/) + throw new GZIPException("checksum is not calculated yet."); + return inflater.istate.getGZIPHeader().getCRC(); + } + + public void readHeader() throws IOException { + + byte[] empty = "".getBytes(); + inflater.setOutput(empty, 0, 0); + inflater.setInput(empty, 0, 0, false); + + byte[] b = new byte[10]; + + int n = fill(b); + if(n!=10){ + if(n>0){ + inflater.setInput(b, 0, n, false); + //inflater.next_in_index = n; + inflater.next_in_index = 0; + inflater.avail_in = n; + } + throw new IOException("no input"); + } + + inflater.setInput(b, 0, n, false); + + byte[] b1 = new byte[1]; + do{ + if(inflater.avail_in<=0){ + int i = in.read(b1); + if(i<=0) + throw new IOException("no input"); + inflater.setInput(b1, 0, 1, true); + } + + int err = inflater.inflate(JZlib.Z_NO_FLUSH); + + if(err!=0/*Z_OK*/){ + int len = 2048-inflater.next_in.length; + if(len>0){ + byte[] tmp = new byte[len]; + n = fill(tmp); + if(n>0){ + inflater.avail_in += inflater.next_in_index; + inflater.next_in_index = 0; + inflater.setInput(tmp, 0, n, true); + } + } + //inflater.next_in_index = inflater.next_in.length; + inflater.avail_in += inflater.next_in_index; + inflater.next_in_index = 0; + throw new IOException(inflater.msg); + } + } + while(inflater.istate.inParsingHeader()); + } + + private int fill(byte[] buf) { + int len = buf.length; + int n = 0; + do{ + int i = -1; + try { + i = in.read(buf, n, buf.length - n); + } + catch(IOException e){ + } + if(i == -1){ + break; + } + n+=i; + } + while(n<len); + return n; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/GZIPOutputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,90 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +public class GZIPOutputStream extends DeflaterOutputStream { + + public GZIPOutputStream(OutputStream out) throws IOException { + this(out, DEFAULT_BUFSIZE); + } + + public GZIPOutputStream(OutputStream out, int size) throws IOException { + this(out, size, true); + } + + public GZIPOutputStream(OutputStream out, + int size, + boolean close_out) throws IOException { + this(out, + new Deflater(JZlib.Z_DEFAULT_COMPRESSION, 15+16), + size, close_out); + mydeflater=true; + } + + public GZIPOutputStream(OutputStream out, + Deflater deflater, + int size, + boolean close_out) throws IOException{ + super(out, deflater, size, close_out); + } + + + private void check() throws GZIPException { + if(deflater.dstate.status != 42 /*INIT_STATUS*/) + throw new GZIPException("header is already written."); + } + + public void setModifiedTime(long mtime) throws GZIPException { + check(); + deflater.dstate.getGZIPHeader().setModifiedTime(mtime); + } + + public void setOS(int os) throws GZIPException { + check(); + deflater.dstate.getGZIPHeader().setOS(os); + } + + public void setName(String name) throws GZIPException { + check(); + deflater.dstate.getGZIPHeader().setName(name); + } + + public void setComment(String comment) throws GZIPException { + check(); + deflater.dstate.getGZIPHeader().setComment(comment); + } + + public long getCRC() throws GZIPException { + if(deflater.dstate.status != 666 /*FINISH_STATE*/) + throw new GZIPException("checksum is not calculated yet."); + return deflater.dstate.getGZIPHeader().getCRC(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/InfBlocks.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,614 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class InfBlocks{ + static final private int MANY=1440; + + // And'ing with mask[n] masks the lower n bits + static final private int[] inflate_mask = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, + 0x00007fff, 0x0000ffff + }; + + // Table for deflate from PKZIP's appnote.txt. + static final int[] border = { // Order of the bit length code lengths + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + }; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + static final private int TYPE=0; // get type bits (3, including end bit) + static final private int LENS=1; // get lengths for stored + static final private int STORED=2;// processing stored block + static final private int TABLE=3; // get table lengths + static final private int BTREE=4; // get bit lengths tree for a dynamic block + static final private int DTREE=5; // get length, distance trees for a dynamic block + static final private int CODES=6; // processing fixed or dynamic block + static final private int DRY=7; // output remaining window bytes + static final private int DONE=8; // finished last block, done + static final private int BAD=9; // ot a data error--stuck here + + int mode; // current inflate_block mode + + int left; // if STORED, bytes left to copy + + int table; // table lengths (14 bits) + int index; // index into blens (or border) + int[] blens; // bit lengths of codes + int[] bb=new int[1]; // bit length tree depth + int[] tb=new int[1]; // bit length decoding tree + + int[] bl=new int[1]; + int[] bd=new int[1]; + + int[][] tl=new int[1][]; + int[][] td=new int[1][]; + int[] tli=new int[1]; // tl_index + int[] tdi=new int[1]; // td_index + + private final InfCodes codes; // if CODES, current state + + int last; // true if this block is the last block + + // mode independent information + int bitk; // bits in bit buffer + int bitb; // bit buffer + int[] hufts; // single malloc for tree space + byte[] window; // sliding window + int end; // one byte after sliding window + int read; // window read pointer + int write; // window write pointer + private boolean check; + + private final InfTree inftree=new InfTree(); + + private final ZStream z; + + InfBlocks(ZStream z, int w){ + this.z=z; + this.codes=new InfCodes(this.z, this); + hufts=new int[MANY*3]; + window=new byte[w]; + end=w; + this.check = (z.istate.wrap==0) ? false : true; + mode = TYPE; + reset(); + } + + void reset(){ + if(mode==BTREE || mode==DTREE){ + } + if(mode==CODES){ + codes.free(z); + } + mode=TYPE; + bitk=0; + bitb=0; + read=write=0; + if(check){ + z.adler.reset(); + } + } + + int proc(int r){ + int t; // temporary storage + int b; // bit buffer + int k; // bits in bit buffer + int p; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + + // copy input/output information to locals (UPDATE macro restores) + {p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;} + {q=write;m=(int)(q<read?read-q-1:end-q);} + + // process input based on current state + while(true){ + switch (mode){ + case TYPE: + + while(k<(3)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + t = (int)(b & 7); + last = t & 1; + + switch (t >>> 1){ + case 0: // stored + {b>>>=(3);k-=(3);} + t = k & 7; // go to byte boundary + + {b>>>=(t);k-=(t);} + mode = LENS; // get length of stored block + break; + case 1: // fixed + InfTree.inflate_trees_fixed(bl, bd, tl, td, z); + codes.init(bl[0], bd[0], tl[0], 0, td[0], 0); + + {b>>>=(3);k-=(3);} + + mode = CODES; + break; + case 2: // dynamic + + {b>>>=(3);k-=(3);} + + mode = TABLE; + break; + case 3: // illegal + + {b>>>=(3);k-=(3);} + mode = BAD; + z.msg = "invalid block type"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + break; + case LENS: + + while(k<(32)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + + if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){ + mode = BAD; + z.msg = "invalid stored block lengths"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + left = (b & 0xffff); + b = k = 0; // dump bits + mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE); + break; + case STORED: + if (n == 0){ + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + + if(m==0){ + if(q==end&&read!=0){ + q=0; m=(int)(q<read?read-q-1:end-q); + } + if(m==0){ + write=q; + r=inflate_flush(r); + q=write;m=(int)(q<read?read-q-1:end-q); + if(q==end&&read!=0){ + q=0; m=(int)(q<read?read-q-1:end-q); + } + if(m==0){ + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + } + } + r=Z_OK; + + t = left; + if(t>n) t = n; + if(t>m) t = m; + System.arraycopy(z.next_in, p, window, q, t); + p += t; n -= t; + q += t; m -= t; + if ((left -= t) != 0) + break; + mode = last!=0 ? DRY : TYPE; + break; + case TABLE: + + while(k<(14)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + + table = t = (b & 0x3fff); + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + mode = BAD; + z.msg = "too many length or distance symbols"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if(blens==null || blens.length<t){ + blens=new int[t]; + } + else{ + for(int i=0; i<t; i++){blens[i]=0;} + } + + {b>>>=(14);k-=(14);} + + index = 0; + mode = BTREE; + case BTREE: + while (index < 4 + (table >>> 10)){ + while(k<(3)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + + blens[border[index++]] = b&7; + + {b>>>=(3);k-=(3);} + } + + while(index < 19){ + blens[border[index++]] = 0; + } + + bb[0] = 7; + t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z); + if (t != Z_OK){ + r = t; + if (r == Z_DATA_ERROR){ + blens=null; + mode = BAD; + } + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + + index = 0; + mode = DTREE; + case DTREE: + while (true){ + t = table; + if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){ + break; + } + + int[] h; + int i, j, c; + + t = bb[0]; + + while(k<(t)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + + if(tb[0]==-1){ + //System.err.println("null..."); + } + + t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1]; + c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2]; + + if (c < 16){ + b>>>=(t);k-=(t); + blens[index++] = c; + } + else { // c == 16..18 + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + + while(k<(t+i)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + + b>>>=(t);k-=(t); + + j += (b & inflate_mask[i]); + + b>>>=(i);k-=(i); + + i = index; + t = table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)){ + blens=null; + mode = BAD; + z.msg = "invalid bit length repeat"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + + c = c == 16 ? blens[i-1] : 0; + do{ + blens[i++] = c; + } + while (--j!=0); + index = i; + } + } + + tb[0]=-1; + { + bl[0] = 9; // must be <= 9 for lookahead assumptions + bd[0] = 6; // must be <= 9 for lookahead assumptions + t = table; + t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), + 1 + ((t >> 5) & 0x1f), + blens, bl, bd, tli, tdi, hufts, z); + + if (t != Z_OK){ + if (t == Z_DATA_ERROR){ + blens=null; + mode = BAD; + } + r = t; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]); + } + mode = CODES; + case CODES: + bitb=b; bitk=k; + z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + + if ((r = codes.proc(r)) != Z_STREAM_END){ + return inflate_flush(r); + } + r = Z_OK; + codes.free(z); + + p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk; + q=write;m=(int)(q<read?read-q-1:end-q); + + if (last==0){ + mode = TYPE; + break; + } + mode = DRY; + case DRY: + write=q; + r=inflate_flush(r); + q=write; m=(int)(q<read?read-q-1:end-q); + if (read != write){ + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + mode = DONE; + case DONE: + r = Z_STREAM_END; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + case BAD: + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + + default: + r = Z_STREAM_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + } + } + + void free(){ + reset(); + window=null; + hufts=null; + //ZFREE(z, s); + } + + void set_dictionary(byte[] d, int start, int n){ + System.arraycopy(d, start, window, 0, n); + read = write = n; + } + + // Returns true if inflate is currently at the end of a block generated + // by Z_SYNC_FLUSH or Z_FULL_FLUSH. + int sync_point(){ + return mode == LENS ? 1 : 0; + } + + // copy as much as possible from the sliding window to the output area + int inflate_flush(int r){ + int n; + int p; + int q; + + // local copies of source and destination pointers + p = z.next_out_index; + q = read; + + // compute number of bytes to copy as far as end of window + n = (int)((q <= write ? write : end) - q); + if(n > z.avail_out) n = z.avail_out; + if(n!=0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if(check && n>0){ + z.adler.update(window, q, n); + } + + // copy as far as end of window + System.arraycopy(window, q, z.next_out, p, n); + p += n; + q += n; + + // see if more to copy at beginning of window + if (q == end){ + // wrap pointers + q = 0; + if (write == end) + write = 0; + + // compute bytes to copy + n = write - q; + if (n > z.avail_out) n = z.avail_out; + if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if(check && n>0){ + z.adler.update(window, q, n); + } + + // copy + System.arraycopy(window, q, z.next_out, p, n); + p += n; + q += n; + } + + // update pointers + z.next_out_index = p; + read = q; + + // done + return r; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/InfCodes.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,610 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class InfCodes{ + + static final private int[] inflate_mask = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, + 0x00007fff, 0x0000ffff + }; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + // waiting for "i:"=input, + // "o:"=output, + // "x:"=nothing + static final private int START=0; // x: set up for LEN + static final private int LEN=1; // i: get length/literal/eob next + static final private int LENEXT=2; // i: getting length extra (have base) + static final private int DIST=3; // i: get distance next + static final private int DISTEXT=4;// i: getting distance extra + static final private int COPY=5; // o: copying bytes in window, waiting for space + static final private int LIT=6; // o: got literal, waiting for output space + static final private int WASH=7; // o: got eob, possibly still output waiting + static final private int END=8; // x: got eob and all data flushed + static final private int BADCODE=9;// x: got error + + int mode; // current inflate_codes mode + + // mode dependent information + int len; + + int[] tree; // pointer into tree + int tree_index=0; + int need; // bits needed + + int lit; + + // if EXT or COPY, where and how much + int get; // bits to get for extra + int dist; // distance back to copy from + + byte lbits; // ltree bits decoded per branch + byte dbits; // dtree bits decoder per branch + int[] ltree; // literal/length/eob tree + int ltree_index; // literal/length/eob tree + int[] dtree; // distance tree + int dtree_index; // distance tree + + private final ZStream z; + private final InfBlocks s; + InfCodes(ZStream z, InfBlocks s){ + this.z=z; + this.s=s; + } + + void init(int bl, int bd, + int[] tl, int tl_index, + int[] td, int td_index){ + mode=START; + lbits=(byte)bl; + dbits=(byte)bd; + ltree=tl; + ltree_index=tl_index; + dtree = td; + dtree_index=td_index; + tree=null; + } + + int proc(int r){ + int j; // temporary storage + int[] t; // temporary pointer + int tindex; // temporary pointer + int e; // extra bits or operation + int b=0; // bit buffer + int k=0; // bits in bit buffer + int p=0; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + int f; // pointer to copy strings from + + // copy input/output information to locals (UPDATE macro restores) + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; + q=s.write;m=q<s.read?s.read-q-1:s.end-q; + + // process input and output based on current state + while (true){ + switch (mode){ + // waiting for "i:"=input, "o:"=output, "x:"=nothing + case START: // x: set up for LEN + if (m >= 258 && n >= 10){ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + r = inflate_fast(lbits, dbits, + ltree, ltree_index, + dtree, dtree_index, + s, z); + + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; + q=s.write;m=q<s.read?s.read-q-1:s.end-q; + + if (r != Z_OK){ + mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } + need = lbits; + tree = ltree; + tree_index=ltree_index; + + mode = LEN; + case LEN: // i: get length/literal/eob next + j = need; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; + b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + + tindex=(tree_index+(b&inflate_mask[j]))*3; + + b>>>=(tree[tindex+1]); + k-=(tree[tindex+1]); + + e=tree[tindex]; + + if(e == 0){ // literal + lit = tree[tindex+2]; + mode = LIT; + break; + } + if((e & 16)!=0 ){ // length + get = e & 15; + len = tree[tindex+2]; + mode = LENEXT; + break; + } + if ((e & 64) == 0){ // next table + need = e; + tree_index = tindex/3+tree[tindex+2]; + break; + } + if ((e & 32)!=0){ // end of block + mode = WASH; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid literal/length code"; + r = Z_DATA_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + + case LENEXT: // i: getting length extra (have base) + j = get; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + + len += (b & inflate_mask[j]); + + b>>=j; + k-=j; + + need = dbits; + tree = dtree; + tree_index=dtree_index; + mode = DIST; + case DIST: // i: get distance next + j = need; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + + tindex=(tree_index+(b & inflate_mask[j]))*3; + + b>>=tree[tindex+1]; + k-=tree[tindex+1]; + + e = (tree[tindex]); + if((e & 16)!=0){ // distance + get = e & 15; + dist = tree[tindex+2]; + mode = DISTEXT; + break; + } + if ((e & 64) == 0){ // next table + need = e; + tree_index = tindex/3 + tree[tindex+2]; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid distance code"; + r = Z_DATA_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + + case DISTEXT: // i: getting distance extra + j = get; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; b|=(z.next_in[p++]&0xff)<<k; + k+=8; + } + + dist += (b & inflate_mask[j]); + + b>>=j; + k-=j; + + mode = COPY; + case COPY: // o: copying bytes in window, waiting for space + f = q - dist; + while(f < 0){ // modulo window size-"while" instead + f += s.end; // of "if" handles invalid distances + } + while (len!=0){ + + if(m==0){ + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;} + if(m==0){ + s.write=q; r=s.inflate_flush(r); + q=s.write;m=q<s.read?s.read-q-1:s.end-q; + + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;} + + if(m==0){ + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + } + } + + s.window[q++]=s.window[f++]; m--; + + if (f == s.end) + f = 0; + len--; + } + mode = START; + break; + case LIT: // o: got literal, waiting for output space + if(m==0){ + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;} + if(m==0){ + s.write=q; r=s.inflate_flush(r); + q=s.write;m=q<s.read?s.read-q-1:s.end-q; + + if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;} + if(m==0){ + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + } + } + r=Z_OK; + + s.window[q++]=(byte)lit; m--; + + mode = START; + break; + case WASH: // o: got eob, possibly more output + if (k > 7){ // return unused byte, if any + k -= 8; + n++; + p--; // can always return one + } + + s.write=q; r=s.inflate_flush(r); + q=s.write;m=q<s.read?s.read-q-1:s.end-q; + + if (s.read != s.write){ + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + mode = END; + case END: + r = Z_STREAM_END; + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + + case BADCODE: // x: got error + + r = Z_DATA_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + + default: + r = Z_STREAM_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + } + } + + void free(ZStream z){ + // ZFREE(z, c); + } + + // Called with number of bytes left to write in window at least 258 + // (the maximum string length) and number of input bytes available + // at least ten. The ten bytes are six bytes for the longest length/ + // distance pair plus four bytes for overloading the bit buffer. + + int inflate_fast(int bl, int bd, + int[] tl, int tl_index, + int[] td, int td_index, + InfBlocks s, ZStream z){ + int t; // temporary pointer + int[] tp; // temporary pointer + int tp_index; // temporary pointer + int e; // extra bits or operation + int b; // bit buffer + int k; // bits in bit buffer + int p; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + int ml; // mask for literal/length tree + int md; // mask for distance tree + int c; // bytes to copy + int d; // distance back to copy from + int r; // copy source pointer + + int tp_index_t_3; // (tp_index+t)*3 + + // load input, output, bit values + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; + q=s.write;m=q<s.read?s.read-q-1:s.end-q; + + // initialize masks + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + // do until not enough input or output space for fast loop + do { // assume called with m >= 258 && n >= 10 + // get literal/length code + while(k<(20)){ // max bits for literal/length code + n--; + b|=(z.next_in[p++]&0xff)<<k;k+=8; + } + + t= b&ml; + tp=tl; + tp_index=tl_index; + tp_index_t_3=(tp_index+t)*3; + if ((e = tp[tp_index_t_3]) == 0){ + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + s.window[q++] = (byte)tp[tp_index_t_3+2]; + m--; + continue; + } + do { + + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + if((e&16)!=0){ + e &= 15; + c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]); + + b>>=e; k-=e; + + // decode distance base of block to copy + while(k<(15)){ // max bits for distance code + n--; + b|=(z.next_in[p++]&0xff)<<k;k+=8; + } + + t= b&md; + tp=td; + tp_index=td_index; + tp_index_t_3=(tp_index+t)*3; + e = tp[tp_index_t_3]; + + do { + + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + if((e&16)!=0){ + // get extra bits to add to distance base + e &= 15; + while(k<(e)){ // get extra bits (up to 13) + n--; + b|=(z.next_in[p++]&0xff)<<k;k+=8; + } + + d = tp[tp_index_t_3+2] + (b&inflate_mask[e]); + + b>>=(e); k-=(e); + + // do the copy + m -= c; + if (q >= d){ // offset before dest + // just copy + r=q-d; + if(q-r>0 && 2>(q-r)){ + s.window[q++]=s.window[r++]; // minimum count is three, + s.window[q++]=s.window[r++]; // so unroll loop a little + c-=2; + } + else{ + System.arraycopy(s.window, r, s.window, q, 2); + q+=2; r+=2; c-=2; + } + } + else{ // else offset after destination + r=q-d; + do{ + r+=s.end; // force pointer in window + }while(r<0); // covers invalid distances + e=s.end-r; + if(c>e){ // if source crosses, + c-=e; // wrapped copy + if(q-r>0 && e>(q-r)){ + do{s.window[q++] = s.window[r++];} + while(--e!=0); + } + else{ + System.arraycopy(s.window, r, s.window, q, e); + q+=e; r+=e; e=0; + } + r = 0; // copy rest from start of window + } + + } + + // copy all or what's left + if(q-r>0 && c>(q-r)){ + do{s.window[q++] = s.window[r++];} + while(--c!=0); + } + else{ + System.arraycopy(s.window, r, s.window, q, c); + q+=c; r+=c; c=0; + } + break; + } + else if((e&64)==0){ + t+=tp[tp_index_t_3+2]; + t+=(b&inflate_mask[e]); + tp_index_t_3=(tp_index+t)*3; + e=tp[tp_index_t_3]; + } + else{ + z.msg = "invalid distance code"; + + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_DATA_ERROR; + } + } + while(true); + break; + } + + if((e&64)==0){ + t+=tp[tp_index_t_3+2]; + t+=(b&inflate_mask[e]); + tp_index_t_3=(tp_index+t)*3; + if((e=tp[tp_index_t_3])==0){ + + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + s.window[q++]=(byte)tp[tp_index_t_3+2]; + m--; + break; + } + } + else if((e&32)!=0){ + + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_STREAM_END; + } + else{ + z.msg="invalid literal/length code"; + + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_DATA_ERROR; + } + } + while(true); + } + while(m>=258 && n>= 10); + + // not enough input or output--restore pointers and return + c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_OK; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/InfTree.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,518 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class InfTree{ + + static final private int MANY=1440; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + static final int fixed_bl = 9; + static final int fixed_bd = 5; + + static final int[] fixed_tl = { + 96,7,256, 0,8,80, 0,8,16, 84,8,115, + 82,7,31, 0,8,112, 0,8,48, 0,9,192, + 80,7,10, 0,8,96, 0,8,32, 0,9,160, + 0,8,0, 0,8,128, 0,8,64, 0,9,224, + 80,7,6, 0,8,88, 0,8,24, 0,9,144, + 83,7,59, 0,8,120, 0,8,56, 0,9,208, + 81,7,17, 0,8,104, 0,8,40, 0,9,176, + 0,8,8, 0,8,136, 0,8,72, 0,9,240, + 80,7,4, 0,8,84, 0,8,20, 85,8,227, + 83,7,43, 0,8,116, 0,8,52, 0,9,200, + 81,7,13, 0,8,100, 0,8,36, 0,9,168, + 0,8,4, 0,8,132, 0,8,68, 0,9,232, + 80,7,8, 0,8,92, 0,8,28, 0,9,152, + 84,7,83, 0,8,124, 0,8,60, 0,9,216, + 82,7,23, 0,8,108, 0,8,44, 0,9,184, + 0,8,12, 0,8,140, 0,8,76, 0,9,248, + 80,7,3, 0,8,82, 0,8,18, 85,8,163, + 83,7,35, 0,8,114, 0,8,50, 0,9,196, + 81,7,11, 0,8,98, 0,8,34, 0,9,164, + 0,8,2, 0,8,130, 0,8,66, 0,9,228, + 80,7,7, 0,8,90, 0,8,26, 0,9,148, + 84,7,67, 0,8,122, 0,8,58, 0,9,212, + 82,7,19, 0,8,106, 0,8,42, 0,9,180, + 0,8,10, 0,8,138, 0,8,74, 0,9,244, + 80,7,5, 0,8,86, 0,8,22, 192,8,0, + 83,7,51, 0,8,118, 0,8,54, 0,9,204, + 81,7,15, 0,8,102, 0,8,38, 0,9,172, + 0,8,6, 0,8,134, 0,8,70, 0,9,236, + 80,7,9, 0,8,94, 0,8,30, 0,9,156, + 84,7,99, 0,8,126, 0,8,62, 0,9,220, + 82,7,27, 0,8,110, 0,8,46, 0,9,188, + 0,8,14, 0,8,142, 0,8,78, 0,9,252, + 96,7,256, 0,8,81, 0,8,17, 85,8,131, + 82,7,31, 0,8,113, 0,8,49, 0,9,194, + 80,7,10, 0,8,97, 0,8,33, 0,9,162, + 0,8,1, 0,8,129, 0,8,65, 0,9,226, + 80,7,6, 0,8,89, 0,8,25, 0,9,146, + 83,7,59, 0,8,121, 0,8,57, 0,9,210, + 81,7,17, 0,8,105, 0,8,41, 0,9,178, + 0,8,9, 0,8,137, 0,8,73, 0,9,242, + 80,7,4, 0,8,85, 0,8,21, 80,8,258, + 83,7,43, 0,8,117, 0,8,53, 0,9,202, + 81,7,13, 0,8,101, 0,8,37, 0,9,170, + 0,8,5, 0,8,133, 0,8,69, 0,9,234, + 80,7,8, 0,8,93, 0,8,29, 0,9,154, + 84,7,83, 0,8,125, 0,8,61, 0,9,218, + 82,7,23, 0,8,109, 0,8,45, 0,9,186, + 0,8,13, 0,8,141, 0,8,77, 0,9,250, + 80,7,3, 0,8,83, 0,8,19, 85,8,195, + 83,7,35, 0,8,115, 0,8,51, 0,9,198, + 81,7,11, 0,8,99, 0,8,35, 0,9,166, + 0,8,3, 0,8,131, 0,8,67, 0,9,230, + 80,7,7, 0,8,91, 0,8,27, 0,9,150, + 84,7,67, 0,8,123, 0,8,59, 0,9,214, + 82,7,19, 0,8,107, 0,8,43, 0,9,182, + 0,8,11, 0,8,139, 0,8,75, 0,9,246, + 80,7,5, 0,8,87, 0,8,23, 192,8,0, + 83,7,51, 0,8,119, 0,8,55, 0,9,206, + 81,7,15, 0,8,103, 0,8,39, 0,9,174, + 0,8,7, 0,8,135, 0,8,71, 0,9,238, + 80,7,9, 0,8,95, 0,8,31, 0,9,158, + 84,7,99, 0,8,127, 0,8,63, 0,9,222, + 82,7,27, 0,8,111, 0,8,47, 0,9,190, + 0,8,15, 0,8,143, 0,8,79, 0,9,254, + 96,7,256, 0,8,80, 0,8,16, 84,8,115, + 82,7,31, 0,8,112, 0,8,48, 0,9,193, + + 80,7,10, 0,8,96, 0,8,32, 0,9,161, + 0,8,0, 0,8,128, 0,8,64, 0,9,225, + 80,7,6, 0,8,88, 0,8,24, 0,9,145, + 83,7,59, 0,8,120, 0,8,56, 0,9,209, + 81,7,17, 0,8,104, 0,8,40, 0,9,177, + 0,8,8, 0,8,136, 0,8,72, 0,9,241, + 80,7,4, 0,8,84, 0,8,20, 85,8,227, + 83,7,43, 0,8,116, 0,8,52, 0,9,201, + 81,7,13, 0,8,100, 0,8,36, 0,9,169, + 0,8,4, 0,8,132, 0,8,68, 0,9,233, + 80,7,8, 0,8,92, 0,8,28, 0,9,153, + 84,7,83, 0,8,124, 0,8,60, 0,9,217, + 82,7,23, 0,8,108, 0,8,44, 0,9,185, + 0,8,12, 0,8,140, 0,8,76, 0,9,249, + 80,7,3, 0,8,82, 0,8,18, 85,8,163, + 83,7,35, 0,8,114, 0,8,50, 0,9,197, + 81,7,11, 0,8,98, 0,8,34, 0,9,165, + 0,8,2, 0,8,130, 0,8,66, 0,9,229, + 80,7,7, 0,8,90, 0,8,26, 0,9,149, + 84,7,67, 0,8,122, 0,8,58, 0,9,213, + 82,7,19, 0,8,106, 0,8,42, 0,9,181, + 0,8,10, 0,8,138, 0,8,74, 0,9,245, + 80,7,5, 0,8,86, 0,8,22, 192,8,0, + 83,7,51, 0,8,118, 0,8,54, 0,9,205, + 81,7,15, 0,8,102, 0,8,38, 0,9,173, + 0,8,6, 0,8,134, 0,8,70, 0,9,237, + 80,7,9, 0,8,94, 0,8,30, 0,9,157, + 84,7,99, 0,8,126, 0,8,62, 0,9,221, + 82,7,27, 0,8,110, 0,8,46, 0,9,189, + 0,8,14, 0,8,142, 0,8,78, 0,9,253, + 96,7,256, 0,8,81, 0,8,17, 85,8,131, + 82,7,31, 0,8,113, 0,8,49, 0,9,195, + 80,7,10, 0,8,97, 0,8,33, 0,9,163, + 0,8,1, 0,8,129, 0,8,65, 0,9,227, + 80,7,6, 0,8,89, 0,8,25, 0,9,147, + 83,7,59, 0,8,121, 0,8,57, 0,9,211, + 81,7,17, 0,8,105, 0,8,41, 0,9,179, + 0,8,9, 0,8,137, 0,8,73, 0,9,243, + 80,7,4, 0,8,85, 0,8,21, 80,8,258, + 83,7,43, 0,8,117, 0,8,53, 0,9,203, + 81,7,13, 0,8,101, 0,8,37, 0,9,171, + 0,8,5, 0,8,133, 0,8,69, 0,9,235, + 80,7,8, 0,8,93, 0,8,29, 0,9,155, + 84,7,83, 0,8,125, 0,8,61, 0,9,219, + 82,7,23, 0,8,109, 0,8,45, 0,9,187, + 0,8,13, 0,8,141, 0,8,77, 0,9,251, + 80,7,3, 0,8,83, 0,8,19, 85,8,195, + 83,7,35, 0,8,115, 0,8,51, 0,9,199, + 81,7,11, 0,8,99, 0,8,35, 0,9,167, + 0,8,3, 0,8,131, 0,8,67, 0,9,231, + 80,7,7, 0,8,91, 0,8,27, 0,9,151, + 84,7,67, 0,8,123, 0,8,59, 0,9,215, + 82,7,19, 0,8,107, 0,8,43, 0,9,183, + 0,8,11, 0,8,139, 0,8,75, 0,9,247, + 80,7,5, 0,8,87, 0,8,23, 192,8,0, + 83,7,51, 0,8,119, 0,8,55, 0,9,207, + 81,7,15, 0,8,103, 0,8,39, 0,9,175, + 0,8,7, 0,8,135, 0,8,71, 0,9,239, + 80,7,9, 0,8,95, 0,8,31, 0,9,159, + 84,7,99, 0,8,127, 0,8,63, 0,9,223, + 82,7,27, 0,8,111, 0,8,47, 0,9,191, + 0,8,15, 0,8,143, 0,8,79, 0,9,255 + }; + static final int[] fixed_td = { + 80,5,1, 87,5,257, 83,5,17, 91,5,4097, + 81,5,5, 89,5,1025, 85,5,65, 93,5,16385, + 80,5,3, 88,5,513, 84,5,33, 92,5,8193, + 82,5,9, 90,5,2049, 86,5,129, 192,5,24577, + 80,5,2, 87,5,385, 83,5,25, 91,5,6145, + 81,5,7, 89,5,1537, 85,5,97, 93,5,24577, + 80,5,4, 88,5,769, 84,5,49, 92,5,12289, + 82,5,13, 90,5,3073, 86,5,193, 192,5,24577 + }; + + // Tables for deflate from PKZIP's appnote.txt. + static final int[] cplens = { // Copy lengths for literal codes 257..285 + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + }; + + // see note #13 above about 258 + static final int[] cplext = { // Extra bits for literal codes 257..285 + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid + }; + + static final int[] cpdist = { // Copy offsets for distance codes 0..29 + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + + static final int[] cpdext = { // Extra bits for distance codes + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + // If BMAX needs to be larger than 16, then h and x[] should be uLong. + static final int BMAX=15; // maximum bit length of any code + + int[] hn = null; // hufts used in space + int[] v = null; // work area for huft_build + int[] c = null; // bit length count table + int[] r = null; // table entry for structure assignment + int[] u = null; // table stack + int[] x = null; // bit offsets, then code stack + + private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX) + int bindex, + int n, // number of codes (assumed <= 288) + int s, // number of simple-valued codes (0..s-1) + int[] d, // list of base values for non-simple codes + int[] e, // list of extra bits for non-simple codes + int[] t, // result: starting table + int[] m, // maximum lookup bits, returns actual + int[] hp,// space for trees + int[] hn,// hufts used in space + int[] v // working area: values in order of bit length + ){ + // Given a list of code lengths and a maximum table size, make a set of + // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + // if the given code set is incomplete (the tables are still built in this + // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of + // lengths), or Z_MEM_ERROR if not enough memory. + + int a; // counter for codes of length k + int f; // i repeats in table every f entries + int g; // maximum code length + int h; // table level + int i; // counter, current code + int j; // counter + int k; // number of bits in current code + int l; // bits per table (returned in m) + int mask; // (1 << w) - 1, to avoid cc -O bug on HP + int p; // pointer into c[], b[], or v[] + int q; // points to current table + int w; // bits before this table == (l * h) + int xp; // pointer into x + int y; // number of dummy codes added + int z; // number of entries in current table + + // Generate counts for each bit length + + p = 0; i = n; + do { + c[b[bindex+p]]++; p++; i--; // assume all entries <= BMAX + }while(i!=0); + + if(c[0] == n){ // null input--all zero length codes + t[0] = -1; + m[0] = 0; + return Z_OK; + } + + // Find minimum and maximum length, bound *m by those + l = m[0]; + for (j = 1; j <= BMAX; j++) + if(c[j]!=0) break; + k = j; // minimum code length + if(l < j){ + l = j; + } + for (i = BMAX; i!=0; i--){ + if(c[i]!=0) break; + } + g = i; // maximum code length + if(l > i){ + l = i; + } + m[0] = l; + + // Adjust last length count to fill out codes, if needed + for (y = 1 << j; j < i; j++, y <<= 1){ + if ((y -= c[j]) < 0){ + return Z_DATA_ERROR; + } + } + if ((y -= c[i]) < 0){ + return Z_DATA_ERROR; + } + c[i] += y; + + // Generate starting offsets into the value table for each length + x[1] = j = 0; + p = 1; xp = 2; + while (--i!=0) { // note that i == g from above + x[xp] = (j += c[p]); + xp++; + p++; + } + + // Make a table of values in order of bit lengths + i = 0; p = 0; + do { + if ((j = b[bindex+p]) != 0){ + v[x[j]++] = i; + } + p++; + } + while (++i < n); + n = x[g]; // set n to length of v + + // Generate the Huffman codes and for each, make the table entries + x[0] = i = 0; // first Huffman code is zero + p = 0; // grab values in bit order + h = -1; // no tables yet--level -1 + w = -l; // bits decoded == (l * h) + u[0] = 0; // just to keep compilers happy + q = 0; // ditto + z = 0; // ditto + + // go through the bit lengths (k already is bits in shortest code) + for (; k <= g; k++){ + a = c[k]; + while (a--!=0){ + // here i is the Huffman code of length k bits for value *p + // make tables up to required level + while (k > w + l){ + h++; + w += l; // previous table always l bits + // compute minimum size table less than or equal to l bits + z = g - w; + z = (z > l) ? l : z; // table size upper limit + if((f=1<<(j=k-w))>a+1){ // try a k-w bit table + // too few codes for k-w bit table + f -= a + 1; // deduct codes from patterns left + xp = k; + if(j < z){ + while (++j < z){ // try smaller tables up to z bits + if((f <<= 1) <= c[++xp]) + break; // enough codes to use up j bits + f -= c[xp]; // else deduct codes from patterns + } + } + } + z = 1 << j; // table entries for j-bit table + + // allocate new table + if (hn[0] + z > MANY){ // (note: doesn't matter for fixed) + return Z_DATA_ERROR; // overflow of MANY + } + u[h] = q = /*hp+*/ hn[0]; // DEBUG + hn[0] += z; + + // connect to last table, if there is one + if(h!=0){ + x[h]=i; // save pattern for backing up + r[0]=(byte)j; // bits in this table + r[1]=(byte)l; // bits to dump before this table + j=i>>>(w - l); + r[2] = (int)(q - u[h-1] - j); // offset to this table + System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table + } + else{ + t[0] = q; // first table is returned result + } + } + + // set up table entry in r + r[1] = (byte)(k - w); + if (p >= n){ + r[0] = 128 + 64; // out of values--invalid code + } + else if (v[p] < s){ + r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block + r[2] = v[p++]; // simple code is just the value + } + else{ + r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists + r[2]=d[v[p++] - s]; + } + + // fill code-like entries with r + f=1<<(k-w); + for (j=i>>>w;j<z;j+=f){ + System.arraycopy(r, 0, hp, (q+j)*3, 3); + } + + // backwards increment the k-bit code i + for (j = 1 << (k - 1); (i & j)!=0; j >>>= 1){ + i ^= j; + } + i ^= j; + + // backup over finished tables + mask = (1 << w) - 1; // needed on HP, cc -O bug + while ((i & mask) != x[h]){ + h--; // don't need to update q + w -= l; + mask = (1 << w) - 1; + } + } + } + // Return Z_BUF_ERROR if we were given an incomplete table + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; + } + + int inflate_trees_bits(int[] c, // 19 code lengths + int[] bb, // bits tree desired/actual depth + int[] tb, // bits tree result + int[] hp, // space for trees + ZStream z // for messages + ){ + int result; + initWorkArea(19); + hn[0]=0; + result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); + + if(result == Z_DATA_ERROR){ + z.msg = "oversubscribed dynamic bit lengths tree"; + } + else if(result == Z_BUF_ERROR || bb[0] == 0){ + z.msg = "incomplete dynamic bit lengths tree"; + result = Z_DATA_ERROR; + } + return result; + } + + int inflate_trees_dynamic(int nl, // number of literal/length codes + int nd, // number of distance codes + int[] c, // that many (total) code lengths + int[] bl, // literal desired/actual bit depth + int[] bd, // distance desired/actual bit depth + int[] tl, // literal/length tree result + int[] td, // distance tree result + int[] hp, // space for trees + ZStream z // for messages + ){ + int result; + + // build literal/length tree + initWorkArea(288); + hn[0]=0; + result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); + if (result != Z_OK || bl[0] == 0){ + if(result == Z_DATA_ERROR){ + z.msg = "oversubscribed literal/length tree"; + } + else if (result != Z_MEM_ERROR){ + z.msg = "incomplete literal/length tree"; + result = Z_DATA_ERROR; + } + return result; + } + + // build distance tree + initWorkArea(288); + result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); + + if (result != Z_OK || (bd[0] == 0 && nl > 257)){ + if (result == Z_DATA_ERROR){ + z.msg = "oversubscribed distance tree"; + } + else if (result == Z_BUF_ERROR) { + z.msg = "incomplete distance tree"; + result = Z_DATA_ERROR; + } + else if (result != Z_MEM_ERROR){ + z.msg = "empty distance tree with lengths"; + result = Z_DATA_ERROR; + } + return result; + } + + return Z_OK; + } + + static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth + int[] bd, //distance desired/actual bit depth + int[][] tl,//literal/length tree result + int[][] td,//distance tree result + ZStream z //for memory allocation + ){ + bl[0]=fixed_bl; + bd[0]=fixed_bd; + tl[0]=fixed_tl; + td[0]=fixed_td; + return Z_OK; + } + + private void initWorkArea(int vsize){ + if(hn==null){ + hn=new int[1]; + v=new int[vsize]; + c=new int[BMAX+1]; + r=new int[3]; + u=new int[BMAX]; + x=new int[BMAX+1]; + } + if(v.length<vsize){ v=new int[vsize]; } + for(int i=0; i<vsize; i++){v[i]=0;} + for(int i=0; i<BMAX+1; i++){c[i]=0;} + for(int i=0; i<3; i++){r[i]=0;} + System.arraycopy(c, 0, u, 0, BMAX); + System.arraycopy(c, 0, x, 0, BMAX+1); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/Inflate.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,751 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class Inflate{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + + // preset dictionary flag in zlib header + static final private int PRESET_DICT=0x20; + + static final int Z_NO_FLUSH=0; + static final int Z_PARTIAL_FLUSH=1; + static final int Z_SYNC_FLUSH=2; + static final int Z_FULL_FLUSH=3; + static final int Z_FINISH=4; + + static final private int Z_DEFLATED=8; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + static final private int METHOD=0; // waiting for method byte + static final private int FLAG=1; // waiting for flag byte + static final private int DICT4=2; // four dictionary check bytes to go + static final private int DICT3=3; // three dictionary check bytes to go + static final private int DICT2=4; // two dictionary check bytes to go + static final private int DICT1=5; // one dictionary check byte to go + static final private int DICT0=6; // waiting for inflateSetDictionary + static final private int BLOCKS=7; // decompressing blocks + static final private int CHECK4=8; // four check bytes to go + static final private int CHECK3=9; // three check bytes to go + static final private int CHECK2=10; // two check bytes to go + static final private int CHECK1=11; // one check byte to go + static final private int DONE=12; // finished check, done + static final private int BAD=13; // got an error--stay here + + static final private int HEAD=14; + static final private int LENGTH=15; + static final private int TIME=16; + static final private int OS=17; + static final private int EXLEN=18; + static final private int EXTRA=19; + static final private int NAME=20; + static final private int COMMENT=21; + static final private int HCRC=22; + static final private int FLAGS=23; + + static final int INFLATE_ANY=0x40000000; + + int mode; // current inflate mode + + // mode dependent information + int method; // if FLAGS, method byte + + // if CHECK, check values to compare + long was = -1; // computed check value + long need; // stream check value + + // if BAD, inflateSync's marker bytes count + int marker; + + // mode independent information + int wrap; // flag for no wrapper + // 0: no wrapper + // 1: zlib header + // 2: gzip header + // 4: auto detection + + int wbits; // log2(window size) (8..15, defaults to 15) + + InfBlocks blocks; // current inflate_blocks state + + private final ZStream z; + + private int flags; + + private int need_bytes = -1; + private byte[] crcbuf=new byte[4]; + + GZIPHeader gheader = null; + + int inflateReset(){ + if(z == null) return Z_STREAM_ERROR; + + z.total_in = z.total_out = 0; + z.msg = null; + this.mode = HEAD; + this.need_bytes = -1; + this.blocks.reset(); + return Z_OK; + } + + int inflateEnd(){ + if(blocks != null){ + blocks.free(); + } + return Z_OK; + } + + Inflate(ZStream z){ + this.z=z; + } + + int inflateInit(int w){ + z.msg = null; + blocks = null; + + // handle undocumented wrap option (no zlib header or check) + wrap = 0; + if(w < 0){ + w = - w; + } + else if((w&INFLATE_ANY) != 0){ + wrap = 4; + w &= ~INFLATE_ANY; + if(w < 48) + w &= 15; + } + else if((w & ~31) != 0) { // for example, DEF_WBITS + 32 + wrap = 4; // zlib and gzip wrapped data should be accepted. + w &= 15; + } + else { + wrap = (w >> 4) + 1; + if(w < 48) + w &= 15; + } + + if(w<8 ||w>15){ + inflateEnd(); + return Z_STREAM_ERROR; + } + if(blocks != null && wbits != w){ + blocks.free(); + blocks=null; + } + + // set window size + wbits=w; + + this.blocks=new InfBlocks(z, 1<<w); + + // reset state + inflateReset(); + + return Z_OK; + } + + int inflate(int f){ + int hold = 0; + + int r; + int b; + + if(z == null || z.next_in == null){ + if(f == Z_FINISH && this.mode==HEAD) + return Z_OK; + return Z_STREAM_ERROR; + } + + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; + r = Z_BUF_ERROR; + while (true){ + + switch (this.mode){ + case HEAD: + if(wrap==0){ + this.mode = BLOCKS; + break; + } + + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + + if((wrap == 4 || (wrap&2)!=0) && + this.need == 0x8b1fL) { // gzip header + if(wrap == 4){ + wrap = 2; + } + z.adler=new CRC32(); + checksum(2, this.need); + + if(gheader==null) + gheader=new GZIPHeader(); + + this.mode = FLAGS; + break; + } + + if((wrap&2) != 0){ + this.mode = BAD; + z.msg = "incorrect header check"; + break; + } + + flags = 0; + + this.method = ((int)this.need)&0xff; + b=((int)(this.need>>8))&0xff; + + if(((wrap&1)==0 || // check if zlib header allowed + (((this.method << 8)+b) % 31)!=0) && + (this.method&0xf)!=Z_DEFLATED){ + if(wrap == 4){ + z.next_in_index -= 2; + z.avail_in += 2; + z.total_in -= 2; + wrap = 0; + this.mode = BLOCKS; + break; + } + this.mode = BAD; + z.msg = "incorrect header check"; + // since zlib 1.2, it is allowted to inflateSync for this case. + /* + this.marker = 5; // can't try inflateSync + */ + break; + } + + if((this.method&0xf)!=Z_DEFLATED){ + this.mode = BAD; + z.msg="unknown compression method"; + // since zlib 1.2, it is allowted to inflateSync for this case. + /* + this.marker = 5; // can't try inflateSync + */ + break; + } + + if(wrap == 4){ + wrap = 1; + } + + if((this.method>>4)+8>this.wbits){ + this.mode = BAD; + z.msg="invalid window size"; + // since zlib 1.2, it is allowted to inflateSync for this case. + /* + this.marker = 5; // can't try inflateSync + */ + break; + } + + z.adler=new Adler32(); + + if((b&PRESET_DICT)==0){ + this.mode = BLOCKS; + break; + } + this.mode = DICT4; + case DICT4: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; + this.mode=DICT3; + case DICT3: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; + this.mode=DICT2; + case DICT2: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; + this.mode=DICT1; + case DICT1: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need += (z.next_in[z.next_in_index++]&0xffL); + z.adler.reset(this.need); + this.mode = DICT0; + return Z_NEED_DICT; + case DICT0: + this.mode = BAD; + z.msg = "need dictionary"; + this.marker = 0; // can try inflateSync + return Z_STREAM_ERROR; + case BLOCKS: + r = this.blocks.proc(r); + if(r == Z_DATA_ERROR){ + this.mode = BAD; + this.marker = 0; // can try inflateSync + break; + } + if(r == Z_OK){ + r = f; + } + if(r != Z_STREAM_END){ + return r; + } + r = f; + this.was=z.adler.getValue(); + this.blocks.reset(); + if(this.wrap==0){ + this.mode=DONE; + break; + } + this.mode=CHECK4; + case CHECK4: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; + this.mode=CHECK3; + case CHECK3: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; + this.mode = CHECK2; + case CHECK2: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; + this.mode = CHECK1; + case CHECK1: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=(z.next_in[z.next_in_index++]&0xffL); + + if(flags!=0){ // gzip + this.need = ((this.need&0xff000000)>>24 | + (this.need&0x00ff0000)>>8 | + (this.need&0x0000ff00)<<8 | + (this.need&0x0000ffff)<<24)&0xffffffffL; + } + + if(((int)(this.was)) != ((int)(this.need))){ + z.msg = "incorrect data check"; + // chack is delayed + /* + this.mode = BAD; + this.marker = 5; // can't try inflateSync + break; + */ + } + else if(flags!=0 && gheader!=null){ + gheader.crc = this.need; + } + + this.mode = LENGTH; + case LENGTH: + if (wrap!=0 && flags!=0) { + + try { r=readBytes(4, r, f); } + catch(Return e){ return e.r; } + + if(z.msg!=null && z.msg.equals("incorrect data check")){ + this.mode = BAD; + this.marker = 5; // can't try inflateSync + break; + } + + if (this.need != (z.total_out & 0xffffffffL)) { + z.msg = "incorrect length check"; + this.mode = BAD; + break; + } + z.msg = null; + } + else { + if(z.msg!=null && z.msg.equals("incorrect data check")){ + this.mode = BAD; + this.marker = 5; // can't try inflateSync + break; + } + } + + this.mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + + case FLAGS: + + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + + flags = ((int)this.need)&0xffff; + + if ((flags & 0xff) != Z_DEFLATED) { + z.msg = "unknown compression method"; + this.mode = BAD; + break; + } + if ((flags & 0xe000)!=0) { + z.msg = "unknown header flags set"; + this.mode = BAD; + break; + } + + if ((flags & 0x0200)!=0){ + checksum(2, this.need); + } + + this.mode = TIME; + + case TIME: + try { r=readBytes(4, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null) + gheader.time = this.need; + if ((flags & 0x0200)!=0){ + checksum(4, this.need); + } + this.mode = OS; + case OS: + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null){ + gheader.xflags = ((int)this.need)&0xff; + gheader.os = (((int)this.need)>>8)&0xff; + } + if ((flags & 0x0200)!=0){ + checksum(2, this.need); + } + this.mode = EXLEN; + case EXLEN: + if ((flags & 0x0400)!=0) { + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null){ + gheader.extra = new byte[((int)this.need)&0xffff]; + } + if ((flags & 0x0200)!=0){ + checksum(2, this.need); + } + } + else if(gheader!=null){ + gheader.extra=null; + } + this.mode = EXTRA; + + case EXTRA: + if ((flags & 0x0400)!=0) { + try { + r=readBytes(r, f); + if(gheader!=null){ + byte[] foo = tmp_string.toByteArray(); + tmp_string=null; + if(foo.length == gheader.extra.length){ + System.arraycopy(foo, 0, gheader.extra, 0, foo.length); + } + else{ + z.msg = "bad extra field length"; + this.mode = BAD; + break; + } + } + } + catch(Return e){ return e.r; } + } + else if(gheader!=null){ + gheader.extra=null; + } + this.mode = NAME; + case NAME: + if ((flags & 0x0800)!=0) { + try { + r=readString(r, f); + if(gheader!=null){ + gheader.name=tmp_string.toByteArray(); + } + tmp_string=null; + } + catch(Return e){ return e.r; } + } + else if(gheader!=null){ + gheader.name=null; + } + this.mode = COMMENT; + case COMMENT: + if ((flags & 0x1000)!=0) { + try { + r=readString(r, f); + if(gheader!=null){ + gheader.comment=tmp_string.toByteArray(); + } + tmp_string=null; + } + catch(Return e){ return e.r; } + } + else if(gheader!=null){ + gheader.comment=null; + } + this.mode = HCRC; + case HCRC: + if ((flags & 0x0200)!=0) { + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null){ + gheader.hcrc=(int)(this.need&0xffff); + } + if(this.need != (z.adler.getValue()&0xffffL)){ + this.mode = BAD; + z.msg = "header crc mismatch"; + this.marker = 5; // can't try inflateSync + break; + } + } + z.adler = new CRC32(); + + this.mode = BLOCKS; + break; + default: + return Z_STREAM_ERROR; + } + } + } + + int inflateSetDictionary(byte[] dictionary, int dictLength){ + if(z==null || (this.mode != DICT0 && this.wrap != 0)){ + return Z_STREAM_ERROR; + } + + int index=0; + int length = dictLength; + + if(this.mode==DICT0){ + long adler_need=z.adler.getValue(); + z.adler.reset(); + z.adler.update(dictionary, 0, dictLength); + if(z.adler.getValue()!=adler_need){ + return Z_DATA_ERROR; + } + } + + z.adler.reset(); + + if(length >= (1<<this.wbits)){ + length = (1<<this.wbits)-1; + index=dictLength - length; + } + this.blocks.set_dictionary(dictionary, index, length); + this.mode = BLOCKS; + return Z_OK; + } + + static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff}; + + int inflateSync(){ + int n; // number of bytes to look at + int p; // pointer to bytes + int m; // number of marker bytes found in a row + long r, w; // temporaries to save total_in and total_out + + // set up + if(z == null) + return Z_STREAM_ERROR; + if(this.mode != BAD){ + this.mode = BAD; + this.marker = 0; + } + if((n=z.avail_in)==0) + return Z_BUF_ERROR; + + p=z.next_in_index; + m=this.marker; + // search + while (n!=0 && m < 4){ + if(z.next_in[p] == mark[m]){ + m++; + } + else if(z.next_in[p]!=0){ + m = 0; + } + else{ + m = 4 - m; + } + p++; n--; + } + + // restore + z.total_in += p-z.next_in_index; + z.next_in_index = p; + z.avail_in = n; + this.marker = m; + + // return no joy or set up to restart on a new block + if(m != 4){ + return Z_DATA_ERROR; + } + r=z.total_in; w=z.total_out; + inflateReset(); + z.total_in=r; z.total_out = w; + this.mode = BLOCKS; + + return Z_OK; + } + + // Returns true if inflate is currently at the end of a block generated + // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + // but removes the length bytes of the resulting empty stored block. When + // decompressing, PPP checks that at the end of input packet, inflate is + // waiting for these length bytes. + int inflateSyncPoint(){ + if(z == null || this.blocks == null) + return Z_STREAM_ERROR; + return this.blocks.sync_point(); + } + + private int readBytes(int n, int r, int f) throws Return{ + if(need_bytes == -1){ + need_bytes=n; + this.need=0; + } + while(need_bytes>0){ + if(z.avail_in==0){ throw new Return(r); }; r=f; + z.avail_in--; z.total_in++; + this.need = this.need | + ((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8)); + need_bytes--; + } + if(n==2){ + this.need&=0xffffL; + } + else if(n==4) { + this.need&=0xffffffffL; + } + need_bytes=-1; + return r; + } + class Return extends Exception{ + int r; + Return(int r){this.r=r; } + } + + private java.io.ByteArrayOutputStream tmp_string = null; + private int readString(int r, int f) throws Return{ + if(tmp_string == null){ + tmp_string=new java.io.ByteArrayOutputStream(); + } + int b=0; + do { + if(z.avail_in==0){ throw new Return(r); }; r=f; + z.avail_in--; z.total_in++; + b = z.next_in[z.next_in_index]; + if(b!=0) tmp_string.write(z.next_in, z.next_in_index, 1); + z.adler.update(z.next_in, z.next_in_index, 1); + z.next_in_index++; + }while(b!=0); + return r; + } + + private int readBytes(int r, int f) throws Return{ + if(tmp_string == null){ + tmp_string=new java.io.ByteArrayOutputStream(); + } + int b=0; + while(this.need>0){ + if(z.avail_in==0){ throw new Return(r); }; r=f; + z.avail_in--; z.total_in++; + b = z.next_in[z.next_in_index]; + tmp_string.write(z.next_in, z.next_in_index, 1); + z.adler.update(z.next_in, z.next_in_index, 1); + z.next_in_index++; + this.need--; + } + return r; + } + + private void checksum(int n, long v){ + for(int i=0; i<n; i++){ + crcbuf[i]=(byte)(v&0xff); + v>>=8; + } + z.adler.update(crcbuf, 0, n); + } + + public GZIPHeader getGZIPHeader(){ + return gheader; + } + + boolean inParsingHeader(){ + switch(mode){ + case HEAD: + case DICT4: + case DICT3: + case DICT2: + case DICT1: + case FLAGS: + case TIME: + case OS: + case EXLEN: + case EXTRA: + case NAME: + case COMMENT: + case HCRC: + return true; + default: + return false; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/Inflater.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,168 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class Inflater extends ZStream{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_WBITS=MAX_WBITS; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + public Inflater() { + super(); + init(); + } + + public Inflater(JZlib.WrapperType wrapperType) throws GZIPException { + this(DEF_WBITS, wrapperType); + } + + public Inflater(int w, JZlib.WrapperType wrapperType) throws GZIPException { + super(); + int ret = init(w, wrapperType); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public Inflater(int w) throws GZIPException { + this(w, false); + } + + public Inflater(boolean nowrap) throws GZIPException { + this(DEF_WBITS, nowrap); + } + + public Inflater(int w, boolean nowrap) throws GZIPException { + super(); + int ret = init(w, nowrap); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + private boolean finished = false; + + public int init(){ + return init(DEF_WBITS); + } + + public int init(JZlib.WrapperType wrapperType){ + return init(DEF_WBITS, wrapperType); + } + + public int init(int w, JZlib.WrapperType wrapperType) { + boolean nowrap = false; + if(wrapperType == JZlib.W_NONE){ + nowrap = true; + } + else if(wrapperType == JZlib.W_GZIP) { + w += 16; + } + else if(wrapperType == JZlib.W_ANY) { + w |= Inflate.INFLATE_ANY; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return init(w, nowrap); + } + + public int init(boolean nowrap){ + return init(DEF_WBITS, nowrap); + } + + public int init(int w){ + return init(w, false); + } + + public int init(int w, boolean nowrap){ + finished = false; + istate=new Inflate(this); + return istate.inflateInit(nowrap?-w:w); + } + + public int inflate(int f){ + if(istate==null) return Z_STREAM_ERROR; + int ret = istate.inflate(f); + if(ret == Z_STREAM_END) + finished = true; + return ret; + } + + public int end(){ + finished = true; + if(istate==null) return Z_STREAM_ERROR; + int ret=istate.inflateEnd(); +// istate = null; + return ret; + } + + public int sync(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSync(); + } + + public int syncPoint(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSyncPoint(); + } + + public int setDictionary(byte[] dictionary, int dictLength){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSetDictionary(dictionary, dictLength); + } + + public boolean finished(){ + return istate.mode==12 /*DONE*/; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/InflaterInputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,247 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +public class InflaterInputStream extends FilterInputStream { + protected final Inflater inflater; + protected byte[] buf; + + private boolean closed = false; + + private boolean eof = false; + + private boolean close_in = true; + + protected static final int DEFAULT_BUFSIZE = 512; + + public InflaterInputStream(InputStream in) throws IOException { + this(in, false); + } + + public InflaterInputStream(InputStream in, boolean nowrap) throws IOException { + this(in, new Inflater(nowrap)); + myinflater = true; + } + + public InflaterInputStream(InputStream in, Inflater inflater) throws IOException { + this(in, inflater, DEFAULT_BUFSIZE); + } + + public InflaterInputStream(InputStream in, + Inflater inflater, int size) throws IOException { + this(in, inflater, size, true); + } + + public InflaterInputStream(InputStream in, + Inflater inflater, + int size, boolean close_in) throws IOException { + super(in); + if (in == null || inflater == null) { + throw new NullPointerException(); + } + else if (size <= 0) { + throw new IllegalArgumentException("buffer size must be greater than 0"); + } + this.inflater = inflater; + buf = new byte[size]; + this.close_in = close_in; + } + + protected boolean myinflater = false; + + private byte[] byte1 = new byte[1]; + + public int read() throws IOException { + if (closed) { throw new IOException("Stream closed"); } + return read(byte1, 0, 1) == -1 ? -1 : byte1[0] & 0xff; + } + + public int read(byte[] b, int off, int len) throws IOException { + if (closed) { throw new IOException("Stream closed"); } + if (b == null) { + throw new NullPointerException(); + } + else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } + else if (len == 0) { + return 0; + } + else if (eof) { + return -1; + } + + int n = 0; + inflater.setOutput(b, off, len); + while(!eof) { + if(inflater.avail_in==0) + fill(); + int err = inflater.inflate(JZlib.Z_NO_FLUSH); + n += inflater.next_out_index - off; + off = inflater.next_out_index; + switch(err) { + case JZlib.Z_DATA_ERROR: + throw new IOException(inflater.msg); + case JZlib.Z_STREAM_END: + case JZlib.Z_NEED_DICT: + eof = true; + if(err == JZlib.Z_NEED_DICT) + return -1; + break; + default: + } + if(inflater.avail_out==0) + break; + } + return n; + } + + public int available() throws IOException { + if (closed) { throw new IOException("Stream closed"); } + if (eof) { + return 0; + } + else { + return 1; + } + } + + private byte[] b = new byte[512]; + + public long skip(long n) throws IOException { + if (n < 0) { + throw new IllegalArgumentException("negative skip length"); + } + + if (closed) { throw new IOException("Stream closed"); } + + int max = (int)Math.min(n, Integer.MAX_VALUE); + int total = 0; + while (total < max) { + int len = max - total; + if (len > b.length) { + len = b.length; + } + len = read(b, 0, len); + if (len == -1) { + eof = true; + break; + } + total += len; + } + return total; + } + + public void close() throws IOException { + if (!closed) { + if (myinflater) + inflater.end(); + if(close_in) + in.close(); + closed = true; + } + } + + protected void fill() throws IOException { + if (closed) { throw new IOException("Stream closed"); } + int len = in.read(buf, 0, buf.length); + if (len == -1) { + if(inflater.istate.wrap == 0 && + !inflater.finished()){ + buf[0]=0; + len=1; + } + else if(inflater.istate.was != -1){ // in reading trailer + throw new IOException("footer is not found"); + } + else{ + throw new EOFException("Unexpected end of ZLIB input stream"); + } + } + inflater.setInput(buf, 0, len, true); + } + + public boolean markSupported() { + return false; + } + + public synchronized void mark(int readlimit) { + } + + public synchronized void reset() throws IOException { + throw new IOException("mark/reset not supported"); + } + + public long getTotalIn() { + return inflater.getTotalIn(); + } + + public long getTotalOut() { + return inflater.getTotalOut(); + } + + public byte[] getAvailIn() { + if(inflater.avail_in<=0) + return null; + byte[] tmp = new byte[inflater.avail_in]; + System.arraycopy(inflater.next_in, inflater.next_in_index, + tmp, 0, inflater.avail_in); + return tmp; + } + + public void readHeader() throws IOException { + + byte[] empty = "".getBytes(); + inflater.setInput(empty, 0, 0, false); + inflater.setOutput(empty, 0, 0); + + int err = inflater.inflate(JZlib.Z_NO_FLUSH); + if(!inflater.istate.inParsingHeader()){ + return; + } + + byte[] b1 = new byte[1]; + do{ + int i = in.read(b1); + if(i<=0) + throw new IOException("no input"); + inflater.setInput(b1); + err = inflater.inflate(JZlib.Z_NO_FLUSH); + if(err!=0/*Z_OK*/) + throw new IOException(inflater.msg); + } + while(inflater.istate.inParsingHeader()); + } + + public Inflater getInflater(){ + return inflater; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/JZlib.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,92 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class JZlib{ + private static final String version="1.1.0"; + public static String version(){return version;} + + static final public int MAX_WBITS=15; // 32K LZ77 window + static final public int DEF_WBITS=MAX_WBITS; + + public enum WrapperType { + NONE, ZLIB, GZIP, ANY + } + + public static final WrapperType W_NONE = WrapperType.NONE; + public static final WrapperType W_ZLIB = WrapperType.ZLIB; + public static final WrapperType W_GZIP = WrapperType.GZIP; + public static final WrapperType W_ANY = WrapperType.ANY; + + // compression levels + static final public int Z_NO_COMPRESSION=0; + static final public int Z_BEST_SPEED=1; + static final public int Z_BEST_COMPRESSION=9; + static final public int Z_DEFAULT_COMPRESSION=(-1); + + // compression strategy + static final public int Z_FILTERED=1; + static final public int Z_HUFFMAN_ONLY=2; + static final public int Z_DEFAULT_STRATEGY=0; + + static final public int Z_NO_FLUSH=0; + static final public int Z_PARTIAL_FLUSH=1; + static final public int Z_SYNC_FLUSH=2; + static final public int Z_FULL_FLUSH=3; + static final public int Z_FINISH=4; + + static final public int Z_OK=0; + static final public int Z_STREAM_END=1; + static final public int Z_NEED_DICT=2; + static final public int Z_ERRNO=-1; + static final public int Z_STREAM_ERROR=-2; + static final public int Z_DATA_ERROR=-3; + static final public int Z_MEM_ERROR=-4; + static final public int Z_BUF_ERROR=-5; + static final public int Z_VERSION_ERROR=-6; + + // The three kinds of block type + static final public byte Z_BINARY = 0; + static final public byte Z_ASCII = 1; + static final public byte Z_UNKNOWN = 2; + + public static long adler32_combine(long adler1, long adler2, long len2){ + return Adler32.combine(adler1, adler2, len2); + } + + public static long crc32_combine(long crc1, long crc2, long len2){ + return CRC32.combine(crc1, crc2, len2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/StaticTree.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,148 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class StaticTree{ + static final private int MAX_BITS=15; + + static final private int BL_CODES=19; + static final private int D_CODES=30; + static final private int LITERALS=256; + static final private int LENGTH_CODES=29; + static final private int L_CODES=(LITERALS+1+LENGTH_CODES); + + // Bit length codes must not exceed MAX_BL_BITS bits + static final int MAX_BL_BITS=7; + + static final short[] static_ltree = { + 12, 8, 140, 8, 76, 8, 204, 8, 44, 8, + 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, + 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, + 252, 8, 2, 8, 130, 8, 66, 8, 194, 8, + 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, + 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, + 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, + 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, + 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, + 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, + 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, + 230, 8, 22, 8, 150, 8, 86, 8, 214, 8, + 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, + 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, + 110, 8, 238, 8, 30, 8, 158, 8, 94, 8, + 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, + 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, + 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, + 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, + 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, + 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, + 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, + 121, 8, 249, 8, 5, 8, 133, 8, 69, 8, + 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, + 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, + 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, + 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, + 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, + 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, + 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, + 211, 9, 467, 9, 51, 9, 307, 9, 179, 9, + 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, + 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, + 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, + 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, + 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, + 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, + 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, + 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, + 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, + 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, + 359, 9, 231, 9, 487, 9, 23, 9, 279, 9, + 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, + 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, + 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, + 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, + 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, + 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, + 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, + 351, 9, 223, 9, 479, 9, 63, 9, 319, 9, + 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, + 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, + 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, + 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, + 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, + 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, + 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, + 163, 8, 99, 8, 227, 8 + }; + + static final short[] static_dtree = { + 0, 5, 16, 5, 8, 5, 24, 5, 4, 5, + 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, + 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, + 30, 5, 1, 5, 17, 5, 9, 5, 25, 5, + 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, + 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 + }; + + static StaticTree static_l_desc = + new StaticTree(static_ltree, Tree.extra_lbits, + LITERALS+1, L_CODES, MAX_BITS); + + static StaticTree static_d_desc = + new StaticTree(static_dtree, Tree.extra_dbits, + 0, D_CODES, MAX_BITS); + + static StaticTree static_bl_desc = + new StaticTree(null, Tree.extra_blbits, + 0, BL_CODES, MAX_BL_BITS); + + short[] static_tree; // static tree or null + int[] extra_bits; // extra bits for each code or null + int extra_base; // base index for extra_bits + int elems; // max number of elements in the tree + int max_length; // max bit length for the codes + + private StaticTree(short[] static_tree, + int[] extra_bits, + int extra_base, + int elems, + int max_length){ + this.static_tree=static_tree; + this.extra_bits=extra_bits; + this.extra_base=extra_base; + this.elems=elems; + this.max_length=max_length; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/Tree.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,367 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class Tree{ + static final private int MAX_BITS=15; + static final private int BL_CODES=19; + static final private int D_CODES=30; + static final private int LITERALS=256; + static final private int LENGTH_CODES=29; + static final private int L_CODES=(LITERALS+1+LENGTH_CODES); + static final private int HEAP_SIZE=(2*L_CODES+1); + + // Bit length codes must not exceed MAX_BL_BITS bits + static final int MAX_BL_BITS=7; + + // end of block literal code + static final int END_BLOCK=256; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + static final int REP_3_6=16; + + // repeat a zero length 3-10 times (3 bits of repeat count) + static final int REPZ_3_10=17; + + // repeat a zero length 11-138 times (7 bits of repeat count) + static final int REPZ_11_138=18; + + // extra bits for each length code + static final int[] extra_lbits={ + 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0 + }; + + // extra bits for each distance code + static final int[] extra_dbits={ + 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 + }; + + // extra bits for each bit length code + static final int[] extra_blbits={ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7 + }; + + static final byte[] bl_order={ + 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; + + + // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit + // length codes. + + static final int Buf_size=8*2; + + // see definition of array dist_code below + static final int DIST_CODE_LEN=512; + + static final byte[] _dist_code = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, + 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 + }; + + static final byte[] _length_code={ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, + 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, + 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 + }; + + static final int[] base_length = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 160, 192, 224, 0 + }; + + static final int[] base_dist = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 + }; + + // Mapping from a distance to a distance code. dist is the distance - 1 and + // must not have side effects. _dist_code[256] and _dist_code[257] are never + // used. + static int d_code(int dist){ + return ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>>7)]); + } + + short[] dyn_tree; // the dynamic tree + int max_code; // largest code with non zero frequency + StaticTree stat_desc; // the corresponding static tree + + // Compute the optimal bit lengths for a tree and update the total bit length + // for the current block. + // IN assertion: the fields freq and dad are set, heap[heap_max] and + // above are the tree nodes sorted by increasing frequency. + // OUT assertions: the field len is set to the optimal bit length, the + // array bl_count contains the frequencies for each bit length. + // The length opt_len is updated; static_len is also updated if stree is + // not null. + void gen_bitlen(Deflate s){ + short[] tree = dyn_tree; + short[] stree = stat_desc.static_tree; + int[] extra = stat_desc.extra_bits; + int base = stat_desc.extra_base; + int max_length = stat_desc.max_length; + int h; // heap index + int n, m; // iterate over the tree elements + int bits; // bit length + int xbits; // extra bits + short f; // frequency + int overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0; + + // In a first pass, compute the optimal bit lengths (which may + // overflow in the case of the bit length tree). + tree[s.heap[s.heap_max]*2+1] = 0; // root of the heap + + for(h=s.heap_max+1; h<HEAP_SIZE; h++){ + n = s.heap[h]; + bits = tree[tree[n*2+1]*2+1] + 1; + if (bits > max_length){ bits = max_length; overflow++; } + tree[n*2+1] = (short)bits; + // We overwrite tree[n*2+1] which is no longer needed + + if (n > max_code) continue; // not a leaf node + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n*2]; + s.opt_len += f * (bits + xbits); + if (stree!=null) s.static_len += f * (stree[n*2+1] + xbits); + } + if (overflow == 0) return; + + // This happens for example on obj2 and pic of the Calgary corpus + // Find the first bit length which could increase: + do { + bits = max_length-1; + while(s.bl_count[bits]==0) bits--; + s.bl_count[bits]--; // move one leaf down the tree + s.bl_count[bits+1]+=2; // move one overflow item as its brother + s.bl_count[max_length]--; + // The brother of the overflow item also moves one step up, + // but this does not affect bl_count[max_length] + overflow -= 2; + } + while (overflow > 0); + + for (bits = max_length; bits != 0; bits--) { + n = s.bl_count[bits]; + while (n != 0) { + m = s.heap[--h]; + if (m > max_code) continue; + if (tree[m*2+1] != bits) { + s.opt_len += ((long)bits - (long)tree[m*2+1])*(long)tree[m*2]; + tree[m*2+1] = (short)bits; + } + n--; + } + } + } + + // Construct one Huffman tree and assigns the code bit strings and lengths. + // Update the total bit length for the current block. + // IN assertion: the field freq is set for all tree elements. + // OUT assertions: the fields len and code are set to the optimal bit length + // and corresponding code. The length opt_len is updated; static_len is + // also updated if stree is not null. The field max_code is set. + void build_tree(Deflate s){ + short[] tree=dyn_tree; + short[] stree=stat_desc.static_tree; + int elems=stat_desc.elems; + int n, m; // iterate over heap elements + int max_code=-1; // largest code with non zero frequency + int node; // new node being created + + // Construct the initial heap, with least frequent element in + // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + // heap[0] is not used. + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for(n=0; n<elems; n++) { + if(tree[n*2] != 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + } + else{ + tree[n*2+1] = 0; + } + } + + // The pkzip format requires that at least one distance code exists, + // and that at least one bit should be sent even if there is only one + // possible code. So to avoid special checks later on we force at least + // two codes of non zero frequency. + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); + tree[node*2] = 1; + s.depth[node] = 0; + s.opt_len--; if (stree!=null) s.static_len -= stree[node*2+1]; + // node is 0 or 1 so it does not have extra bits + } + this.max_code = max_code; + + // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + // establish sub-heaps of increasing lengths: + + for(n=s.heap_len/2;n>=1; n--) + s.pqdownheap(tree, n); + + // Construct the Huffman tree by repeatedly combining the least two + // frequent nodes. + + node=elems; // next internal node of the tree + do{ + // n = node of least frequency + n=s.heap[1]; + s.heap[1]=s.heap[s.heap_len--]; + s.pqdownheap(tree, 1); + m=s.heap[1]; // m = node of next least frequency + + s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency + s.heap[--s.heap_max] = m; + + // Create a new node father of n and m + tree[node*2] = (short)(tree[n*2] + tree[m*2]); + s.depth[node] = (byte)(Math.max(s.depth[n],s.depth[m])+1); + tree[n*2+1] = tree[m*2+1] = (short)node; + + // and insert the new node in the heap + s.heap[1] = node++; + s.pqdownheap(tree, 1); + } + while(s.heap_len>=2); + + s.heap[--s.heap_max] = s.heap[1]; + + // At this point, the fields freq and dad are set. We can now + // generate the bit lengths. + + gen_bitlen(s); + + // The field len is now set, we can generate the bit codes + gen_codes(tree, max_code, s.bl_count, s.next_code); + } + + // Generate the codes for a given tree and bit counts (which need not be + // optimal). + // IN assertion: the array bl_count contains the bit length statistics for + // the given tree and the field len is set for all tree elements. + // OUT assertion: the field code is set for all tree elements of non + // zero code length. + private final static void gen_codes( + short[] tree, // the tree to decorate + int max_code, // largest code with non zero frequency + short[] bl_count, // number of codes at each bit length + short[] next_code){ + short code = 0; // running code value + int bits; // bit index + int n; // code index + + // The distribution counts are first used to generate the code values + // without bit reversal. + next_code[0]=0; + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (short)((code + bl_count[bits-1]) << 1); + } + + // Check that the bit counts in bl_count are consistent. The last code + // must be all ones. + //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, + // "inconsistent bit counts"); + //Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n*2+1]; + if (len == 0) continue; + // Now reverse the bits + tree[n*2] = (short)(bi_reverse(next_code[len]++, len)); + } + } + + // Reverse the first len bits of a code, using straightforward code (a faster + // method would use a table) + // IN assertion: 1 <= len <= 15 + private final static int bi_reverse( + int code, // the value to invert + int len // its bit length + ){ + int res = 0; + do{ + res|=code&1; + code>>>=1; + res<<=1; + } + while(--len>0); + return res>>>1; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/ZInputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,126 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +/** + * ZInputStream + * + * @deprecated use DeflaterOutputStream or InflaterInputStream + */ +@Deprecated +public class ZInputStream extends FilterInputStream { + + protected int flush=JZlib.Z_NO_FLUSH; + protected boolean compress; + protected InputStream in=null; + + protected Deflater deflater; + protected InflaterInputStream iis; + + public ZInputStream(InputStream in) throws IOException { + this(in, false); + } + public ZInputStream(InputStream in, boolean nowrap) throws IOException { + super(in); + iis = new InflaterInputStream(in, nowrap); + compress=false; + } + + public ZInputStream(InputStream in, int level) throws IOException { + super(in); + this.in=in; + deflater = new Deflater(); + deflater.init(level); + compress=true; + } + + private byte[] buf1 = new byte[1]; + public int read() throws IOException { + if(read(buf1, 0, 1)==-1) return -1; + return(buf1[0]&0xFF); + } + + private byte[] buf = new byte[512]; + + public int read(byte[] b, int off, int len) throws IOException { + if(compress){ + deflater.setOutput(b, off, len); + while(true){ + int datalen = in.read(buf, 0, buf.length); + if(datalen == -1) return -1; + deflater.setInput(buf, 0, datalen, true); + int err = deflater.deflate(flush); + if(deflater.next_out_index>0) + return deflater.next_out_index; + if(err == JZlib.Z_STREAM_END) + return 0; + if(err == JZlib.Z_STREAM_ERROR || + err == JZlib.Z_DATA_ERROR){ + throw new ZStreamException("deflating: "+deflater.msg); + } + } + } + else{ + return iis.read(b, off, len); + } + } + + public long skip(long n) throws IOException { + int len=512; + if(n<len) + len=(int)n; + byte[] tmp=new byte[len]; + return((long)read(tmp)); + } + + public int getFlushMode() { + return flush; + } + + public void setFlushMode(int flush) { + this.flush=flush; + } + + public long getTotalIn() { + if(compress) return deflater.total_in; + else return iis.getTotalIn(); + } + + public long getTotalOut() { + if(compress) return deflater.total_out; + else return iis.getTotalOut(); + } + + public void close() throws IOException{ + if(compress) deflater.end(); + else iis.close(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/ZOutputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,159 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +/** + * ZOutputStream + * + * @deprecated use DeflaterOutputStream or InflaterInputStream + */ +@Deprecated +public class ZOutputStream extends FilterOutputStream { + + protected int bufsize=512; + protected int flush=JZlib.Z_NO_FLUSH; + protected byte[] buf=new byte[bufsize]; + protected boolean compress; + + protected OutputStream out; + private boolean end=false; + + private DeflaterOutputStream dos; + private Inflater inflater; + + public ZOutputStream(OutputStream out) throws IOException { + super(out); + this.out=out; + inflater = new Inflater(); + inflater.init(); + compress=false; + } + + public ZOutputStream(OutputStream out, int level) throws IOException { + this(out, level, false); + } + + public ZOutputStream(OutputStream out, int level, boolean nowrap) throws IOException { + super(out); + this.out=out; + Deflater deflater = new Deflater(level, nowrap); + dos = new DeflaterOutputStream(out, deflater); + compress=true; + } + + private byte[] buf1 = new byte[1]; + public void write(int b) throws IOException { + buf1[0]=(byte)b; + write(buf1, 0, 1); + } + + public void write(byte b[], int off, int len) throws IOException { + if(len==0) return; + if(compress){ + dos.write(b, off, len); + } + else { + inflater.setInput(b, off, len, true); + int err = JZlib.Z_OK; + while(inflater.avail_in>0){ + inflater.setOutput(buf, 0, buf.length); + err = inflater.inflate(flush); + if(inflater.next_out_index>0) + out.write(buf, 0, inflater.next_out_index); + if(err != JZlib.Z_OK) + break; + } + if(err != JZlib.Z_OK) + throw new ZStreamException("inflating: "+inflater.msg); + return; + } + } + + public int getFlushMode() { + return flush; + } + + public void setFlushMode(int flush) { + this.flush=flush; + } + + public void finish() throws IOException { + int err; + if(compress){ + int tmp = flush; + int flush = JZlib.Z_FINISH; + try{ + write("".getBytes(), 0, 0); + } + finally { flush = tmp; } + } + else{ + dos.finish(); + } + flush(); + } + public synchronized void end() { + if(end) return; + if(compress){ + try { dos.finish(); } catch(Exception e){} + } + else{ + inflater.end(); + } + end=true; + } + public void close() throws IOException { + try{ + try{finish();} + catch (IOException ignored) {} + } + finally{ + end(); + out.close(); + out=null; + } + } + + public long getTotalIn() { + if(compress) return dos.getTotalIn(); + else return inflater.total_in; + } + + public long getTotalOut() { + if(compress) return dos.getTotalOut(); + else return inflater.total_out; + } + + public void flush() throws IOException { + out.flush(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/ZStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,377 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +/** + * ZStream + * + * @deprecated Not for public use in the future. + */ +@Deprecated +public class ZStream{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_WBITS=MAX_WBITS; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + public byte[] next_in; // next input byte + public int next_in_index; + public int avail_in; // number of bytes available at next_in + public long total_in; // total nb of input bytes read so far + + public byte[] next_out; // next output byte should be put there + public int next_out_index; + public int avail_out; // remaining free space at next_out + public long total_out; // total nb of bytes output so far + + public String msg; + + Deflate dstate; + Inflate istate; + + int data_type; // best guess about the data type: ascii or binary + + Checksum adler; + + public ZStream(){ + this(new Adler32()); + } + + public ZStream(Checksum adler){ + this.adler=adler; + } + + public int inflateInit(){ + return inflateInit(DEF_WBITS); + } + public int inflateInit(boolean nowrap){ + return inflateInit(DEF_WBITS, nowrap); + } + public int inflateInit(int w){ + return inflateInit(w, false); + } + public int inflateInit(JZlib.WrapperType wrapperType) { + return inflateInit(DEF_WBITS, wrapperType); + } + public int inflateInit(int w, JZlib.WrapperType wrapperType) { + boolean nowrap = false; + if(wrapperType == JZlib.W_NONE){ + nowrap = true; + } + else if(wrapperType == JZlib.W_GZIP) { + w += 16; + } + else if(wrapperType == JZlib.W_ANY) { + w |= Inflate.INFLATE_ANY; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return inflateInit(w, nowrap); + } + public int inflateInit(int w, boolean nowrap){ + istate=new Inflate(this); + return istate.inflateInit(nowrap?-w:w); + } + + public int inflate(int f){ + if(istate==null) return Z_STREAM_ERROR; + return istate.inflate(f); + } + public int inflateEnd(){ + if(istate==null) return Z_STREAM_ERROR; + int ret=istate.inflateEnd(); +// istate = null; + return ret; + } + public int inflateSync(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSync(); + } + public int inflateSyncPoint(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSyncPoint(); + } + public int inflateSetDictionary(byte[] dictionary, int dictLength){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSetDictionary(dictionary, dictLength); + } + public boolean inflateFinished(){ + return istate.mode==12 /*DONE*/; + } + + public int deflateInit(int level){ + return deflateInit(level, MAX_WBITS); + } + public int deflateInit(int level, boolean nowrap){ + return deflateInit(level, MAX_WBITS, nowrap); + } + public int deflateInit(int level, int bits){ + return deflateInit(level, bits, false); + } + public int deflateInit(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){ + if(bits < 9 || bits > 15){ + return Z_STREAM_ERROR; + } + if(wrapperType == JZlib.W_NONE) { + bits *= -1; + } + else if(wrapperType == JZlib.W_GZIP) { + bits += 16; + } + else if(wrapperType == JZlib.W_ANY) { + return Z_STREAM_ERROR; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return this.deflateInit(level, bits, memlevel); + } + public int deflateInit(int level, int bits, int memlevel){ + dstate=new Deflate(this); + return dstate.deflateInit(level, bits, memlevel); + } + public int deflateInit(int level, int bits, boolean nowrap){ + dstate=new Deflate(this); + return dstate.deflateInit(level, nowrap?-bits:bits); + } + public int deflate(int flush){ + if(dstate==null){ + return Z_STREAM_ERROR; + } + return dstate.deflate(flush); + } + public int deflateEnd(){ + if(dstate==null) return Z_STREAM_ERROR; + int ret=dstate.deflateEnd(); + dstate=null; + return ret; + } + public int deflateParams(int level, int strategy){ + if(dstate==null) return Z_STREAM_ERROR; + return dstate.deflateParams(level, strategy); + } + public int deflateSetDictionary (byte[] dictionary, int dictLength){ + if(dstate == null) + return Z_STREAM_ERROR; + return dstate.deflateSetDictionary(dictionary, dictLength); + } + + // Flush as much pending output as possible. All deflate() output goes + // through this function so some applications may wish to modify it + // to avoid allocating a large strm->next_out buffer and copying into it. + // (See also read_buf()). + void flush_pending(){ + int len=dstate.pending; + + if(len>avail_out) len=avail_out; + if(len==0) return; + + if(dstate.pending_buf.length<=dstate.pending_out || + next_out.length<=next_out_index || + dstate.pending_buf.length<(dstate.pending_out+len) || + next_out.length<(next_out_index+len)){ + //System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+ + // ", "+next_out.length+", "+next_out_index+", "+len); + //System.out.println("avail_out="+avail_out); + } + + System.arraycopy(dstate.pending_buf, dstate.pending_out, + next_out, next_out_index, len); + + next_out_index+=len; + dstate.pending_out+=len; + total_out+=len; + avail_out-=len; + dstate.pending-=len; + if(dstate.pending==0){ + dstate.pending_out=0; + } + } + + // Read a new buffer from the current input stream, update the adler32 + // and total number of bytes read. All deflate() input goes through + // this function so some applications may wish to modify it to avoid + // allocating a large strm->next_in buffer and copying from it. + // (See also flush_pending()). + int read_buf(byte[] buf, int start, int size) { + int len=avail_in; + + if(len>size) len=size; + if(len==0) return 0; + + avail_in-=len; + + if(dstate.wrap!=0) { + adler.update(next_in, next_in_index, len); + } + System.arraycopy(next_in, next_in_index, buf, start, len); + next_in_index += len; + total_in += len; + return len; + } + + public long getAdler(){ + return adler.getValue(); + } + + public void free(){ + next_in=null; + next_out=null; + msg=null; + } + + public void setOutput(byte[] buf){ + setOutput(buf, 0, buf.length); + } + + public void setOutput(byte[] buf, int off, int len){ + next_out = buf; + next_out_index = off; + avail_out = len; + } + + public void setInput(byte[] buf){ + setInput(buf, 0, buf.length, false); + } + + public void setInput(byte[] buf, boolean append){ + setInput(buf, 0, buf.length, append); + } + + public void setInput(byte[] buf, int off, int len, boolean append){ + if(len<=0 && append && next_in!=null) return; + + if(avail_in>0 && append){ + byte[] tmp = new byte[avail_in+len]; + System.arraycopy(next_in, next_in_index, tmp, 0, avail_in); + System.arraycopy(buf, off, tmp, avail_in, len); + next_in=tmp; + next_in_index=0; + avail_in+=len; + } + else{ + next_in=buf; + next_in_index=off; + avail_in=len; + } + } + + public byte[] getNextIn(){ + return next_in; + } + + public void setNextIn(byte[] next_in){ + this.next_in = next_in; + } + + public int getNextInIndex(){ + return next_in_index; + } + + public void setNextInIndex(int next_in_index){ + this.next_in_index = next_in_index; + } + + public int getAvailIn(){ + return avail_in; + } + + public void setAvailIn(int avail_in){ + this.avail_in = avail_in; + } + + public byte[] getNextOut(){ + return next_out; + } + + public void setNextOut(byte[] next_out){ + this.next_out = next_out; + } + + public int getNextOutIndex(){ + return next_out_index; + } + + public void setNextOutIndex(int next_out_index){ + this.next_out_index = next_out_index; + } + + public int getAvailOut(){ + return avail_out; + + } + + public void setAvailOut(int avail_out){ + this.avail_out = avail_out; + } + + public long getTotalOut(){ + return total_out; + } + + public long getTotalIn(){ + return total_in; + } + + public String getMessage(){ + return msg; + } + + /** + * Those methods are expected to be override by Inflater and Deflater. + * In the future, they will become abstract methods. + */ + public int end(){ return Z_OK; } + public boolean finished(){ return false; } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/jcraft/jzlib/ZStreamException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,44 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +public class ZStreamException extends java.io.IOException { + public ZStreamException() { + super(); + } + public ZStreamException(String s) { + super(s); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/lamerman/FileDialog.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,292 @@ +package com.lamerman; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.TreeMap; + +import com.five_ten_sg.connectbot.R; +import android.app.AlertDialog; +import android.app.ListActivity; +import android.content.DialogInterface; +import android.net.Uri; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.TextView; + +public class FileDialog extends ListActivity { + + private static final String ITEM_KEY = "key"; + private static final String ITEM_IMAGE = "image"; + private static final String ROOT = "/"; + + public static final String START_PATH = "START_PATH"; + public static final String RESULT_PATH = "RESULT_PATH"; + public static final String SELECTION_MODE = "SELECTION_MODE"; + public static final String TITLE = "TITLE"; + + private List<String> path = null; + private TextView myPath; + private EditText mFileName; + private ArrayList<HashMap<String, Object>> mList; + + private Button selectButton; + + private LinearLayout layoutSelect; + private LinearLayout layoutCreate; + private InputMethodManager inputManager; + private String parentPath; + private String currentPath = ROOT; + + private int selectionMode = SelectionMode.MODE_CREATE; + + private File selectedFile; + private HashMap<String, Integer> lastPositions = new HashMap<String, Integer>(); + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setResult(RESULT_CANCELED, getIntent()); + setContentView(R.layout.file_dialog_main); + this.setTitle(String.format("%s: %s", + getResources().getText(R.string.app_name), + getIntent().getStringExtra(TITLE))); + myPath = (TextView) findViewById(R.id.path); + mFileName = (EditText) findViewById(R.id.fdEditTextFile); + inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + selectButton = (Button) findViewById(R.id.fdButtonSelect); + selectButton.setEnabled(false); + selectButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + if (selectedFile != null) { + getIntent().setData(Uri.fromFile(selectedFile)); + setResult(RESULT_OK, getIntent()); + finish(); + } + } + }); + final Button newButton = (Button) findViewById(R.id.fdButtonNew); + newButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + setCreateVisible(v); + mFileName.setText(""); + mFileName.requestFocus(); + } + }); + final Button cancelButton = (Button) findViewById(R.id.fdButtonCancel); + cancelButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + setResult(RESULT_CANCELED, getIntent()); + finish(); + } + }); + selectionMode = getIntent().getIntExtra(SELECTION_MODE, + SelectionMode.MODE_CREATE); + + if (selectionMode == SelectionMode.MODE_OPEN) { + newButton.setEnabled(false); + } + + layoutSelect = (LinearLayout) findViewById(R.id.fdLinearLayoutSelect); + layoutCreate = (LinearLayout) findViewById(R.id.fdLinearLayoutCreate); + layoutCreate.setVisibility(View.GONE); + final Button cancelCreateButton = (Button) findViewById(R.id.fdButtonCancelCreate); + cancelCreateButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + setSelectVisible(v); + } + }); + final Button createButton = (Button) findViewById(R.id.fdButtonCreate); + createButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + if (mFileName.getText().length() > 0) { + getIntent().putExtra(RESULT_PATH, + currentPath + "/" + mFileName.getText()); + setResult(RESULT_OK, getIntent()); + finish(); + } + } + }); + String startPath = getIntent().getStringExtra(START_PATH); + + if (startPath != null) { + getDir(startPath); + } + else { + getDir(ROOT); + } + } + + @Override + protected void onPause() { + String myPathStr = myPath.getText().toString(); + int idx = myPathStr.lastIndexOf(':'); + String currPath = myPathStr.substring(idx + 2); + getIntent().putExtra(START_PATH, currPath); + super.onPause(); + } + + private void getDir(String dirPath) { + boolean useAutoSelection = dirPath.length() < currentPath.length(); + Integer position = lastPositions.get(parentPath); + getDirImpl(dirPath); + + if (position != null && useAutoSelection) { + getListView().setSelection(position); + } + } + + private void getDirImpl(final String dirPath) { + currentPath = dirPath; + final List<String> item = new ArrayList<String>(); + path = new ArrayList<String>(); + mList = new ArrayList<HashMap<String, Object>>(); + File f = new File(currentPath); + File[] files = f.listFiles(); + + if (files == null) { + currentPath = ROOT; + f = new File(currentPath); + files = f.listFiles(); + } + + myPath.setText(getText(R.string.location) + ": " + currentPath); + + if (!currentPath.equals(ROOT)) { + item.add(ROOT); + addItem(ROOT, R.drawable.folder); + path.add(ROOT); + item.add("../"); + addItem("../", R.drawable.folder); + path.add(f.getParent()); + parentPath = f.getParent(); + } + + TreeMap<String, String> dirsMap = new TreeMap<String, String>(); + TreeMap<String, String> dirsPathMap = new TreeMap<String, String>(); + TreeMap<String, String> filesMap = new TreeMap<String, String>(); + TreeMap<String, String> filesPathMap = new TreeMap<String, String>(); + + for (File file : files) { + if (file.isDirectory()) { + String dirName = file.getName(); + dirsMap.put(dirName, dirName); + dirsPathMap.put(dirName, file.getPath()); + } + else { + filesMap.put(file.getName(), file.getName()); + filesPathMap.put(file.getName(), file.getPath()); + } + } + + item.addAll(dirsMap.tailMap("").values()); + item.addAll(filesMap.tailMap("").values()); + path.addAll(dirsPathMap.tailMap("").values()); + path.addAll(filesPathMap.tailMap("").values()); + SimpleAdapter fileList = new SimpleAdapter(this, mList, + R.layout.file_dialog_row, + new String[] { ITEM_KEY, ITEM_IMAGE }, new int[] { + R.id.fdrowtext, R.id.fdrowimage + }); + + for (String dir : dirsMap.tailMap("").values()) { + addItem(dir, R.drawable.folder); + } + + for (String file : filesMap.tailMap("").values()) { + addItem(file, R.drawable.file); + } + + fileList.notifyDataSetChanged(); + setListAdapter(fileList); + } + + private void addItem(String fileName, int imageId) { + HashMap<String, Object> item = new HashMap<String, Object>(); + item.put(ITEM_KEY, fileName); + item.put(ITEM_IMAGE, imageId); + mList.add(item); + } + + @Override + protected void onListItemClick(ListView l, View v, int position, long id) { + File file = new File(path.get(position)); + setSelectVisible(v); + + if (file.isDirectory()) { + selectButton.setEnabled(false); + + if (file.canRead()) { + lastPositions.put(currentPath, position); + getDir(path.get(position)); + } + else { + new AlertDialog.Builder(this) + .setIcon(R.drawable.icon) + .setTitle( + "[" + file.getName() + "] " + + getText(R.string.cant_read_folder)) + .setPositiveButton("OK", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + } + }).show(); + } + } + else { + selectedFile = file; + v.setSelected(true); + selectButton.setEnabled(true); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if ((keyCode == KeyEvent.KEYCODE_BACK)) { + selectButton.setEnabled(false); + + if (layoutCreate.getVisibility() == View.VISIBLE) { + layoutCreate.setVisibility(View.GONE); + layoutSelect.setVisibility(View.VISIBLE); + } + else { + if (!currentPath.equals(ROOT)) { + getDir(parentPath); + } + else { + return super.onKeyDown(keyCode, event); + } + } + + return true; + } + else { + return super.onKeyDown(keyCode, event); + } + } + + private void setCreateVisible(View v) { + layoutCreate.setVisibility(View.VISIBLE); + layoutSelect.setVisibility(View.GONE); + inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); + selectButton.setEnabled(false); + } + + private void setSelectVisible(View v) { + layoutCreate.setVisibility(View.GONE); + layoutSelect.setVisibility(View.VISIBLE); + inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); + selectButton.setEnabled(false); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/lamerman/SelectionMode.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,7 @@ +package com.lamerman; + +public class SelectionMode { + public static final int MODE_CREATE = 0; + + public static final int MODE_OPEN = 1; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/madgag/ssh/android/authagent/AndroidAuthAgent.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,120 @@ +/* + * This file is auto-generated. DO NOT MODIFY. + * Original file: /home/roberto/development/madgag-ssh/ssh-android/src/main/java/com/madgag/ssh/android/authagent/AndroidAuthAgent.aidl + */ +package com.madgag.ssh.android.authagent; +public interface AndroidAuthAgent extends android.os.IInterface { + /** Local-side IPC implementation stub class. */ + public static abstract class Stub extends android.os.Binder implements com.madgag.ssh.android.authagent.AndroidAuthAgent { + private static final java.lang.String DESCRIPTOR = "com.madgag.ssh.android.authagent.AndroidAuthAgent"; + /** Construct the stub at attach it to the interface. */ + public Stub() { + this.attachInterface(this, DESCRIPTOR); + } + /** + * Cast an IBinder object into an com.madgag.ssh.android.authagent.AndroidAuthAgent interface, + * generating a proxy if needed. + */ + public static com.madgag.ssh.android.authagent.AndroidAuthAgent asInterface(android.os.IBinder obj) { + if ((obj == null)) { + return null; + } + + android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR); + + if (((iin != null) && (iin instanceof com.madgag.ssh.android.authagent.AndroidAuthAgent))) { + return ((com.madgag.ssh.android.authagent.AndroidAuthAgent)iin); + } + + return new com.madgag.ssh.android.authagent.AndroidAuthAgent.Stub.Proxy(obj); + } + public android.os.IBinder asBinder() { + return this; + } + @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { + switch (code) { + case INTERFACE_TRANSACTION: { + reply.writeString(DESCRIPTOR); + return true; + } + + case TRANSACTION_getIdentities: { + data.enforceInterface(DESCRIPTOR); + java.util.Map _result = this.getIdentities(); + reply.writeNoException(); + reply.writeMap(_result); + return true; + } + + case TRANSACTION_sign: { + data.enforceInterface(DESCRIPTOR); + byte[] _arg0; + _arg0 = data.createByteArray(); + byte[] _arg1; + _arg1 = data.createByteArray(); + byte[] _result = this.sign(_arg0, _arg1); + reply.writeNoException(); + reply.writeByteArray(_result); + return true; + } + } + + return super.onTransact(code, data, reply, flags); + } + private static class Proxy implements com.madgag.ssh.android.authagent.AndroidAuthAgent { + private android.os.IBinder mRemote; + Proxy(android.os.IBinder remote) { + mRemote = remote; + } + public android.os.IBinder asBinder() { + return mRemote; + } + public java.lang.String getInterfaceDescriptor() { + return DESCRIPTOR; + } + public java.util.Map getIdentities() throws android.os.RemoteException { + android.os.Parcel _data = android.os.Parcel.obtain(); + android.os.Parcel _reply = android.os.Parcel.obtain(); + java.util.Map _result; + + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_getIdentities, _data, _reply, 0); + _reply.readException(); + java.lang.ClassLoader cl = (java.lang.ClassLoader)this.getClass().getClassLoader(); + _result = _reply.readHashMap(cl); + } + finally { + _reply.recycle(); + _data.recycle(); + } + + return _result; + } + public byte[] sign(byte[] publicKey, byte[] data) throws android.os.RemoteException { + android.os.Parcel _data = android.os.Parcel.obtain(); + android.os.Parcel _reply = android.os.Parcel.obtain(); + byte[] _result; + + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeByteArray(publicKey); + _data.writeByteArray(data); + mRemote.transact(Stub.TRANSACTION_sign, _data, _reply, 0); + _reply.readException(); + _result = _reply.createByteArray(); + } + finally { + _reply.recycle(); + _data.recycle(); + } + + return _result; + } + } + static final int TRANSACTION_getIdentities = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); + static final int TRANSACTION_sign = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); + } + public java.util.Map getIdentities() throws android.os.RemoteException; + public byte[] sign(byte[] publicKey, byte[] data) throws android.os.RemoteException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/de/mud/telnet/TelnetProtocolHandler.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,789 @@ +/* + * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". + * + * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved. + * + * Please visit http://javatelnet.org/ for updates and contact. + * + * --LICENSE NOTICE-- + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --LICENSE NOTICE-- + * + */ + +package de.mud.telnet; + +import java.io.IOException; +/** + * This is a telnet protocol handler. The handler needs implementations + * for several methods to handle the telnet options and to be able to + * read and write the buffer. + * <P> + * <B>Maintainer:</B> Marcus Meissner + * + * @version $Id: TelnetProtocolHandler.java 503 2005-10-24 07:34:13Z marcus $ + * @author Matthias L. Jugel, Marcus Meissner + */ +public abstract class TelnetProtocolHandler { + /** contains the current revision id */ + public final static String ID = "$Id: TelnetProtocolHandler.java 503 2005-10-24 07:34:13Z marcus $"; + + /** debug level */ + private final static int debug = 0; + + /** temporary buffer for data-telnetstuff-data transformation */ + private byte[] tempbuf = new byte[0]; + + /** the data sent on pressing <RETURN> \n */ + private byte[] crlf = new byte[2]; + /** the data sent on pressing <LineFeed> \r */ + private byte[] cr = new byte[2]; + + /** + * Create a new telnet protocol handler. + */ + public TelnetProtocolHandler() { + reset(); + crlf[0] = 13; crlf[1] = 10; + cr[0] = 13; cr[1] = 0; + } + + /** + * Get the current terminal type for TTYPE telnet option. + * @return the string id of the terminal + */ + protected abstract String getTerminalType(); + + /** + * Get the current window size of the terminal for the + * NAWS telnet option. + * @return the size of the terminal as Dimension + */ + protected abstract int[] getWindowSize(); + + /** + * Set the local echo option of telnet. + * @param echo true for local echo, false for no local echo + */ + protected abstract void setLocalEcho(boolean echo); + + /** + * Generate an EOR (end of record) request. For use by prompt displaying. + */ + protected abstract void notifyEndOfRecord(); + + /** + * Send data to the remote host. + * @param b array of bytes to send + */ + protected abstract void write(byte[] b) throws IOException; + + /** + * Read the charset name from terminal. + */ + protected abstract String getCharsetName(); + + /** + * Send one byte to the remote host. + * @param b the byte to be sent + * @see #write(byte[] b) + */ + private static byte[] one = new byte[1]; + private void write(byte b) throws IOException { + one[0] = b; + write(one); + } + + /** + * Reset the protocol handler. This may be necessary after the + * connection was closed or some other problem occured. + */ + public void reset() { + neg_state = 0; + receivedDX = new byte[256]; + sentDX = new byte[256]; + receivedWX = new byte[256]; + sentWX = new byte[256]; + } + + // =================================================================== + // the actual negotiation handling for the telnet protocol follows: + // =================================================================== + + /** state variable for telnet negotiation reader */ + private byte neg_state = 0; + + /** constants for the negotiation state */ + private final static byte STATE_DATA = 0; + private final static byte STATE_IAC = 1; + private final static byte STATE_IACSB = 2; + private final static byte STATE_IACWILL = 3; + private final static byte STATE_IACDO = 4; + private final static byte STATE_IACWONT = 5; + private final static byte STATE_IACDONT = 6; + private final static byte STATE_IACSBIAC = 7; + private final static byte STATE_IACSBDATA = 8; + private final static byte STATE_IACSBDATAIAC = 9; + + /** What IAC SB <xx> we are handling right now */ + private byte current_sb; + + /** current SB negotiation buffer */ + private byte[] sbbuf; + + /** IAC - init sequence for telnet negotiation. */ + private final static byte IAC = (byte)255; + /** [IAC] End Of Record */ + private final static byte EOR = (byte)239; + /** [IAC] WILL */ + private final static byte WILL = (byte)251; + /** [IAC] WONT */ + private final static byte WONT = (byte)252; + /** [IAC] DO */ + private final static byte DO = (byte)253; + /** [IAC] DONT */ + private final static byte DONT = (byte)254; + /** [IAC] Sub Begin */ + private final static byte SB = (byte)250; + /** [IAC] Sub End */ + private final static byte SE = (byte)240; + /** Telnet option: binary mode */ + private final static byte TELOPT_BINARY = (byte)0; /* binary mode */ + /** Telnet option: echo text */ + private final static byte TELOPT_ECHO = (byte)1; /* echo on/off */ + /** Telnet option: sga */ + private final static byte TELOPT_SGA = (byte)3; /* supress go ahead */ + /** Telnet option: End Of Record */ + private final static byte TELOPT_EOR = (byte)25; /* end of record */ + /** Telnet option: Negotiate About Window Size */ + private final static byte TELOPT_NAWS = (byte)31; /* NA-WindowSize*/ + /** Telnet option: Terminal Type */ + private final static byte TELOPT_TTYPE = (byte)24; /* terminal type */ + /** Telnet option: CHARSET */ + private final static byte TELOPT_CHARSET = (byte)42; /* charset */ + + private final static byte[] IACWILL = { IAC, WILL }; + private final static byte[] IACWONT = { IAC, WONT }; + private final static byte[] IACDO = { IAC, DO }; + private final static byte[] IACDONT = { IAC, DONT }; + private final static byte[] IACSB = { IAC, SB }; + private final static byte[] IACSE = { IAC, SE }; + + private final static byte CHARSET_ACCEPTED = (byte)2; + private final static byte CHARSET_REJECTED = (byte)3; + + /** Telnet option qualifier 'IS' */ + private final static byte TELQUAL_IS = (byte)0; + /** Telnet option qualifier 'SEND' */ + private final static byte TELQUAL_SEND = (byte)1; + + /** What IAC DO(NT) request do we have received already ? */ + private byte[] receivedDX; + /** What IAC WILL/WONT request do we have received already ? */ + private byte[] receivedWX; + /** What IAC DO/DONT request do we have sent already ? */ + private byte[] sentDX; + /** What IAC WILL/WONT request do we have sent already ? */ + private byte[] sentWX; + + /** + * Send a Telnet Escape character (IAC <code>) + */ + public void sendTelnetControl(byte code) + throws IOException { + byte[] b = new byte[2]; + b[0] = IAC; + b[1] = code; + write(b); + } + + /** + * Send the new Window Size (via NAWS) + */ + public void setWindowSize(int columns, int rows) + throws IOException { + if (debug > 2) System.err.println("sending NAWS"); + + if (receivedDX[TELOPT_NAWS] != DO) { + System.err.println("not allowed to send NAWS? (DONT NAWS)"); + return; + } + + write(IAC); write(SB); write(TELOPT_NAWS); + write((byte)(columns >> 8)); + write((byte)(columns & 0xff)); + write((byte)(rows >> 8)); + write((byte)(rows & 0xff)); + write(IAC); write(SE); + } + + + /** + * Handle an incoming IAC SB <type> <bytes> IAC SE + * @param type type of SB + * @param sbata byte array as <bytes> + */ + private void handle_sb(byte type, byte[] sbdata) + throws IOException { + if (debug > 1) + System.err.println("TelnetIO.handle_sb(" + type + ")"); + + switch (type) { + case TELOPT_TTYPE: + if (sbdata.length > 0 && sbdata[0] == TELQUAL_SEND) { + write(IACSB); write(TELOPT_TTYPE); write(TELQUAL_IS); + /* FIXME: need more logic here if we use + * more than one terminal type + */ + String ttype = getTerminalType(); + + if (ttype == null) ttype = "dumb"; + + write(ttype.getBytes()); + write(IACSE); + } + + break; + + case TELOPT_CHARSET: + System.out.println("Got SB CHARSET"); + String charsetStr = new String(sbdata, "US-ASCII"); + + if (charsetStr.startsWith("TTABLE ")) { + charsetStr = charsetStr.substring(7); + } + + String[] charsets = charsetStr.split(charsetStr.substring(0, 0)); + String myCharset = getCharsetName(); + + for (String charset : charsets) { + if (charset.equals(myCharset)) { + write(IACSB); write(TELOPT_CHARSET); write(CHARSET_ACCEPTED); + write(charset.getBytes()); + write(IACSE); + System.out.println("Sent our charset!"); + return; + } + } + + write(IACSB); write(TELOPT_CHARSET); write(CHARSET_REJECTED); + write(IACSE); + break; + } + } + + /** + * Do not send any notifications at startup. We do not know, + * whether the remote client understands telnet protocol handling, + * so we are silent. + * (This used to send IAC WILL SGA, but this is false for a compliant + * client.) + */ + public void startup() throws IOException { + } + /** + * Transpose special telnet codes like 0xff or newlines to values + * that are compliant to the protocol. This method will also send + * the buffer immediately after transposing the data. + * @param buf the data buffer to be sent + */ + public void transpose(byte[] buf) throws IOException { + int i; + byte[] nbuf, xbuf; + int nbufptr = 0; + nbuf = new byte[buf.length * 2]; // FIXME: buffer overflows possible + + for (i = 0; i < buf.length ; i++) { + switch (buf[i]) { + // Escape IAC twice in stream ... to be telnet protocol compliant + // this is there in binary and non-binary mode. + case IAC: + nbuf[nbufptr++] = IAC; + nbuf[nbufptr++] = IAC; + break; + + // We need to heed RFC 854. LF (\n) is 10, CR (\r) is 13 + // we assume that the Terminal sends \n for lf+cr and \r for just cr + // linefeed+carriage return is CR LF */ + case 10: // \n + if (receivedDX[TELOPT_BINARY + 128 ] != DO) { + while (nbuf.length - nbufptr < crlf.length) { + xbuf = new byte[nbuf.length * 2]; + System.arraycopy(nbuf, 0, xbuf, 0, nbufptr); + nbuf = xbuf; + } + + for (int j = 0; j < crlf.length; j++) + nbuf[nbufptr++] = crlf[j]; + + break; + } + else { + // copy verbatim in binary mode. + nbuf[nbufptr++] = buf[i]; + } + + break; + + // carriage return is CR NUL */ + case 13: // \r + if (receivedDX[TELOPT_BINARY + 128 ] != DO) { + while (nbuf.length - nbufptr < cr.length) { + xbuf = new byte[nbuf.length * 2]; + System.arraycopy(nbuf, 0, xbuf, 0, nbufptr); + nbuf = xbuf; + } + + for (int j = 0; j < cr.length; j++) + nbuf[nbufptr++] = cr[j]; + } + else { + // copy verbatim in binary mode. + nbuf[nbufptr++] = buf[i]; + } + + break; + + // all other characters are just copied + default: + nbuf[nbufptr++] = buf[i]; + break; + } + } + + xbuf = new byte[nbufptr]; + System.arraycopy(nbuf, 0, xbuf, 0, nbufptr); + write(xbuf); + } + + public void setCRLF(String xcrlf) { crlf = xcrlf.getBytes(); } + public void setCR(String xcr) { cr = xcr.getBytes(); } + + /** + * Handle telnet protocol negotiation. The buffer will be parsed + * and necessary actions are taken according to the telnet protocol. + * See <A HREF="RFC-Telnet-URL">RFC-Telnet</A> + * @param nbuf the byte buffer put out after negotiation + * @return number of bytes processed, 0 for none, and -1 for end of buffer. + */ + public int negotiate(byte nbuf[], int offset) + throws IOException { + int count = tempbuf.length; + byte[] buf = tempbuf; + byte sendbuf[] = new byte[3]; + byte b, reply; + int boffset = 0, noffset = offset; + boolean dobreak = false; + + if (count == 0) // buffer is empty. + return -1; + + while (!dobreak && (boffset < count) && (noffset < nbuf.length)) { + b = buf[boffset++]; + + // of course, byte is a signed entity (-128 -> 127) + // but apparently the SGI Netscape 3.0 doesn't seem + // to care and provides happily values up to 255 + if (b >= 128) + b = (byte)(b - 256); + + if (debug > 2) { + Byte B = new Byte(b); + System.err.print("byte: " + B.intValue() + " "); + } + + switch (neg_state) { + case STATE_DATA: + if (b == IAC) { + neg_state = STATE_IAC; + dobreak = true; // leave the loop so we can sync. + } + else + nbuf[noffset++] = b; + + break; + + case STATE_IAC: + switch (b) { + case IAC: + if (debug > 2) System.err.print("IAC "); + + neg_state = STATE_DATA; + nbuf[noffset++] = IAC; + break; + + case WILL: + if (debug > 2) System.err.print("WILL "); + + neg_state = STATE_IACWILL; + break; + + case WONT: + if (debug > 2) System.err.print("WONT "); + + neg_state = STATE_IACWONT; + break; + + case DONT: + if (debug > 2) System.err.print("DONT "); + + neg_state = STATE_IACDONT; + break; + + case DO: + if (debug > 2) System.err.print("DO "); + + neg_state = STATE_IACDO; + break; + + case EOR: + if (debug > 1) System.err.print("EOR "); + + notifyEndOfRecord(); + dobreak = true; // leave the loop so we can sync. + neg_state = STATE_DATA; + break; + + case SB: + if (debug > 2) System.err.print("SB "); + + neg_state = STATE_IACSB; + break; + + default: + if (debug > 2) System.err.print("<UNKNOWN " + b + " > "); + + neg_state = STATE_DATA; + break; + } + + break; + + case STATE_IACWILL: + switch (b) { + case TELOPT_ECHO: + if (debug > 2) System.err.println("ECHO"); + + reply = DO; + setLocalEcho(false); + break; + + case TELOPT_SGA: + if (debug > 2) System.err.println("SGA"); + + reply = DO; + break; + + case TELOPT_EOR: + if (debug > 2) System.err.println("EOR"); + + reply = DO; + break; + + case TELOPT_BINARY: + if (debug > 2) System.err.println("BINARY"); + + reply = DO; + break; + + default: + if (debug > 2) System.err.println("<UNKNOWN," + b + ">"); + + reply = DONT; + break; + } + + if (debug > 1) System.err.println("<" + b + ", WILL =" + WILL + ">"); + + if (reply != sentDX[b + 128] || WILL != receivedWX[b + 128]) { + sendbuf[0] = IAC; + sendbuf[1] = reply; + sendbuf[2] = b; + write(sendbuf); + sentDX[b + 128] = reply; + receivedWX[b + 128] = WILL; + } + + neg_state = STATE_DATA; + break; + + case STATE_IACWONT: + switch (b) { + case TELOPT_ECHO: + if (debug > 2) System.err.println("ECHO"); + + setLocalEcho(true); + reply = DONT; + break; + + case TELOPT_SGA: + if (debug > 2) System.err.println("SGA"); + + reply = DONT; + break; + + case TELOPT_EOR: + if (debug > 2) System.err.println("EOR"); + + reply = DONT; + break; + + case TELOPT_BINARY: + if (debug > 2) System.err.println("BINARY"); + + reply = DONT; + break; + + default: + if (debug > 2) System.err.println("<UNKNOWN," + b + ">"); + + reply = DONT; + break; + } + + if (reply != sentDX[b + 128] || WONT != receivedWX[b + 128]) { + sendbuf[0] = IAC; + sendbuf[1] = reply; + sendbuf[2] = b; + write(sendbuf); + sentDX[b + 128] = reply; + receivedWX[b + 128] = WILL; + } + + neg_state = STATE_DATA; + break; + + case STATE_IACDO: + switch (b) { + case TELOPT_ECHO: + if (debug > 2) System.err.println("ECHO"); + + reply = WILL; + setLocalEcho(true); + break; + + case TELOPT_SGA: + if (debug > 2) System.err.println("SGA"); + + reply = WILL; + break; + + case TELOPT_TTYPE: + if (debug > 2) System.err.println("TTYPE"); + + reply = WILL; + break; + + case TELOPT_BINARY: + if (debug > 2) System.err.println("BINARY"); + + reply = WILL; + break; + + case TELOPT_NAWS: + if (debug > 2) System.err.println("NAWS"); + + int[] size = getWindowSize(); + receivedDX[b] = DO; + + if (size == null) { + // this shouldn't happen + write(IAC); + write(WONT); + write(TELOPT_NAWS); + reply = WONT; + sentWX[b] = WONT; + break; + } + + reply = WILL; + sentWX[b] = WILL; + sendbuf[0] = IAC; + sendbuf[1] = WILL; + sendbuf[2] = TELOPT_NAWS; + write(sendbuf); + write(IAC); write(SB); write(TELOPT_NAWS); + write((byte)(size[0] >> 8)); + write((byte)(size[0] & 0xff)); + write((byte)(size[1] >> 8)); + write((byte)(size[1] & 0xff)); + write(IAC); write(SE); + break; + + default: + if (debug > 2) System.err.println("<UNKNOWN," + b + ">"); + + reply = WONT; + break; + } + + if (reply != sentWX[128 + b] || DO != receivedDX[128 + b]) { + sendbuf[0] = IAC; + sendbuf[1] = reply; + sendbuf[2] = b; + write(sendbuf); + sentWX[b + 128] = reply; + receivedDX[b + 128] = DO; + } + + neg_state = STATE_DATA; + break; + + case STATE_IACDONT: + switch (b) { + case TELOPT_ECHO: + if (debug > 2) System.err.println("ECHO"); + + reply = WONT; + setLocalEcho(false); + break; + + case TELOPT_SGA: + if (debug > 2) System.err.println("SGA"); + + reply = WONT; + break; + + case TELOPT_NAWS: + if (debug > 2) System.err.println("NAWS"); + + reply = WONT; + break; + + case TELOPT_BINARY: + if (debug > 2) System.err.println("BINARY"); + + reply = WONT; + break; + + default: + if (debug > 2) System.err.println("<UNKNOWN," + b + ">"); + + reply = WONT; + break; + } + + if (reply != sentWX[b + 128] || DONT != receivedDX[b + 128]) { + write(IAC); write(reply); write(b); + sentWX[b + 128] = reply; + receivedDX[b + 128] = DONT; + } + + neg_state = STATE_DATA; + break; + + case STATE_IACSBIAC: + if (debug > 2) System.err.println("" + b + " "); + + if (b == IAC) { + sbbuf = new byte[0]; + current_sb = b; + neg_state = STATE_IACSBDATA; + } + else { + System.err.println("(bad) " + b + " "); + neg_state = STATE_DATA; + } + + break; + + case STATE_IACSB: + if (debug > 2) System.err.println("" + b + " "); + + switch (b) { + case IAC: + neg_state = STATE_IACSBIAC; + break; + + default: + current_sb = b; + sbbuf = new byte[0]; + neg_state = STATE_IACSBDATA; + break; + } + + break; + + case STATE_IACSBDATA: + if (debug > 2) System.err.println("" + b + " "); + + switch (b) { + case IAC: + neg_state = STATE_IACSBDATAIAC; + break; + + default: + byte[] xsb = new byte[sbbuf.length + 1]; + System.arraycopy(sbbuf, 0, xsb, 0, sbbuf.length); + sbbuf = xsb; + sbbuf[sbbuf.length - 1] = b; + break; + } + + break; + + case STATE_IACSBDATAIAC: + if (debug > 2) System.err.println("" + b + " "); + + switch (b) { + case IAC: + neg_state = STATE_IACSBDATA; + byte[] xsb = new byte[sbbuf.length + 1]; + System.arraycopy(sbbuf, 0, xsb, 0, sbbuf.length); + sbbuf = xsb; + sbbuf[sbbuf.length - 1] = IAC; + break; + + case SE: + handle_sb(current_sb, sbbuf); + current_sb = 0; + neg_state = STATE_DATA; + break; + + case SB: + handle_sb(current_sb, sbbuf); + neg_state = STATE_IACSB; + break; + + default: + neg_state = STATE_DATA; + break; + } + + break; + + default: + if (debug > 1) + System.err.println("This should not happen: " + neg_state + " "); + + neg_state = STATE_DATA; + break; + } + } + + // shrink tempbuf to new processed size. + byte[] xb = new byte[count - boffset]; + System.arraycopy(tempbuf, boffset, xb, 0, count - boffset); + tempbuf = xb; + return noffset - offset; + } + + public void inputfeed(byte[] b, int offset, int len) { + byte[] xb = new byte[tempbuf.length + len]; + System.arraycopy(tempbuf, 0, xb, 0, tempbuf.length); + System.arraycopy(b, offset, xb, tempbuf.length, len); + tempbuf = xb; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/de/mud/terminal/Precomposer.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1052 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.mud.terminal; + +/** + * @author Kenny Root + * This data was taken from xterm's precompose.c + */ +public class Precomposer { + public final static char precompositions[][] = { + { 0x226E, 0x003C, 0x0338}, + { 0x2260, 0x003D, 0x0338}, + { 0x226F, 0x003E, 0x0338}, + { 0x00C0, 0x0041, 0x0300}, + { 0x00C1, 0x0041, 0x0301}, + { 0x00C2, 0x0041, 0x0302}, + { 0x00C3, 0x0041, 0x0303}, + { 0x0100, 0x0041, 0x0304}, + { 0x0102, 0x0041, 0x0306}, + { 0x0226, 0x0041, 0x0307}, + { 0x00C4, 0x0041, 0x0308}, + { 0x1EA2, 0x0041, 0x0309}, + { 0x00C5, 0x0041, 0x030A}, + { 0x01CD, 0x0041, 0x030C}, + { 0x0200, 0x0041, 0x030F}, + { 0x0202, 0x0041, 0x0311}, + { 0x1EA0, 0x0041, 0x0323}, + { 0x1E00, 0x0041, 0x0325}, + { 0x0104, 0x0041, 0x0328}, + { 0x1E02, 0x0042, 0x0307}, + { 0x1E04, 0x0042, 0x0323}, + { 0x1E06, 0x0042, 0x0331}, + { 0x0106, 0x0043, 0x0301}, + { 0x0108, 0x0043, 0x0302}, + { 0x010A, 0x0043, 0x0307}, + { 0x010C, 0x0043, 0x030C}, + { 0x00C7, 0x0043, 0x0327}, + { 0x1E0A, 0x0044, 0x0307}, + { 0x010E, 0x0044, 0x030C}, + { 0x1E0C, 0x0044, 0x0323}, + { 0x1E10, 0x0044, 0x0327}, + { 0x1E12, 0x0044, 0x032D}, + { 0x1E0E, 0x0044, 0x0331}, + { 0x00C8, 0x0045, 0x0300}, + { 0x00C9, 0x0045, 0x0301}, + { 0x00CA, 0x0045, 0x0302}, + { 0x1EBC, 0x0045, 0x0303}, + { 0x0112, 0x0045, 0x0304}, + { 0x0114, 0x0045, 0x0306}, + { 0x0116, 0x0045, 0x0307}, + { 0x00CB, 0x0045, 0x0308}, + { 0x1EBA, 0x0045, 0x0309}, + { 0x011A, 0x0045, 0x030C}, + { 0x0204, 0x0045, 0x030F}, + { 0x0206, 0x0045, 0x0311}, + { 0x1EB8, 0x0045, 0x0323}, + { 0x0228, 0x0045, 0x0327}, + { 0x0118, 0x0045, 0x0328}, + { 0x1E18, 0x0045, 0x032D}, + { 0x1E1A, 0x0045, 0x0330}, + { 0x1E1E, 0x0046, 0x0307}, + { 0x01F4, 0x0047, 0x0301}, + { 0x011C, 0x0047, 0x0302}, + { 0x1E20, 0x0047, 0x0304}, + { 0x011E, 0x0047, 0x0306}, + { 0x0120, 0x0047, 0x0307}, + { 0x01E6, 0x0047, 0x030C}, + { 0x0122, 0x0047, 0x0327}, + { 0x0124, 0x0048, 0x0302}, + { 0x1E22, 0x0048, 0x0307}, + { 0x1E26, 0x0048, 0x0308}, + { 0x021E, 0x0048, 0x030C}, + { 0x1E24, 0x0048, 0x0323}, + { 0x1E28, 0x0048, 0x0327}, + { 0x1E2A, 0x0048, 0x032E}, + { 0x00CC, 0x0049, 0x0300}, + { 0x00CD, 0x0049, 0x0301}, + { 0x00CE, 0x0049, 0x0302}, + { 0x0128, 0x0049, 0x0303}, + { 0x012A, 0x0049, 0x0304}, + { 0x012C, 0x0049, 0x0306}, + { 0x0130, 0x0049, 0x0307}, + { 0x00CF, 0x0049, 0x0308}, + { 0x1EC8, 0x0049, 0x0309}, + { 0x01CF, 0x0049, 0x030C}, + { 0x0208, 0x0049, 0x030F}, + { 0x020A, 0x0049, 0x0311}, + { 0x1ECA, 0x0049, 0x0323}, + { 0x012E, 0x0049, 0x0328}, + { 0x1E2C, 0x0049, 0x0330}, + { 0x0134, 0x004A, 0x0302}, + { 0x1E30, 0x004B, 0x0301}, + { 0x01E8, 0x004B, 0x030C}, + { 0x1E32, 0x004B, 0x0323}, + { 0x0136, 0x004B, 0x0327}, + { 0x1E34, 0x004B, 0x0331}, + { 0x0139, 0x004C, 0x0301}, + { 0x013D, 0x004C, 0x030C}, + { 0x1E36, 0x004C, 0x0323}, + { 0x013B, 0x004C, 0x0327}, + { 0x1E3C, 0x004C, 0x032D}, + { 0x1E3A, 0x004C, 0x0331}, + { 0x1E3E, 0x004D, 0x0301}, + { 0x1E40, 0x004D, 0x0307}, + { 0x1E42, 0x004D, 0x0323}, + { 0x01F8, 0x004E, 0x0300}, + { 0x0143, 0x004E, 0x0301}, + { 0x00D1, 0x004E, 0x0303}, + { 0x1E44, 0x004E, 0x0307}, + { 0x0147, 0x004E, 0x030C}, + { 0x1E46, 0x004E, 0x0323}, + { 0x0145, 0x004E, 0x0327}, + { 0x1E4A, 0x004E, 0x032D}, + { 0x1E48, 0x004E, 0x0331}, + { 0x00D2, 0x004F, 0x0300}, + { 0x00D3, 0x004F, 0x0301}, + { 0x00D4, 0x004F, 0x0302}, + { 0x00D5, 0x004F, 0x0303}, + { 0x014C, 0x004F, 0x0304}, + { 0x014E, 0x004F, 0x0306}, + { 0x022E, 0x004F, 0x0307}, + { 0x00D6, 0x004F, 0x0308}, + { 0x1ECE, 0x004F, 0x0309}, + { 0x0150, 0x004F, 0x030B}, + { 0x01D1, 0x004F, 0x030C}, + { 0x020C, 0x004F, 0x030F}, + { 0x020E, 0x004F, 0x0311}, + { 0x01A0, 0x004F, 0x031B}, + { 0x1ECC, 0x004F, 0x0323}, + { 0x01EA, 0x004F, 0x0328}, + { 0x1E54, 0x0050, 0x0301}, + { 0x1E56, 0x0050, 0x0307}, + { 0x0154, 0x0052, 0x0301}, + { 0x1E58, 0x0052, 0x0307}, + { 0x0158, 0x0052, 0x030C}, + { 0x0210, 0x0052, 0x030F}, + { 0x0212, 0x0052, 0x0311}, + { 0x1E5A, 0x0052, 0x0323}, + { 0x0156, 0x0052, 0x0327}, + { 0x1E5E, 0x0052, 0x0331}, + { 0x015A, 0x0053, 0x0301}, + { 0x015C, 0x0053, 0x0302}, + { 0x1E60, 0x0053, 0x0307}, + { 0x0160, 0x0053, 0x030C}, + { 0x1E62, 0x0053, 0x0323}, + { 0x0218, 0x0053, 0x0326}, + { 0x015E, 0x0053, 0x0327}, + { 0x1E6A, 0x0054, 0x0307}, + { 0x0164, 0x0054, 0x030C}, + { 0x1E6C, 0x0054, 0x0323}, + { 0x021A, 0x0054, 0x0326}, + { 0x0162, 0x0054, 0x0327}, + { 0x1E70, 0x0054, 0x032D}, + { 0x1E6E, 0x0054, 0x0331}, + { 0x00D9, 0x0055, 0x0300}, + { 0x00DA, 0x0055, 0x0301}, + { 0x00DB, 0x0055, 0x0302}, + { 0x0168, 0x0055, 0x0303}, + { 0x016A, 0x0055, 0x0304}, + { 0x016C, 0x0055, 0x0306}, + { 0x00DC, 0x0055, 0x0308}, + { 0x1EE6, 0x0055, 0x0309}, + { 0x016E, 0x0055, 0x030A}, + { 0x0170, 0x0055, 0x030B}, + { 0x01D3, 0x0055, 0x030C}, + { 0x0214, 0x0055, 0x030F}, + { 0x0216, 0x0055, 0x0311}, + { 0x01AF, 0x0055, 0x031B}, + { 0x1EE4, 0x0055, 0x0323}, + { 0x1E72, 0x0055, 0x0324}, + { 0x0172, 0x0055, 0x0328}, + { 0x1E76, 0x0055, 0x032D}, + { 0x1E74, 0x0055, 0x0330}, + { 0x1E7C, 0x0056, 0x0303}, + { 0x1E7E, 0x0056, 0x0323}, + { 0x1E80, 0x0057, 0x0300}, + { 0x1E82, 0x0057, 0x0301}, + { 0x0174, 0x0057, 0x0302}, + { 0x1E86, 0x0057, 0x0307}, + { 0x1E84, 0x0057, 0x0308}, + { 0x1E88, 0x0057, 0x0323}, + { 0x1E8A, 0x0058, 0x0307}, + { 0x1E8C, 0x0058, 0x0308}, + { 0x1EF2, 0x0059, 0x0300}, + { 0x00DD, 0x0059, 0x0301}, + { 0x0176, 0x0059, 0x0302}, + { 0x1EF8, 0x0059, 0x0303}, + { 0x0232, 0x0059, 0x0304}, + { 0x1E8E, 0x0059, 0x0307}, + { 0x0178, 0x0059, 0x0308}, + { 0x1EF6, 0x0059, 0x0309}, + { 0x1EF4, 0x0059, 0x0323}, + { 0x0179, 0x005A, 0x0301}, + { 0x1E90, 0x005A, 0x0302}, + { 0x017B, 0x005A, 0x0307}, + { 0x017D, 0x005A, 0x030C}, + { 0x1E92, 0x005A, 0x0323}, + { 0x1E94, 0x005A, 0x0331}, + { 0x00E0, 0x0061, 0x0300}, + { 0x00E1, 0x0061, 0x0301}, + { 0x00E2, 0x0061, 0x0302}, + { 0x00E3, 0x0061, 0x0303}, + { 0x0101, 0x0061, 0x0304}, + { 0x0103, 0x0061, 0x0306}, + { 0x0227, 0x0061, 0x0307}, + { 0x00E4, 0x0061, 0x0308}, + { 0x1EA3, 0x0061, 0x0309}, + { 0x00E5, 0x0061, 0x030A}, + { 0x01CE, 0x0061, 0x030C}, + { 0x0201, 0x0061, 0x030F}, + { 0x0203, 0x0061, 0x0311}, + { 0x1EA1, 0x0061, 0x0323}, + { 0x1E01, 0x0061, 0x0325}, + { 0x0105, 0x0061, 0x0328}, + { 0x1E03, 0x0062, 0x0307}, + { 0x1E05, 0x0062, 0x0323}, + { 0x1E07, 0x0062, 0x0331}, + { 0x0107, 0x0063, 0x0301}, + { 0x0109, 0x0063, 0x0302}, + { 0x010B, 0x0063, 0x0307}, + { 0x010D, 0x0063, 0x030C}, + { 0x00E7, 0x0063, 0x0327}, + { 0x1E0B, 0x0064, 0x0307}, + { 0x010F, 0x0064, 0x030C}, + { 0x1E0D, 0x0064, 0x0323}, + { 0x1E11, 0x0064, 0x0327}, + { 0x1E13, 0x0064, 0x032D}, + { 0x1E0F, 0x0064, 0x0331}, + { 0x00E8, 0x0065, 0x0300}, + { 0x00E9, 0x0065, 0x0301}, + { 0x00EA, 0x0065, 0x0302}, + { 0x1EBD, 0x0065, 0x0303}, + { 0x0113, 0x0065, 0x0304}, + { 0x0115, 0x0065, 0x0306}, + { 0x0117, 0x0065, 0x0307}, + { 0x00EB, 0x0065, 0x0308}, + { 0x1EBB, 0x0065, 0x0309}, + { 0x011B, 0x0065, 0x030C}, + { 0x0205, 0x0065, 0x030F}, + { 0x0207, 0x0065, 0x0311}, + { 0x1EB9, 0x0065, 0x0323}, + { 0x0229, 0x0065, 0x0327}, + { 0x0119, 0x0065, 0x0328}, + { 0x1E19, 0x0065, 0x032D}, + { 0x1E1B, 0x0065, 0x0330}, + { 0x1E1F, 0x0066, 0x0307}, + { 0x01F5, 0x0067, 0x0301}, + { 0x011D, 0x0067, 0x0302}, + { 0x1E21, 0x0067, 0x0304}, + { 0x011F, 0x0067, 0x0306}, + { 0x0121, 0x0067, 0x0307}, + { 0x01E7, 0x0067, 0x030C}, + { 0x0123, 0x0067, 0x0327}, + { 0x0125, 0x0068, 0x0302}, + { 0x1E23, 0x0068, 0x0307}, + { 0x1E27, 0x0068, 0x0308}, + { 0x021F, 0x0068, 0x030C}, + { 0x1E25, 0x0068, 0x0323}, + { 0x1E29, 0x0068, 0x0327}, + { 0x1E2B, 0x0068, 0x032E}, + { 0x1E96, 0x0068, 0x0331}, + { 0x00EC, 0x0069, 0x0300}, + { 0x00ED, 0x0069, 0x0301}, + { 0x00EE, 0x0069, 0x0302}, + { 0x0129, 0x0069, 0x0303}, + { 0x012B, 0x0069, 0x0304}, + { 0x012D, 0x0069, 0x0306}, + { 0x00EF, 0x0069, 0x0308}, + { 0x1EC9, 0x0069, 0x0309}, + { 0x01D0, 0x0069, 0x030C}, + { 0x0209, 0x0069, 0x030F}, + { 0x020B, 0x0069, 0x0311}, + { 0x1ECB, 0x0069, 0x0323}, + { 0x012F, 0x0069, 0x0328}, + { 0x1E2D, 0x0069, 0x0330}, + { 0x0135, 0x006A, 0x0302}, + { 0x01F0, 0x006A, 0x030C}, + { 0x1E31, 0x006B, 0x0301}, + { 0x01E9, 0x006B, 0x030C}, + { 0x1E33, 0x006B, 0x0323}, + { 0x0137, 0x006B, 0x0327}, + { 0x1E35, 0x006B, 0x0331}, + { 0x013A, 0x006C, 0x0301}, + { 0x013E, 0x006C, 0x030C}, + { 0x1E37, 0x006C, 0x0323}, + { 0x013C, 0x006C, 0x0327}, + { 0x1E3D, 0x006C, 0x032D}, + { 0x1E3B, 0x006C, 0x0331}, + { 0x1E3F, 0x006D, 0x0301}, + { 0x1E41, 0x006D, 0x0307}, + { 0x1E43, 0x006D, 0x0323}, + { 0x01F9, 0x006E, 0x0300}, + { 0x0144, 0x006E, 0x0301}, + { 0x00F1, 0x006E, 0x0303}, + { 0x1E45, 0x006E, 0x0307}, + { 0x0148, 0x006E, 0x030C}, + { 0x1E47, 0x006E, 0x0323}, + { 0x0146, 0x006E, 0x0327}, + { 0x1E4B, 0x006E, 0x032D}, + { 0x1E49, 0x006E, 0x0331}, + { 0x00F2, 0x006F, 0x0300}, + { 0x00F3, 0x006F, 0x0301}, + { 0x00F4, 0x006F, 0x0302}, + { 0x00F5, 0x006F, 0x0303}, + { 0x014D, 0x006F, 0x0304}, + { 0x014F, 0x006F, 0x0306}, + { 0x022F, 0x006F, 0x0307}, + { 0x00F6, 0x006F, 0x0308}, + { 0x1ECF, 0x006F, 0x0309}, + { 0x0151, 0x006F, 0x030B}, + { 0x01D2, 0x006F, 0x030C}, + { 0x020D, 0x006F, 0x030F}, + { 0x020F, 0x006F, 0x0311}, + { 0x01A1, 0x006F, 0x031B}, + { 0x1ECD, 0x006F, 0x0323}, + { 0x01EB, 0x006F, 0x0328}, + { 0x1E55, 0x0070, 0x0301}, + { 0x1E57, 0x0070, 0x0307}, + { 0x0155, 0x0072, 0x0301}, + { 0x1E59, 0x0072, 0x0307}, + { 0x0159, 0x0072, 0x030C}, + { 0x0211, 0x0072, 0x030F}, + { 0x0213, 0x0072, 0x0311}, + { 0x1E5B, 0x0072, 0x0323}, + { 0x0157, 0x0072, 0x0327}, + { 0x1E5F, 0x0072, 0x0331}, + { 0x015B, 0x0073, 0x0301}, + { 0x015D, 0x0073, 0x0302}, + { 0x1E61, 0x0073, 0x0307}, + { 0x0161, 0x0073, 0x030C}, + { 0x1E63, 0x0073, 0x0323}, + { 0x0219, 0x0073, 0x0326}, + { 0x015F, 0x0073, 0x0327}, + { 0x1E6B, 0x0074, 0x0307}, + { 0x1E97, 0x0074, 0x0308}, + { 0x0165, 0x0074, 0x030C}, + { 0x1E6D, 0x0074, 0x0323}, + { 0x021B, 0x0074, 0x0326}, + { 0x0163, 0x0074, 0x0327}, + { 0x1E71, 0x0074, 0x032D}, + { 0x1E6F, 0x0074, 0x0331}, + { 0x00F9, 0x0075, 0x0300}, + { 0x00FA, 0x0075, 0x0301}, + { 0x00FB, 0x0075, 0x0302}, + { 0x0169, 0x0075, 0x0303}, + { 0x016B, 0x0075, 0x0304}, + { 0x016D, 0x0075, 0x0306}, + { 0x00FC, 0x0075, 0x0308}, + { 0x1EE7, 0x0075, 0x0309}, + { 0x016F, 0x0075, 0x030A}, + { 0x0171, 0x0075, 0x030B}, + { 0x01D4, 0x0075, 0x030C}, + { 0x0215, 0x0075, 0x030F}, + { 0x0217, 0x0075, 0x0311}, + { 0x01B0, 0x0075, 0x031B}, + { 0x1EE5, 0x0075, 0x0323}, + { 0x1E73, 0x0075, 0x0324}, + { 0x0173, 0x0075, 0x0328}, + { 0x1E77, 0x0075, 0x032D}, + { 0x1E75, 0x0075, 0x0330}, + { 0x1E7D, 0x0076, 0x0303}, + { 0x1E7F, 0x0076, 0x0323}, + { 0x1E81, 0x0077, 0x0300}, + { 0x1E83, 0x0077, 0x0301}, + { 0x0175, 0x0077, 0x0302}, + { 0x1E87, 0x0077, 0x0307}, + { 0x1E85, 0x0077, 0x0308}, + { 0x1E98, 0x0077, 0x030A}, + { 0x1E89, 0x0077, 0x0323}, + { 0x1E8B, 0x0078, 0x0307}, + { 0x1E8D, 0x0078, 0x0308}, + { 0x1EF3, 0x0079, 0x0300}, + { 0x00FD, 0x0079, 0x0301}, + { 0x0177, 0x0079, 0x0302}, + { 0x1EF9, 0x0079, 0x0303}, + { 0x0233, 0x0079, 0x0304}, + { 0x1E8F, 0x0079, 0x0307}, + { 0x00FF, 0x0079, 0x0308}, + { 0x1EF7, 0x0079, 0x0309}, + { 0x1E99, 0x0079, 0x030A}, + { 0x1EF5, 0x0079, 0x0323}, + { 0x017A, 0x007A, 0x0301}, + { 0x1E91, 0x007A, 0x0302}, + { 0x017C, 0x007A, 0x0307}, + { 0x017E, 0x007A, 0x030C}, + { 0x1E93, 0x007A, 0x0323}, + { 0x1E95, 0x007A, 0x0331}, + { 0x1FED, 0x00A8, 0x0300}, + { 0x0385, 0x00A8, 0x0301}, + { 0x1FC1, 0x00A8, 0x0342}, + { 0x1EA6, 0x00C2, 0x0300}, + { 0x1EA4, 0x00C2, 0x0301}, + { 0x1EAA, 0x00C2, 0x0303}, + { 0x1EA8, 0x00C2, 0x0309}, + { 0x01DE, 0x00C4, 0x0304}, + { 0x01FA, 0x00C5, 0x0301}, + { 0x01FC, 0x00C6, 0x0301}, + { 0x01E2, 0x00C6, 0x0304}, + { 0x1E08, 0x00C7, 0x0301}, + { 0x1EC0, 0x00CA, 0x0300}, + { 0x1EBE, 0x00CA, 0x0301}, + { 0x1EC4, 0x00CA, 0x0303}, + { 0x1EC2, 0x00CA, 0x0309}, + { 0x1E2E, 0x00CF, 0x0301}, + { 0x1ED2, 0x00D4, 0x0300}, + { 0x1ED0, 0x00D4, 0x0301}, + { 0x1ED6, 0x00D4, 0x0303}, + { 0x1ED4, 0x00D4, 0x0309}, + { 0x1E4C, 0x00D5, 0x0301}, + { 0x022C, 0x00D5, 0x0304}, + { 0x1E4E, 0x00D5, 0x0308}, + { 0x022A, 0x00D6, 0x0304}, + { 0x01FE, 0x00D8, 0x0301}, + { 0x01DB, 0x00DC, 0x0300}, + { 0x01D7, 0x00DC, 0x0301}, + { 0x01D5, 0x00DC, 0x0304}, + { 0x01D9, 0x00DC, 0x030C}, + { 0x1EA7, 0x00E2, 0x0300}, + { 0x1EA5, 0x00E2, 0x0301}, + { 0x1EAB, 0x00E2, 0x0303}, + { 0x1EA9, 0x00E2, 0x0309}, + { 0x01DF, 0x00E4, 0x0304}, + { 0x01FB, 0x00E5, 0x0301}, + { 0x01FD, 0x00E6, 0x0301}, + { 0x01E3, 0x00E6, 0x0304}, + { 0x1E09, 0x00E7, 0x0301}, + { 0x1EC1, 0x00EA, 0x0300}, + { 0x1EBF, 0x00EA, 0x0301}, + { 0x1EC5, 0x00EA, 0x0303}, + { 0x1EC3, 0x00EA, 0x0309}, + { 0x1E2F, 0x00EF, 0x0301}, + { 0x1ED3, 0x00F4, 0x0300}, + { 0x1ED1, 0x00F4, 0x0301}, + { 0x1ED7, 0x00F4, 0x0303}, + { 0x1ED5, 0x00F4, 0x0309}, + { 0x1E4D, 0x00F5, 0x0301}, + { 0x022D, 0x00F5, 0x0304}, + { 0x1E4F, 0x00F5, 0x0308}, + { 0x022B, 0x00F6, 0x0304}, + { 0x01FF, 0x00F8, 0x0301}, + { 0x01DC, 0x00FC, 0x0300}, + { 0x01D8, 0x00FC, 0x0301}, + { 0x01D6, 0x00FC, 0x0304}, + { 0x01DA, 0x00FC, 0x030C}, + { 0x1EB0, 0x0102, 0x0300}, + { 0x1EAE, 0x0102, 0x0301}, + { 0x1EB4, 0x0102, 0x0303}, + { 0x1EB2, 0x0102, 0x0309}, + { 0x1EB1, 0x0103, 0x0300}, + { 0x1EAF, 0x0103, 0x0301}, + { 0x1EB5, 0x0103, 0x0303}, + { 0x1EB3, 0x0103, 0x0309}, + { 0x1E14, 0x0112, 0x0300}, + { 0x1E16, 0x0112, 0x0301}, + { 0x1E15, 0x0113, 0x0300}, + { 0x1E17, 0x0113, 0x0301}, + { 0x1E50, 0x014C, 0x0300}, + { 0x1E52, 0x014C, 0x0301}, + { 0x1E51, 0x014D, 0x0300}, + { 0x1E53, 0x014D, 0x0301}, + { 0x1E64, 0x015A, 0x0307}, + { 0x1E65, 0x015B, 0x0307}, + { 0x1E66, 0x0160, 0x0307}, + { 0x1E67, 0x0161, 0x0307}, + { 0x1E78, 0x0168, 0x0301}, + { 0x1E79, 0x0169, 0x0301}, + { 0x1E7A, 0x016A, 0x0308}, + { 0x1E7B, 0x016B, 0x0308}, + { 0x1E9B, 0x017F, 0x0307}, + { 0x1EDC, 0x01A0, 0x0300}, + { 0x1EDA, 0x01A0, 0x0301}, + { 0x1EE0, 0x01A0, 0x0303}, + { 0x1EDE, 0x01A0, 0x0309}, + { 0x1EE2, 0x01A0, 0x0323}, + { 0x1EDD, 0x01A1, 0x0300}, + { 0x1EDB, 0x01A1, 0x0301}, + { 0x1EE1, 0x01A1, 0x0303}, + { 0x1EDF, 0x01A1, 0x0309}, + { 0x1EE3, 0x01A1, 0x0323}, + { 0x1EEA, 0x01AF, 0x0300}, + { 0x1EE8, 0x01AF, 0x0301}, + { 0x1EEE, 0x01AF, 0x0303}, + { 0x1EEC, 0x01AF, 0x0309}, + { 0x1EF0, 0x01AF, 0x0323}, + { 0x1EEB, 0x01B0, 0x0300}, + { 0x1EE9, 0x01B0, 0x0301}, + { 0x1EEF, 0x01B0, 0x0303}, + { 0x1EED, 0x01B0, 0x0309}, + { 0x1EF1, 0x01B0, 0x0323}, + { 0x01EE, 0x01B7, 0x030C}, + { 0x01EC, 0x01EA, 0x0304}, + { 0x01ED, 0x01EB, 0x0304}, + { 0x01E0, 0x0226, 0x0304}, + { 0x01E1, 0x0227, 0x0304}, + { 0x1E1C, 0x0228, 0x0306}, + { 0x1E1D, 0x0229, 0x0306}, + { 0x0230, 0x022E, 0x0304}, + { 0x0231, 0x022F, 0x0304}, + { 0x01EF, 0x0292, 0x030C}, + { 0x0344, 0x0308, 0x0301}, + { 0x1FBA, 0x0391, 0x0300}, + { 0x0386, 0x0391, 0x0301}, + { 0x1FB9, 0x0391, 0x0304}, + { 0x1FB8, 0x0391, 0x0306}, + { 0x1F08, 0x0391, 0x0313}, + { 0x1F09, 0x0391, 0x0314}, + { 0x1FBC, 0x0391, 0x0345}, + { 0x1FC8, 0x0395, 0x0300}, + { 0x0388, 0x0395, 0x0301}, + { 0x1F18, 0x0395, 0x0313}, + { 0x1F19, 0x0395, 0x0314}, + { 0x1FCA, 0x0397, 0x0300}, + { 0x0389, 0x0397, 0x0301}, + { 0x1F28, 0x0397, 0x0313}, + { 0x1F29, 0x0397, 0x0314}, + { 0x1FCC, 0x0397, 0x0345}, + { 0x1FDA, 0x0399, 0x0300}, + { 0x038A, 0x0399, 0x0301}, + { 0x1FD9, 0x0399, 0x0304}, + { 0x1FD8, 0x0399, 0x0306}, + { 0x03AA, 0x0399, 0x0308}, + { 0x1F38, 0x0399, 0x0313}, + { 0x1F39, 0x0399, 0x0314}, + { 0x1FF8, 0x039F, 0x0300}, + { 0x038C, 0x039F, 0x0301}, + { 0x1F48, 0x039F, 0x0313}, + { 0x1F49, 0x039F, 0x0314}, + { 0x1FEC, 0x03A1, 0x0314}, + { 0x1FEA, 0x03A5, 0x0300}, + { 0x038E, 0x03A5, 0x0301}, + { 0x1FE9, 0x03A5, 0x0304}, + { 0x1FE8, 0x03A5, 0x0306}, + { 0x03AB, 0x03A5, 0x0308}, + { 0x1F59, 0x03A5, 0x0314}, + { 0x1FFA, 0x03A9, 0x0300}, + { 0x038F, 0x03A9, 0x0301}, + { 0x1F68, 0x03A9, 0x0313}, + { 0x1F69, 0x03A9, 0x0314}, + { 0x1FFC, 0x03A9, 0x0345}, + { 0x1FB4, 0x03AC, 0x0345}, + { 0x1FC4, 0x03AE, 0x0345}, + { 0x1F70, 0x03B1, 0x0300}, + { 0x03AC, 0x03B1, 0x0301}, + { 0x1FB1, 0x03B1, 0x0304}, + { 0x1FB0, 0x03B1, 0x0306}, + { 0x1F00, 0x03B1, 0x0313}, + { 0x1F01, 0x03B1, 0x0314}, + { 0x1FB6, 0x03B1, 0x0342}, + { 0x1FB3, 0x03B1, 0x0345}, + { 0x1F72, 0x03B5, 0x0300}, + { 0x03AD, 0x03B5, 0x0301}, + { 0x1F10, 0x03B5, 0x0313}, + { 0x1F11, 0x03B5, 0x0314}, + { 0x1F74, 0x03B7, 0x0300}, + { 0x03AE, 0x03B7, 0x0301}, + { 0x1F20, 0x03B7, 0x0313}, + { 0x1F21, 0x03B7, 0x0314}, + { 0x1FC6, 0x03B7, 0x0342}, + { 0x1FC3, 0x03B7, 0x0345}, + { 0x1F76, 0x03B9, 0x0300}, + { 0x03AF, 0x03B9, 0x0301}, + { 0x1FD1, 0x03B9, 0x0304}, + { 0x1FD0, 0x03B9, 0x0306}, + { 0x03CA, 0x03B9, 0x0308}, + { 0x1F30, 0x03B9, 0x0313}, + { 0x1F31, 0x03B9, 0x0314}, + { 0x1FD6, 0x03B9, 0x0342}, + { 0x1F78, 0x03BF, 0x0300}, + { 0x03CC, 0x03BF, 0x0301}, + { 0x1F40, 0x03BF, 0x0313}, + { 0x1F41, 0x03BF, 0x0314}, + { 0x1FE4, 0x03C1, 0x0313}, + { 0x1FE5, 0x03C1, 0x0314}, + { 0x1F7A, 0x03C5, 0x0300}, + { 0x03CD, 0x03C5, 0x0301}, + { 0x1FE1, 0x03C5, 0x0304}, + { 0x1FE0, 0x03C5, 0x0306}, + { 0x03CB, 0x03C5, 0x0308}, + { 0x1F50, 0x03C5, 0x0313}, + { 0x1F51, 0x03C5, 0x0314}, + { 0x1FE6, 0x03C5, 0x0342}, + { 0x1F7C, 0x03C9, 0x0300}, + { 0x03CE, 0x03C9, 0x0301}, + { 0x1F60, 0x03C9, 0x0313}, + { 0x1F61, 0x03C9, 0x0314}, + { 0x1FF6, 0x03C9, 0x0342}, + { 0x1FF3, 0x03C9, 0x0345}, + { 0x1FD2, 0x03CA, 0x0300}, + { 0x0390, 0x03CA, 0x0301}, + { 0x1FD7, 0x03CA, 0x0342}, + { 0x1FE2, 0x03CB, 0x0300}, + { 0x03B0, 0x03CB, 0x0301}, + { 0x1FE7, 0x03CB, 0x0342}, + { 0x1FF4, 0x03CE, 0x0345}, + { 0x03D3, 0x03D2, 0x0301}, + { 0x03D4, 0x03D2, 0x0308}, + { 0x0407, 0x0406, 0x0308}, + { 0x04D0, 0x0410, 0x0306}, + { 0x04D2, 0x0410, 0x0308}, + { 0x0403, 0x0413, 0x0301}, + { 0x0400, 0x0415, 0x0300}, + { 0x04D6, 0x0415, 0x0306}, + { 0x0401, 0x0415, 0x0308}, + { 0x04C1, 0x0416, 0x0306}, + { 0x04DC, 0x0416, 0x0308}, + { 0x04DE, 0x0417, 0x0308}, + { 0x040D, 0x0418, 0x0300}, + { 0x04E2, 0x0418, 0x0304}, + { 0x0419, 0x0418, 0x0306}, + { 0x04E4, 0x0418, 0x0308}, + { 0x040C, 0x041A, 0x0301}, + { 0x04E6, 0x041E, 0x0308}, + { 0x04EE, 0x0423, 0x0304}, + { 0x040E, 0x0423, 0x0306}, + { 0x04F0, 0x0423, 0x0308}, + { 0x04F2, 0x0423, 0x030B}, + { 0x04F4, 0x0427, 0x0308}, + { 0x04F8, 0x042B, 0x0308}, + { 0x04EC, 0x042D, 0x0308}, + { 0x04D1, 0x0430, 0x0306}, + { 0x04D3, 0x0430, 0x0308}, + { 0x0453, 0x0433, 0x0301}, + { 0x0450, 0x0435, 0x0300}, + { 0x04D7, 0x0435, 0x0306}, + { 0x0451, 0x0435, 0x0308}, + { 0x04C2, 0x0436, 0x0306}, + { 0x04DD, 0x0436, 0x0308}, + { 0x04DF, 0x0437, 0x0308}, + { 0x045D, 0x0438, 0x0300}, + { 0x04E3, 0x0438, 0x0304}, + { 0x0439, 0x0438, 0x0306}, + { 0x04E5, 0x0438, 0x0308}, + { 0x045C, 0x043A, 0x0301}, + { 0x04E7, 0x043E, 0x0308}, + { 0x04EF, 0x0443, 0x0304}, + { 0x045E, 0x0443, 0x0306}, + { 0x04F1, 0x0443, 0x0308}, + { 0x04F3, 0x0443, 0x030B}, + { 0x04F5, 0x0447, 0x0308}, + { 0x04F9, 0x044B, 0x0308}, + { 0x04ED, 0x044D, 0x0308}, + { 0x0457, 0x0456, 0x0308}, + { 0x0476, 0x0474, 0x030F}, + { 0x0477, 0x0475, 0x030F}, + { 0x04DA, 0x04D8, 0x0308}, + { 0x04DB, 0x04D9, 0x0308}, + { 0x04EA, 0x04E8, 0x0308}, + { 0x04EB, 0x04E9, 0x0308}, + { 0xFB2E, 0x05D0, 0x05B7}, + { 0xFB2F, 0x05D0, 0x05B8}, + { 0xFB30, 0x05D0, 0x05BC}, + { 0xFB31, 0x05D1, 0x05BC}, + { 0xFB4C, 0x05D1, 0x05BF}, + { 0xFB32, 0x05D2, 0x05BC}, + { 0xFB33, 0x05D3, 0x05BC}, + { 0xFB34, 0x05D4, 0x05BC}, + { 0xFB4B, 0x05D5, 0x05B9}, + { 0xFB35, 0x05D5, 0x05BC}, + { 0xFB36, 0x05D6, 0x05BC}, + { 0xFB38, 0x05D8, 0x05BC}, + { 0xFB1D, 0x05D9, 0x05B4}, + { 0xFB39, 0x05D9, 0x05BC}, + { 0xFB3A, 0x05DA, 0x05BC}, + { 0xFB3B, 0x05DB, 0x05BC}, + { 0xFB4D, 0x05DB, 0x05BF}, + { 0xFB3C, 0x05DC, 0x05BC}, + { 0xFB3E, 0x05DE, 0x05BC}, + { 0xFB40, 0x05E0, 0x05BC}, + { 0xFB41, 0x05E1, 0x05BC}, + { 0xFB43, 0x05E3, 0x05BC}, + { 0xFB44, 0x05E4, 0x05BC}, + { 0xFB4E, 0x05E4, 0x05BF}, + { 0xFB46, 0x05E6, 0x05BC}, + { 0xFB47, 0x05E7, 0x05BC}, + { 0xFB48, 0x05E8, 0x05BC}, + { 0xFB49, 0x05E9, 0x05BC}, + { 0xFB2A, 0x05E9, 0x05C1}, + { 0xFB2B, 0x05E9, 0x05C2}, + { 0xFB4A, 0x05EA, 0x05BC}, + { 0xFB1F, 0x05F2, 0x05B7}, + { 0x0622, 0x0627, 0x0653}, + { 0x0623, 0x0627, 0x0654}, + { 0x0625, 0x0627, 0x0655}, + { 0x0624, 0x0648, 0x0654}, + { 0x0626, 0x064A, 0x0654}, + { 0x06C2, 0x06C1, 0x0654}, + { 0x06D3, 0x06D2, 0x0654}, + { 0x06C0, 0x06D5, 0x0654}, + { 0x0958, 0x0915, 0x093C}, + { 0x0959, 0x0916, 0x093C}, + { 0x095A, 0x0917, 0x093C}, + { 0x095B, 0x091C, 0x093C}, + { 0x095C, 0x0921, 0x093C}, + { 0x095D, 0x0922, 0x093C}, + { 0x0929, 0x0928, 0x093C}, + { 0x095E, 0x092B, 0x093C}, + { 0x095F, 0x092F, 0x093C}, + { 0x0931, 0x0930, 0x093C}, + { 0x0934, 0x0933, 0x093C}, + { 0x09DC, 0x09A1, 0x09BC}, + { 0x09DD, 0x09A2, 0x09BC}, + { 0x09DF, 0x09AF, 0x09BC}, + { 0x09CB, 0x09C7, 0x09BE}, + { 0x09CC, 0x09C7, 0x09D7}, + { 0x0A59, 0x0A16, 0x0A3C}, + { 0x0A5A, 0x0A17, 0x0A3C}, + { 0x0A5B, 0x0A1C, 0x0A3C}, + { 0x0A5E, 0x0A2B, 0x0A3C}, + { 0x0A33, 0x0A32, 0x0A3C}, + { 0x0A36, 0x0A38, 0x0A3C}, + { 0x0B5C, 0x0B21, 0x0B3C}, + { 0x0B5D, 0x0B22, 0x0B3C}, + { 0x0B4B, 0x0B47, 0x0B3E}, + { 0x0B48, 0x0B47, 0x0B56}, + { 0x0B4C, 0x0B47, 0x0B57}, + { 0x0B94, 0x0B92, 0x0BD7}, + { 0x0BCA, 0x0BC6, 0x0BBE}, + { 0x0BCC, 0x0BC6, 0x0BD7}, + { 0x0BCB, 0x0BC7, 0x0BBE}, + { 0x0C48, 0x0C46, 0x0C56}, + { 0x0CC0, 0x0CBF, 0x0CD5}, + { 0x0CCA, 0x0CC6, 0x0CC2}, + { 0x0CC7, 0x0CC6, 0x0CD5}, + { 0x0CC8, 0x0CC6, 0x0CD6}, + { 0x0CCB, 0x0CCA, 0x0CD5}, + { 0x0D4A, 0x0D46, 0x0D3E}, + { 0x0D4C, 0x0D46, 0x0D57}, + { 0x0D4B, 0x0D47, 0x0D3E}, + { 0x0DDA, 0x0DD9, 0x0DCA}, + { 0x0DDC, 0x0DD9, 0x0DCF}, + { 0x0DDE, 0x0DD9, 0x0DDF}, + { 0x0DDD, 0x0DDC, 0x0DCA}, + { 0x0F69, 0x0F40, 0x0FB5}, + { 0x0F43, 0x0F42, 0x0FB7}, + { 0x0F4D, 0x0F4C, 0x0FB7}, + { 0x0F52, 0x0F51, 0x0FB7}, + { 0x0F57, 0x0F56, 0x0FB7}, + { 0x0F5C, 0x0F5B, 0x0FB7}, + { 0x0F73, 0x0F71, 0x0F72}, + { 0x0F75, 0x0F71, 0x0F74}, + { 0x0F81, 0x0F71, 0x0F80}, + { 0x0FB9, 0x0F90, 0x0FB5}, + { 0x0F93, 0x0F92, 0x0FB7}, + { 0x0F9D, 0x0F9C, 0x0FB7}, + { 0x0FA2, 0x0FA1, 0x0FB7}, + { 0x0FA7, 0x0FA6, 0x0FB7}, + { 0x0FAC, 0x0FAB, 0x0FB7}, + { 0x0F76, 0x0FB2, 0x0F80}, + { 0x0F78, 0x0FB3, 0x0F80}, + { 0x1026, 0x1025, 0x102E}, + { 0x1B06, 0x1B05, 0x1B35}, + { 0x1B08, 0x1B07, 0x1B35}, + { 0x1B0A, 0x1B09, 0x1B35}, + { 0x1B0C, 0x1B0B, 0x1B35}, + { 0x1B0E, 0x1B0D, 0x1B35}, + { 0x1B12, 0x1B11, 0x1B35}, + { 0x1B3B, 0x1B3A, 0x1B35}, + { 0x1B3D, 0x1B3C, 0x1B35}, + { 0x1B40, 0x1B3E, 0x1B35}, + { 0x1B41, 0x1B3F, 0x1B35}, + { 0x1B43, 0x1B42, 0x1B35}, + { 0x1E38, 0x1E36, 0x0304}, + { 0x1E39, 0x1E37, 0x0304}, + { 0x1E5C, 0x1E5A, 0x0304}, + { 0x1E5D, 0x1E5B, 0x0304}, + { 0x1E68, 0x1E62, 0x0307}, + { 0x1E69, 0x1E63, 0x0307}, + { 0x1EAC, 0x1EA0, 0x0302}, + { 0x1EB6, 0x1EA0, 0x0306}, + { 0x1EAD, 0x1EA1, 0x0302}, + { 0x1EB7, 0x1EA1, 0x0306}, + { 0x1EC6, 0x1EB8, 0x0302}, + { 0x1EC7, 0x1EB9, 0x0302}, + { 0x1ED8, 0x1ECC, 0x0302}, + { 0x1ED9, 0x1ECD, 0x0302}, + { 0x1F02, 0x1F00, 0x0300}, + { 0x1F04, 0x1F00, 0x0301}, + { 0x1F06, 0x1F00, 0x0342}, + { 0x1F80, 0x1F00, 0x0345}, + { 0x1F03, 0x1F01, 0x0300}, + { 0x1F05, 0x1F01, 0x0301}, + { 0x1F07, 0x1F01, 0x0342}, + { 0x1F81, 0x1F01, 0x0345}, + { 0x1F82, 0x1F02, 0x0345}, + { 0x1F83, 0x1F03, 0x0345}, + { 0x1F84, 0x1F04, 0x0345}, + { 0x1F85, 0x1F05, 0x0345}, + { 0x1F86, 0x1F06, 0x0345}, + { 0x1F87, 0x1F07, 0x0345}, + { 0x1F0A, 0x1F08, 0x0300}, + { 0x1F0C, 0x1F08, 0x0301}, + { 0x1F0E, 0x1F08, 0x0342}, + { 0x1F88, 0x1F08, 0x0345}, + { 0x1F0B, 0x1F09, 0x0300}, + { 0x1F0D, 0x1F09, 0x0301}, + { 0x1F0F, 0x1F09, 0x0342}, + { 0x1F89, 0x1F09, 0x0345}, + { 0x1F8A, 0x1F0A, 0x0345}, + { 0x1F8B, 0x1F0B, 0x0345}, + { 0x1F8C, 0x1F0C, 0x0345}, + { 0x1F8D, 0x1F0D, 0x0345}, + { 0x1F8E, 0x1F0E, 0x0345}, + { 0x1F8F, 0x1F0F, 0x0345}, + { 0x1F12, 0x1F10, 0x0300}, + { 0x1F14, 0x1F10, 0x0301}, + { 0x1F13, 0x1F11, 0x0300}, + { 0x1F15, 0x1F11, 0x0301}, + { 0x1F1A, 0x1F18, 0x0300}, + { 0x1F1C, 0x1F18, 0x0301}, + { 0x1F1B, 0x1F19, 0x0300}, + { 0x1F1D, 0x1F19, 0x0301}, + { 0x1F22, 0x1F20, 0x0300}, + { 0x1F24, 0x1F20, 0x0301}, + { 0x1F26, 0x1F20, 0x0342}, + { 0x1F90, 0x1F20, 0x0345}, + { 0x1F23, 0x1F21, 0x0300}, + { 0x1F25, 0x1F21, 0x0301}, + { 0x1F27, 0x1F21, 0x0342}, + { 0x1F91, 0x1F21, 0x0345}, + { 0x1F92, 0x1F22, 0x0345}, + { 0x1F93, 0x1F23, 0x0345}, + { 0x1F94, 0x1F24, 0x0345}, + { 0x1F95, 0x1F25, 0x0345}, + { 0x1F96, 0x1F26, 0x0345}, + { 0x1F97, 0x1F27, 0x0345}, + { 0x1F2A, 0x1F28, 0x0300}, + { 0x1F2C, 0x1F28, 0x0301}, + { 0x1F2E, 0x1F28, 0x0342}, + { 0x1F98, 0x1F28, 0x0345}, + { 0x1F2B, 0x1F29, 0x0300}, + { 0x1F2D, 0x1F29, 0x0301}, + { 0x1F2F, 0x1F29, 0x0342}, + { 0x1F99, 0x1F29, 0x0345}, + { 0x1F9A, 0x1F2A, 0x0345}, + { 0x1F9B, 0x1F2B, 0x0345}, + { 0x1F9C, 0x1F2C, 0x0345}, + { 0x1F9D, 0x1F2D, 0x0345}, + { 0x1F9E, 0x1F2E, 0x0345}, + { 0x1F9F, 0x1F2F, 0x0345}, + { 0x1F32, 0x1F30, 0x0300}, + { 0x1F34, 0x1F30, 0x0301}, + { 0x1F36, 0x1F30, 0x0342}, + { 0x1F33, 0x1F31, 0x0300}, + { 0x1F35, 0x1F31, 0x0301}, + { 0x1F37, 0x1F31, 0x0342}, + { 0x1F3A, 0x1F38, 0x0300}, + { 0x1F3C, 0x1F38, 0x0301}, + { 0x1F3E, 0x1F38, 0x0342}, + { 0x1F3B, 0x1F39, 0x0300}, + { 0x1F3D, 0x1F39, 0x0301}, + { 0x1F3F, 0x1F39, 0x0342}, + { 0x1F42, 0x1F40, 0x0300}, + { 0x1F44, 0x1F40, 0x0301}, + { 0x1F43, 0x1F41, 0x0300}, + { 0x1F45, 0x1F41, 0x0301}, + { 0x1F4A, 0x1F48, 0x0300}, + { 0x1F4C, 0x1F48, 0x0301}, + { 0x1F4B, 0x1F49, 0x0300}, + { 0x1F4D, 0x1F49, 0x0301}, + { 0x1F52, 0x1F50, 0x0300}, + { 0x1F54, 0x1F50, 0x0301}, + { 0x1F56, 0x1F50, 0x0342}, + { 0x1F53, 0x1F51, 0x0300}, + { 0x1F55, 0x1F51, 0x0301}, + { 0x1F57, 0x1F51, 0x0342}, + { 0x1F5B, 0x1F59, 0x0300}, + { 0x1F5D, 0x1F59, 0x0301}, + { 0x1F5F, 0x1F59, 0x0342}, + { 0x1F62, 0x1F60, 0x0300}, + { 0x1F64, 0x1F60, 0x0301}, + { 0x1F66, 0x1F60, 0x0342}, + { 0x1FA0, 0x1F60, 0x0345}, + { 0x1F63, 0x1F61, 0x0300}, + { 0x1F65, 0x1F61, 0x0301}, + { 0x1F67, 0x1F61, 0x0342}, + { 0x1FA1, 0x1F61, 0x0345}, + { 0x1FA2, 0x1F62, 0x0345}, + { 0x1FA3, 0x1F63, 0x0345}, + { 0x1FA4, 0x1F64, 0x0345}, + { 0x1FA5, 0x1F65, 0x0345}, + { 0x1FA6, 0x1F66, 0x0345}, + { 0x1FA7, 0x1F67, 0x0345}, + { 0x1F6A, 0x1F68, 0x0300}, + { 0x1F6C, 0x1F68, 0x0301}, + { 0x1F6E, 0x1F68, 0x0342}, + { 0x1FA8, 0x1F68, 0x0345}, + { 0x1F6B, 0x1F69, 0x0300}, + { 0x1F6D, 0x1F69, 0x0301}, + { 0x1F6F, 0x1F69, 0x0342}, + { 0x1FA9, 0x1F69, 0x0345}, + { 0x1FAA, 0x1F6A, 0x0345}, + { 0x1FAB, 0x1F6B, 0x0345}, + { 0x1FAC, 0x1F6C, 0x0345}, + { 0x1FAD, 0x1F6D, 0x0345}, + { 0x1FAE, 0x1F6E, 0x0345}, + { 0x1FAF, 0x1F6F, 0x0345}, + { 0x1FB2, 0x1F70, 0x0345}, + { 0x1FC2, 0x1F74, 0x0345}, + { 0x1FF2, 0x1F7C, 0x0345}, + { 0x1FB7, 0x1FB6, 0x0345}, + { 0x1FCD, 0x1FBF, 0x0300}, + { 0x1FCE, 0x1FBF, 0x0301}, + { 0x1FCF, 0x1FBF, 0x0342}, + { 0x1FC7, 0x1FC6, 0x0345}, + { 0x1FF7, 0x1FF6, 0x0345}, + { 0x1FDD, 0x1FFE, 0x0300}, + { 0x1FDE, 0x1FFE, 0x0301}, + { 0x1FDF, 0x1FFE, 0x0342}, + { 0x219A, 0x2190, 0x0338}, + { 0x219B, 0x2192, 0x0338}, + { 0x21AE, 0x2194, 0x0338}, + { 0x21CD, 0x21D0, 0x0338}, + { 0x21CF, 0x21D2, 0x0338}, + { 0x21CE, 0x21D4, 0x0338}, + { 0x2204, 0x2203, 0x0338}, + { 0x2209, 0x2208, 0x0338}, + { 0x220C, 0x220B, 0x0338}, + { 0x2224, 0x2223, 0x0338}, + { 0x2226, 0x2225, 0x0338}, + { 0x2241, 0x223C, 0x0338}, + { 0x2244, 0x2243, 0x0338}, + { 0x2247, 0x2245, 0x0338}, + { 0x2249, 0x2248, 0x0338}, + { 0x226D, 0x224D, 0x0338}, + { 0x2262, 0x2261, 0x0338}, + { 0x2270, 0x2264, 0x0338}, + { 0x2271, 0x2265, 0x0338}, + { 0x2274, 0x2272, 0x0338}, + { 0x2275, 0x2273, 0x0338}, + { 0x2278, 0x2276, 0x0338}, + { 0x2279, 0x2277, 0x0338}, + { 0x2280, 0x227A, 0x0338}, + { 0x2281, 0x227B, 0x0338}, + { 0x22E0, 0x227C, 0x0338}, + { 0x22E1, 0x227D, 0x0338}, + { 0x2284, 0x2282, 0x0338}, + { 0x2285, 0x2283, 0x0338}, + { 0x2288, 0x2286, 0x0338}, + { 0x2289, 0x2287, 0x0338}, + { 0x22E2, 0x2291, 0x0338}, + { 0x22E3, 0x2292, 0x0338}, + { 0x22AC, 0x22A2, 0x0338}, + { 0x22AD, 0x22A8, 0x0338}, + { 0x22AE, 0x22A9, 0x0338}, + { 0x22AF, 0x22AB, 0x0338}, + { 0x22EA, 0x22B2, 0x0338}, + { 0x22EB, 0x22B3, 0x0338}, + { 0x22EC, 0x22B4, 0x0338}, + { 0x22ED, 0x22B5, 0x0338}, + { 0x2ADC, 0x2ADD, 0x0338}, + { 0x3094, 0x3046, 0x3099}, + { 0x304C, 0x304B, 0x3099}, + { 0x304E, 0x304D, 0x3099}, + { 0x3050, 0x304F, 0x3099}, + { 0x3052, 0x3051, 0x3099}, + { 0x3054, 0x3053, 0x3099}, + { 0x3056, 0x3055, 0x3099}, + { 0x3058, 0x3057, 0x3099}, + { 0x305A, 0x3059, 0x3099}, + { 0x305C, 0x305B, 0x3099}, + { 0x305E, 0x305D, 0x3099}, + { 0x3060, 0x305F, 0x3099}, + { 0x3062, 0x3061, 0x3099}, + { 0x3065, 0x3064, 0x3099}, + { 0x3067, 0x3066, 0x3099}, + { 0x3069, 0x3068, 0x3099}, + { 0x3070, 0x306F, 0x3099}, + { 0x3071, 0x306F, 0x309A}, + { 0x3073, 0x3072, 0x3099}, + { 0x3074, 0x3072, 0x309A}, + { 0x3076, 0x3075, 0x3099}, + { 0x3077, 0x3075, 0x309A}, + { 0x3079, 0x3078, 0x3099}, + { 0x307A, 0x3078, 0x309A}, + { 0x307C, 0x307B, 0x3099}, + { 0x307D, 0x307B, 0x309A}, + { 0x309E, 0x309D, 0x3099}, + { 0x30F4, 0x30A6, 0x3099}, + { 0x30AC, 0x30AB, 0x3099}, + { 0x30AE, 0x30AD, 0x3099}, + { 0x30B0, 0x30AF, 0x3099}, + { 0x30B2, 0x30B1, 0x3099}, + { 0x30B4, 0x30B3, 0x3099}, + { 0x30B6, 0x30B5, 0x3099}, + { 0x30B8, 0x30B7, 0x3099}, + { 0x30BA, 0x30B9, 0x3099}, + { 0x30BC, 0x30BB, 0x3099}, + { 0x30BE, 0x30BD, 0x3099}, + { 0x30C0, 0x30BF, 0x3099}, + { 0x30C2, 0x30C1, 0x3099}, + { 0x30C5, 0x30C4, 0x3099}, + { 0x30C7, 0x30C6, 0x3099}, + { 0x30C9, 0x30C8, 0x3099}, + { 0x30D0, 0x30CF, 0x3099}, + { 0x30D1, 0x30CF, 0x309A}, + { 0x30D3, 0x30D2, 0x3099}, + { 0x30D4, 0x30D2, 0x309A}, + { 0x30D6, 0x30D5, 0x3099}, + { 0x30D7, 0x30D5, 0x309A}, + { 0x30D9, 0x30D8, 0x3099}, + { 0x30DA, 0x30D8, 0x309A}, + { 0x30DC, 0x30DB, 0x3099}, + { 0x30DD, 0x30DB, 0x309A}, + { 0x30F7, 0x30EF, 0x3099}, + { 0x30F8, 0x30F0, 0x3099}, + { 0x30F9, 0x30F1, 0x3099}, + { 0x30FA, 0x30F2, 0x3099}, + { 0x30FE, 0x30FD, 0x3099}, + { 0xFB2C, 0xFB49, 0x05C1}, + { 0xFB2D, 0xFB49, 0x05C2}, + }; + + private static final int UNICODE_SHIFT = 21; + + public static char precompose(char base, char comb) { + int min = 0; + int max = precompositions.length - 1; + int mid; + long sought = base << UNICODE_SHIFT | comb; + long that; + + while (max >= min) { + mid = (min + max) / 2; + that = precompositions[mid][1] << UNICODE_SHIFT | precompositions[mid][2]; + + if (that < sought) + min = mid + 1; + else if (that > sought) + max = mid - 1; + else + return precompositions[mid][0]; + } + + // No match; return character without combiner + return base; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/de/mud/terminal/VDUBuffer.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,880 @@ +/* + * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". + * + * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved. + * + * Please visit http://javatelnet.org/ for updates and contact. + * + * --LICENSE NOTICE-- + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --LICENSE NOTICE-- + * + */ + +package de.mud.terminal; + +import java.util.Arrays; + +/** + * Implementation of a Video Display Unit (VDU) buffer. This class contains + * all methods to manipulate the buffer that stores characters and their + * attributes as well as the regions displayed. + * + * @author Matthias L. Jugel, Marcus Meißner + * @version $Id: VDUBuffer.java 503 2005-10-24 07:34:13Z marcus $ + */ +public class VDUBuffer { + + /** a generic display that should redraw on demand */ + protected VDUDisplay display; + + /** Enable debug messages. */ + public final static int debug = 0; + + public int height, width; /* rows and columns */ + public boolean[] update; /* contains the lines that need update */ + public char[][] charArray; /* contains the characters */ + public int[][] charAttributes; /* contains character attrs */ + public int bufSize; + public int maxBufSize; /* buffer sizes */ + public int screenBase; /* the actual screen start */ + public int windowBase; /* where the start displaying */ + public int scrollMarker; /* marks the last line inserted */ + + private int topMargin; /* top scroll margin */ + private int bottomMargin; /* bottom scroll margin */ + + // cursor variables + protected boolean showcursor = true; + protected int cursorX, cursorY; + + /** Scroll up when inserting a line. */ + public final static boolean SCROLL_UP = false; + /** Scroll down when inserting a line. */ + public final static boolean SCROLL_DOWN = true; + + /* Attributes bit-field usage: + * + * 8421 8421 8421 8421 8421 8421 8421 8421 + * |||| |||| |||| |||| |||| |||| |||| |||`- Bold + * |||| |||| |||| |||| |||| |||| |||| ||`-- Underline + * |||| |||| |||| |||| |||| |||| |||| |`--- Invert + * |||| |||| |||| |||| |||| |||| |||| `---- Low + * |||| |||| |||| |||| |||| |||| |||`------ Invisible + * |||| |||| |||| |||| ||`+-++++-+++------- Foreground Color + * |||| |||| |`++-++++-++------------------ Background Color + * |||| |||| `----------------------------- Fullwidth character + * `+++-++++------------------------------- Reserved for future use + */ + + /** Make character normal. */ + public final static int NORMAL = 0x00; + /** Make character bold. */ + public final static int BOLD = 0x01; + /** Underline character. */ + public final static int UNDERLINE = 0x02; + /** Invert character. */ + public final static int INVERT = 0x04; + /** Lower intensity character. */ + public final static int LOW = 0x08; + /** Invisible character. */ + public final static int INVISIBLE = 0x10; + /** Unicode full-width character (CJK, et al.) */ + public final static int FULLWIDTH = 0x8000000; + + /** how much to left shift the foreground color */ + public final static int COLOR_FG_SHIFT = 5; + /** how much to left shift the background color */ + public final static int COLOR_BG_SHIFT = 14; + /** color mask */ + public final static int COLOR = 0x7fffe0; /* 0000 0000 0111 1111 1111 1111 1110 0000 */ + /** foreground color mask */ + public final static int COLOR_FG = 0x003fe0; /* 0000 0000 0000 0000 0011 1111 1110 0000 */ + /** background color mask */ + public final static int COLOR_BG = 0x7fc000; /* 0000 0000 0111 1111 1100 0000 0000 0000 */ + + /** + * Create a new video display buffer with the passed width and height in + * characters. + * @param width the length of the character lines + * @param height the amount of lines on the screen + */ + public VDUBuffer(int width, int height) { + // set the display screen size + setScreenSize(width, height, false); + } + + /** + * Create a standard video display buffer with 80 columns and 24 lines. + */ + public VDUBuffer() { + this(80, 24); + } + + /** + * Put a character on the screen with normal font and outline. + * The character previously on that position will be overwritten. + * You need to call redraw() to update the screen. + * @param c x-coordinate (column) + * @param l y-coordinate (line) + * @param ch the character to show on the screen + * @see #insertChar + * @see #deleteChar + * @see #redraw + */ + public void putChar(int c, int l, char ch) { + putChar(c, l, ch, NORMAL); + } + + /** + * Put a character on the screen with specific font and outline. + * The character previously on that position will be overwritten. + * You need to call redraw() to update the screen. + * @param c x-coordinate (column) + * @param l y-coordinate (line) + * @param ch the character to show on the screen + * @param attributes the character attributes + * @see #BOLD + * @see #UNDERLINE + * @see #INVERT + * @see #INVISIBLE + * @see #NORMAL + * @see #LOW + * @see #insertChar + * @see #deleteChar + * @see #redraw + */ + + public void putChar(int c, int l, char ch, int attributes) { + int ll = screenBase + l; + + if ((ll >= bufSize) || (c >= width)) return; // ignore characters outside our buffer + + charArray[ll][c] = ch; + charAttributes[ll][c] = attributes; + + if (l < height) + update[l + 1] = true; + } + + /** + * Get the character at the specified position. + * @param c x-coordinate (column) + * @param l y-coordinate (line) + * @see #putChar + */ + public char getChar(int c, int l) { + return charArray[screenBase + l][c]; + } + + /** + * Get the attributes for the specified position. + * @param c x-coordinate (column) + * @param l y-coordinate (line) + * @see #putChar + */ + public int getAttributes(int c, int l) { + return charAttributes[screenBase + l][c]; + } + + /** + * Insert a character at a specific position on the screen. + * All character right to from this position will be moved one to the right. + * You need to call redraw() to update the screen. + * @param c x-coordinate (column) + * @param l y-coordinate (line) + * @param ch the character to insert + * @param attributes the character attributes + * @see #BOLD + * @see #UNDERLINE + * @see #INVERT + * @see #INVISIBLE + * @see #NORMAL + * @see #LOW + * @see #putChar + * @see #deleteChar + * @see #redraw + */ + public void insertChar(int c, int l, char ch, int attributes) { + System.arraycopy(charArray[screenBase + l], c, + charArray[screenBase + l], c + 1, width - c - 1); + System.arraycopy(charAttributes[screenBase + l], c, + charAttributes[screenBase + l], c + 1, width - c - 1); + putChar(c, l, ch, attributes); + } + + /** + * Delete a character at a given position on the screen. + * All characters right to the position will be moved one to the left. + * You need to call redraw() to update the screen. + * @param c x-coordinate (column) + * @param l y-coordinate (line) + * @see #putChar + * @see #insertChar + * @see #redraw + */ + public void deleteChar(int c, int l) { + if (c < width - 1) { + System.arraycopy(charArray[screenBase + l], c + 1, + charArray[screenBase + l], c, width - c - 1); + System.arraycopy(charAttributes[screenBase + l], c + 1, + charAttributes[screenBase + l], c, width - c - 1); + } + + putChar(width - 1, l, (char) 0); + } + + /** + * Put a String at a specific position. Any characters previously on that + * position will be overwritten. You need to call redraw() for screen update. + * @param c x-coordinate (column) + * @param l y-coordinate (line) + * @param s the string to be shown on the screen + * @see #BOLD + * @see #UNDERLINE + * @see #INVERT + * @see #INVISIBLE + * @see #NORMAL + * @see #LOW + * @see #putChar + * @see #insertLine + * @see #deleteLine + * @see #redraw + */ + public void putString(int c, int l, String s) { + putString(c, l, s, NORMAL); + } + + /** + * Put a String at a specific position giving all characters the same + * attributes. Any characters previously on that position will be + * overwritten. You need to call redraw() to update the screen. + * @param c x-coordinate (column) + * @param l y-coordinate (line) + * @param s the string to be shown on the screen + * @param attributes character attributes + * @see #BOLD + * @see #UNDERLINE + * @see #INVERT + * @see #INVISIBLE + * @see #NORMAL + * @see #LOW + * @see #putChar + * @see #insertLine + * @see #deleteLine + * @see #redraw + */ + public void putString(int c, int l, String s, int attributes) { + for (int i = 0; i < s.length() && c + i < width; i++) + putChar(c + i, l, s.charAt(i), attributes); + } + + /** + * Insert a blank line at a specific position. + * The current line and all previous lines are scrolled one line up. The + * top line is lost. You need to call redraw() to update the screen. + * @param l the y-coordinate to insert the line + * @see #deleteLine + * @see #redraw + */ + public void insertLine(int l) { + insertLine(l, 1, SCROLL_UP); + } + + /** + * Insert blank lines at a specific position. + * You need to call redraw() to update the screen + * @param l the y-coordinate to insert the line + * @param n amount of lines to be inserted + * @see #deleteLine + * @see #redraw + */ + public void insertLine(int l, int n) { + insertLine(l, n, SCROLL_UP); + } + + /** + * Insert a blank line at a specific position. Scroll text according to + * the argument. + * You need to call redraw() to update the screen + * @param l the y-coordinate to insert the line + * @param scrollDown scroll down + * @see #deleteLine + * @see #SCROLL_UP + * @see #SCROLL_DOWN + * @see #redraw + */ + public void insertLine(int l, boolean scrollDown) { + insertLine(l, 1, scrollDown); + } + + /** + * Insert blank lines at a specific position. + * The current line and all previous lines are scrolled one line up. The + * top line is lost. You need to call redraw() to update the screen. + * @param l the y-coordinate to insert the line + * @param n number of lines to be inserted + * @param scrollDown scroll down + * @see #deleteLine + * @see #SCROLL_UP + * @see #SCROLL_DOWN + * @see #redraw + */ + + public synchronized void insertLine(int l, int n, boolean scrollDown) { + char cbuf[][] = null; + int abuf[][] = null; + int offset = 0; + int oldBase = screenBase; + int newScreenBase = screenBase; + int newWindowBase = windowBase; + int newBufSize = bufSize; + + if (l > bottomMargin) /* We do not scroll below bottom margin (below the scrolling region). */ + return; + + int top = (l < topMargin ? + 0 : (l > bottomMargin ? + (bottomMargin + 1 < height ? + bottomMargin + 1 : height - 1) : topMargin)); + int bottom = (l > bottomMargin ? + height - 1 : (l < topMargin ? + (topMargin > 0 ? + topMargin - 1 : 0) : bottomMargin)); + + // System.out.println("l is "+l+", top is "+top+", bottom is "+bottom+", bottomargin is "+bottomMargin+", topMargin is "+topMargin); + if (scrollDown) { + if (n > (bottom - top)) n = (bottom - top); + + int size = bottom - l - (n - 1); + + if (size < 0) size = 0; + + cbuf = new char[size][]; + abuf = new int[size][]; + System.arraycopy(charArray, oldBase + l, cbuf, 0, bottom - l - (n - 1)); + System.arraycopy(charAttributes, oldBase + l, + abuf, 0, bottom - l - (n - 1)); + System.arraycopy(cbuf, 0, charArray, oldBase + l + n, + bottom - l - (n - 1)); + System.arraycopy(abuf, 0, charAttributes, oldBase + l + n, + bottom - l - (n - 1)); + cbuf = charArray; + abuf = charAttributes; + } + else { + try { + if (n > (bottom - top) + 1) n = (bottom - top) + 1; + + if (bufSize < maxBufSize) { + if (bufSize + n > maxBufSize) { + offset = n - (maxBufSize - bufSize); + scrollMarker += offset; + newBufSize = maxBufSize; + newScreenBase = maxBufSize - height - 1; + newWindowBase = screenBase; + } + else { + scrollMarker += n; + newScreenBase += n; + newWindowBase += n; + newBufSize += n; + } + + cbuf = new char[newBufSize][]; + abuf = new int[newBufSize][]; + } + else { + offset = n; + cbuf = charArray; + abuf = charAttributes; + } + + // copy anything from the top of the buffer (+offset) to the new top + // up to the screenBase. + if (oldBase > 0) { + System.arraycopy(charArray, offset, + cbuf, 0, + oldBase - offset); + System.arraycopy(charAttributes, offset, + abuf, 0, + oldBase - offset); + } + + // copy anything from the top of the screen (screenBase) up to the + // topMargin to the new screen + if (top > 0) { + System.arraycopy(charArray, oldBase, + cbuf, newScreenBase, + top); + System.arraycopy(charAttributes, oldBase, + abuf, newScreenBase, + top); + } + + // copy anything from the topMargin up to the amount of lines inserted + // to the gap left over between scrollback buffer and screenBase + if (oldBase >= 0) { + System.arraycopy(charArray, oldBase + top, + cbuf, oldBase - offset, + n); + System.arraycopy(charAttributes, oldBase + top, + abuf, oldBase - offset, + n); + } + + // copy anything from topMargin + n up to the line linserted to the + // topMargin + System.arraycopy(charArray, oldBase + top + n, + cbuf, newScreenBase + top, + l - top - (n - 1)); + System.arraycopy(charAttributes, oldBase + top + n, + abuf, newScreenBase + top, + l - top - (n - 1)); + + // + // copy the all lines next to the inserted to the new buffer + if (l < height - 1) { + System.arraycopy(charArray, oldBase + l + 1, + cbuf, newScreenBase + l + 1, + (height - 1) - l); + System.arraycopy(charAttributes, oldBase + l + 1, + abuf, newScreenBase + l + 1, + (height - 1) - l); + } + } + catch (ArrayIndexOutOfBoundsException e) { + // this should not happen anymore, but I will leave the code + // here in case something happens anyway. That code above is + // so complex I always have a hard time understanding what + // I did, even though there are comments + System.err.println("*** Error while scrolling up:"); + System.err.println("--- BEGIN STACK TRACE ---"); + e.printStackTrace(); + System.err.println("--- END STACK TRACE ---"); + System.err.println("bufSize=" + bufSize + ", maxBufSize=" + maxBufSize); + System.err.println("top=" + top + ", bottom=" + bottom); + System.err.println("n=" + n + ", l=" + l); + System.err.println("screenBase=" + screenBase + ", windowBase=" + windowBase); + System.err.println("newScreenBase=" + newScreenBase + ", newWindowBase=" + newWindowBase); + System.err.println("oldBase=" + oldBase); + System.err.println("size.width=" + width + ", size.height=" + height); + System.err.println("abuf.length=" + abuf.length + ", cbuf.length=" + cbuf.length); + System.err.println("*** done dumping debug information"); + } + } + + // this is a little helper to mark the scrolling + scrollMarker -= n; + + for (int i = 0; i < n; i++) { + cbuf[(newScreenBase + l) + (scrollDown ? i : -i)] = new char[width]; + Arrays.fill(cbuf[(newScreenBase + l) + (scrollDown ? i : -i)], ' '); + abuf[(newScreenBase + l) + (scrollDown ? i : -i)] = new int[width]; + } + + charArray = cbuf; + charAttributes = abuf; + screenBase = newScreenBase; + windowBase = newWindowBase; + bufSize = newBufSize; + + if (scrollDown) + markLine(l, bottom - l + 1); + else + markLine(top, l - top + 1); + + display.updateScrollBar(); + } + + /** + * Delete a line at a specific position. Subsequent lines will be scrolled + * up to fill the space and a blank line is inserted at the end of the + * screen. + * @param l the y-coordinate to insert the line + * @see #deleteLine + */ + public void deleteLine(int l) { + int bottom = (l > bottomMargin ? height - 1 : + (l < topMargin ? topMargin : bottomMargin + 1)); + int numRows = bottom - l - 1; + char[] discardedChars = charArray[screenBase + l]; + int[] discardedAttributes = charAttributes[screenBase + l]; + + if (numRows > 0) { + System.arraycopy(charArray, screenBase + l + 1, + charArray, screenBase + l, numRows); + System.arraycopy(charAttributes, screenBase + l + 1, + charAttributes, screenBase + l, numRows); + } + + int newBottomRow = screenBase + bottom - 1; + charArray[newBottomRow] = discardedChars; + charAttributes[newBottomRow] = discardedAttributes; + Arrays.fill(charArray[newBottomRow], ' '); + Arrays.fill(charAttributes[newBottomRow], 0); + markLine(l, bottom - l); + } + + /** + * Delete a rectangular portion of the screen. + * You need to call redraw() to update the screen. + * @param c x-coordinate (column) + * @param l y-coordinate (row) + * @param w with of the area in characters + * @param h height of the area in characters + * @param curAttr attribute to fill + * @see #deleteChar + * @see #deleteLine + * @see #redraw + */ + public void deleteArea(int c, int l, int w, int h, int curAttr) { + int endColumn = c + w; + int targetRow = screenBase + l; + + for (int i = 0; i < h && l + i < height; i++) { + Arrays.fill(charAttributes[targetRow], c, endColumn, curAttr); + Arrays.fill(charArray[targetRow], c, endColumn, ' '); + targetRow++; + } + + markLine(l, h); + } + + /** + * Delete a rectangular portion of the screen. + * You need to call redraw() to update the screen. + * @param c x-coordinate (column) + * @param l y-coordinate (row) + * @param w with of the area in characters + * @param h height of the area in characters + * @see #deleteChar + * @see #deleteLine + * @see #redraw + */ + public void deleteArea(int c, int l, int w, int h) { + deleteArea(c, l, w, h, 0); + } + + /** + * Sets whether the cursor is visible or not. + * @param doshow + */ + public void showCursor(boolean doshow) { + showcursor = doshow; + } + + /** + * Check whether the cursor is currently visible. + * @return visibility + */ + public boolean isCursorVisible() { + return showcursor; + } + + /** + * Puts the cursor at the specified position. + * @param c column + * @param l line + */ + public void setCursorPosition(int c, int l) { + cursorX = (c > width - 1) ? width - 1 : c; + cursorY = (l > height - 1) ? height - 1 : l; + } + + /** + * Get the current column of the cursor position. + */ + public int getCursorColumn() { + return cursorX; + } + + /** + * Get the current line of the cursor position. + */ + public int getCursorRow() { + return cursorY; + } + + /** + * Set the current window base. This allows to view the scrollback buffer. + * @param line the line where the screen window starts + * @see #setBufferSize + * @see #getBufferSize + */ + public void setWindowBase(int line) { + if (line > screenBase) + line = screenBase; + else if (line < 0) line = 0; + + windowBase = line; + update[0] = true; + redraw(); + } + + /** + * Get the current window base. + * @see #setWindowBase + */ + public int getWindowBase() { + return windowBase; + } + + /** + * Set the scroll margins simultaneously. If they're out of bounds, trim them. + * @param l1 line that is the top + * @param l2 line that is the bottom + */ + public void setMargins(int l1, int l2) { + if (l1 > l2) + return; + + if (l1 < 0) + l1 = 0; + + if (l2 >= height) + l2 = height - 1; + + topMargin = l1; + bottomMargin = l2; + } + + /** + * Set the top scroll margin for the screen. If the current bottom margin + * is smaller it will become the top margin and the line will become the + * bottom margin. + * @param l line that is the margin + */ + public void setTopMargin(int l) { + if (l > bottomMargin) { + topMargin = bottomMargin; + bottomMargin = l; + } + else + topMargin = l; + + if (topMargin < 0) topMargin = 0; + + if (bottomMargin >= height) bottomMargin = height - 1; + } + + /** + * Get the top scroll margin. + */ + public int getTopMargin() { + return topMargin; + } + + /** + * Set the bottom scroll margin for the screen. If the current top margin + * is bigger it will become the bottom margin and the line will become the + * top margin. + * @param l line that is the margin + */ + public void setBottomMargin(int l) { + if (l < topMargin) { + bottomMargin = topMargin; + topMargin = l; + } + else + bottomMargin = l; + + if (topMargin < 0) topMargin = 0; + + if (bottomMargin >= height) bottomMargin = height - 1; + } + + /** + * Get the bottom scroll margin. + */ + public int getBottomMargin() { + return bottomMargin; + } + + /** + * Set scrollback buffer size. + * @param amount new size of the buffer + */ + public void setBufferSize(int amount) { + if (amount < height) amount = height; + + if (amount < maxBufSize) { + char cbuf[][] = new char[amount][width]; + int abuf[][] = new int[amount][width]; + int copyStart = bufSize - amount < 0 ? 0 : bufSize - amount; + int copyCount = bufSize - amount < 0 ? bufSize : amount; + + if (charArray != null) + System.arraycopy(charArray, copyStart, cbuf, 0, copyCount); + + if (charAttributes != null) + System.arraycopy(charAttributes, copyStart, abuf, 0, copyCount); + + charArray = cbuf; + charAttributes = abuf; + bufSize = copyCount; + screenBase = bufSize - height; + windowBase = screenBase; + } + + maxBufSize = amount; + update[0] = true; + redraw(); + } + + /** + * Retrieve current scrollback buffer size. + * @see #setBufferSize + */ + public int getBufferSize() { + return bufSize; + } + + /** + * Retrieve maximum buffer Size. + * @see #getBufferSize + */ + public int getMaxBufferSize() { + return maxBufSize; + } + + /** + * Change the size of the screen. This will include adjustment of the + * scrollback buffer. + * @param w of the screen + * @param h of the screen + */ + public void setScreenSize(int w, int h, boolean broadcast) { + char cbuf[][]; + int abuf[][]; + int maxSize = bufSize; + + if (w < 1 || h < 1) return; + + if (debug > 0) + System.err.println("VDU: screen size [" + w + "," + h + "]"); + + if (h > maxBufSize) + maxBufSize = h; + + if (h > bufSize) { + bufSize = h; + screenBase = 0; + windowBase = 0; + } + + if (windowBase + h >= bufSize) + windowBase = bufSize - h; + + if (screenBase + h >= bufSize) + screenBase = bufSize - h; + + cbuf = new char[bufSize][w]; + abuf = new int[bufSize][w]; + + for (int i = 0; i < bufSize; i++) { + Arrays.fill(cbuf[i], ' '); + } + + if (bufSize < maxSize) + maxSize = bufSize; + + int rowLength; + + if (charArray != null && charAttributes != null) { + for (int i = 0; i < maxSize && charArray[i] != null; i++) { + rowLength = charArray[i].length; + System.arraycopy(charArray[i], 0, cbuf[i], 0, + w < rowLength ? w : rowLength); + System.arraycopy(charAttributes[i], 0, abuf[i], 0, + w < rowLength ? w : rowLength); + } + } + + int C = getCursorColumn(); + + if (C < 0) + C = 0; + else if (C >= width) + C = width - 1; + + int R = getCursorRow(); + + if (R < 0) + R = 0; + else if (R >= height) + R = height - 1; + + setCursorPosition(C, R); + charArray = cbuf; + charAttributes = abuf; + width = w; + height = h; + topMargin = 0; + bottomMargin = h - 1; + update = new boolean[h + 1]; + update[0] = true; + /* FIXME: ??? + if(resizeStrategy == RESIZE_FONT) + setBounds(getBounds()); + */ + } + + /** + * Get amount of rows on the screen. + */ + public int getRows() { + return height; + } + + /** + * Get amount of columns on the screen. + */ + public int getColumns() { + return width; + } + + /** + * Mark lines to be updated with redraw(). + * @param l starting line + * @param n amount of lines to be updated + * @see #redraw + */ + public void markLine(int l, int n) { + for (int i = 0; (i < n) && (l + i < height); i++) + update[l + i + 1] = true; + } + +// private static int checkBounds(int value, int lower, int upper) { +// if (value < lower) +// return lower; +// else if (value > upper) +// return upper; +// else +// return value; +// } + + public void setDisplay(VDUDisplay display) { + this.display = display; + } + + /** + * Trigger a redraw on the display. + */ + protected void redraw() { + if (display != null) + display.redraw(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/de/mud/terminal/VDUDisplay.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,37 @@ +/* + * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". + * + * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved. + * + * Please visit http://javatelnet.org/ for updates and contact. + * + * --LICENSE NOTICE-- + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --LICENSE NOTICE-- + * + */ + +package de.mud.terminal; + +/** + * Generic display + */ +public interface VDUDisplay { + public void redraw(); + public void updateScrollBar(); + + public void setColor(int index, int red, int green, int blue); + public void resetColors(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/de/mud/terminal/VDUInput.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,82 @@ +/* + * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". + * + * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved. + * + * Please visit http://javatelnet.org/ for updates and contact. + * + * --LICENSE NOTICE-- + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --LICENSE NOTICE-- + * + */ +package de.mud.terminal; + +import java.util.Properties; + +/** + * An interface for a terminal that accepts input from keyboard and mouse. + * + * @author Matthias L. Jugel, Marcus Meißner + * @version $Id: VDUInput.java 499 2005-09-29 08:24:54Z leo $ + */ +public interface VDUInput { + + public final static int KEY_CONTROL = 0x01; + public final static int KEY_SHIFT = 0x02; + public final static int KEY_ALT = 0x04; + public final static int KEY_ACTION = 0x08; + + + + /** + * Direct access to writing data ... + * @param b + */ + void write(byte b[]); + + /** + * Terminal is mouse-aware and requires (x,y) coordinates of + * on the terminal (character coordinates) and the button clicked. + * @param x + * @param y + * @param modifiers + */ + void mousePressed(int x, int y, int modifiers); + + /** + * Terminal is mouse-aware and requires the coordinates and button + * of the release. + * @param x + * @param y + * @param modifiers + */ + void mouseReleased(int x, int y, int modifiers); + + /** + * Override the standard key codes used by the terminal emulation. + * @param codes a properties object containing key code definitions + */ + void setKeyCodes(Properties codes); + + /** + * keytyping event handler for all the special function and modifier keys + * @param keyCode the key code + * @param keyChar the character represented by the key + * @param modifiers shift/alt/control modifiers + */ + void keyPressed(int keyCode, char keyChar, int modifiers); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/de/mud/terminal/vt320.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,3423 @@ +/* + * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". + * + * (c) Matthias L. Jugel, Marcus Meiner 1996-2005. All Rights Reserved. + * + * Please visit http://javatelnet.org/ for updates and contact. + * + * --LICENSE NOTICE-- + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --LICENSE NOTICE-- + * + */ + +package de.mud.terminal; + +import android.text.AndroidCharacter; + +import java.util.Properties; + +/** + * Implementation of a VT terminal emulation plus ANSI compatible. + * <P> + * <B>Maintainer:</B> Marcus Meißner + * + * @version $Id: vt320.java 507 2005-10-25 10:14:52Z marcus $ + * @author Matthias L. Jugel, Marcus Meißner + */ +public abstract class vt320 extends VDUBuffer implements VDUInput { + + /** the debug level */ + private final static int debug = 0; + private StringBuilder debugStr; + public abstract void debug(String notice); + + /** + * Write an answer back to the remote host. This is needed to be able to + * send terminal answers requests like status and type information. + * @param b the array of bytes to be sent + */ + public abstract void write(byte[] b); + + /** + * Write an answer back to the remote host. This is needed to be able to + * send terminal answers requests like status and type information. + * @param b the byte to be sent + */ + public abstract void write(int b); + + /** + * No more bytes to read from the transport, hook here to test screen changes + */ + public void testChanged() { + /* do nothing by default */ + } + + /** + * inject field contents as if typed + */ + public void setField(int l, int c, char [] d) { + // ignore line and column, just send the bytes to the host. + int n = d.length; + byte [] b = new byte [n]; + + for (int i = 0; i < n; i++) b[i] = (byte)(d[i] & 0x00ff); + + write(b); + } + + public void monitorKey(boolean down) { + // do nothing + } + + public void keyDepressed(int keyCode, char keyChar, int modifiers) { + keyPressed(keyCode, keyChar, modifiers); + } + + /** + * Play the beep sound ... + */ + public void beep() { + /* do nothing by default */ + } + + public void redrawPassthru() { + redraw(); // VDUBuffer.redraw is protected + } + + /** + * Convenience function for putString(char[], int, int) + */ + public void putString(String s) { + int len = s.length(); + char[] tmp = new char[len]; + s.getChars(0, len, tmp, 0); + putString(tmp, null, 0, len); + } + + /** + * Put string at current cursor position. Moves cursor + * according to the String. Does NOT wrap. + * @param s character array + * @param start place to start in array + * @param len number of characters to process + */ + public void putString(char[] s, byte[] fullwidths, int start, int len) { + if (len > 0) { + //markLine(R, 1); + int lastChar = -1; + char c; + boolean isWide = false; + + for (int i = 0; i < len; i++) { + c = s[start + i]; + + // Shortcut for my favorite ASCII + if (c <= 0x7F) { + if (lastChar != -1) + putChar((char) lastChar, isWide, false); + + lastChar = c; + isWide = false; + } + else if (!Character.isLowSurrogate(c) && !Character.isHighSurrogate(c)) { + if (Character.getType(c) == Character.NON_SPACING_MARK) { + if (lastChar != -1) { + char nc = Precomposer.precompose((char) lastChar, c); + putChar(nc, isWide, false); + lastChar = -1; + } + } + else { + if (lastChar != -1) + putChar((char) lastChar, isWide, false); + + lastChar = c; + + if (fullwidths != null) { + final byte width = fullwidths[i]; + isWide = (width == AndroidCharacter.EAST_ASIAN_WIDTH_WIDE) + || (width == AndroidCharacter.EAST_ASIAN_WIDTH_FULL_WIDTH); + } + } + } + } + + if (lastChar != -1) + putChar((char) lastChar, isWide, false); + + setCursorPosition(C, R); + redraw(); + } + } + + protected void sendTelnetCommand(byte cmd) { + /* do nothing by default */ + } + + /** + * Sent the changed window size from the terminal to all listeners. + */ + protected void setWindowSize(int c, int r) { + /* To be overridden by Terminal.java */ + } + + @Override + public void setScreenSize(int c, int r, boolean broadcast) { + int oldrows = height; + + if (debug > 2) { + if (debugStr == null) + debugStr = new StringBuilder(); + + debugStr.append("setscreensize (") + .append(c) + .append(',') + .append(r) + .append(',') + .append(broadcast) + .append(')'); + debug(debugStr.toString()); + debugStr.setLength(0); + } + + super.setScreenSize(c, r, false); + boolean cursorChanged = false; + + // Don't let the cursor go off the screen. + if (C >= c) { + C = c - 1; + cursorChanged = true; + } + + if (R >= r) { + R = r - 1; + cursorChanged = true; + } + + if (cursorChanged) { + setCursorPosition(C, R); + redraw(); + } + + if (broadcast) { + setWindowSize(c, r); /* broadcast up */ + } + } + + + /** + * Create a new vt320 terminal and intialize it with useful settings. + */ + public vt320(int width, int height) { + super(width, height); + debugStr = new StringBuilder(); + setVMS(false); + setIBMCharset(false); + setTerminalID("vt320"); + setBufferSize(100); + //setBorder(2, false); + gx = new char[4]; + reset(); + /* top row of numpad */ + PF1 = "\u001bOP"; + PF2 = "\u001bOQ"; + PF3 = "\u001bOR"; + PF4 = "\u001bOS"; + /* the 3x2 keyblock on PC keyboards */ + Insert = new String[4]; + Remove = new String[4]; + KeyHome = new String[4]; + KeyEnd = new String[4]; + NextScn = new String[4]; + PrevScn = new String[4]; + Escape = new String[4]; + BackSpace = new String[4]; + TabKey = new String[4]; + Insert[0] = Insert[1] = Insert[2] = Insert[3] = "\u001b[2~"; + Remove[0] = Remove[1] = Remove[2] = Remove[3] = "\u001b[3~"; + PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[5~"; + NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[6~"; + KeyHome[0] = KeyHome[1] = KeyHome[2] = KeyHome[3] = "\u001b[H"; + KeyEnd[0] = KeyEnd[1] = KeyEnd[2] = KeyEnd[3] = "\u001b[F"; + Escape[0] = Escape[1] = Escape[2] = Escape[3] = "\u001b"; + + if (vms) { + BackSpace[1] = "" + (char) 10; // VMS shift deletes word back + BackSpace[2] = "\u0018"; // VMS control deletes line back + BackSpace[0] = BackSpace[3] = "\u007f"; // VMS other is delete + } + else { + //BackSpace[0] = BackSpace[1] = BackSpace[2] = BackSpace[3] = "\b"; + // ConnectBot modifications. + BackSpace[0] = "\b"; + BackSpace[1] = "\u007f"; + BackSpace[2] = "\u001b[3~"; + BackSpace[3] = "\u001b[2~"; + } + + /* some more VT100 keys */ + Find = "\u001b[1~"; + Select = "\u001b[4~"; + Help = "\u001b[28~"; + Do = "\u001b[29~"; + FunctionKey = new String[21]; + FunctionKey[0] = ""; + FunctionKey[1] = PF1; + FunctionKey[2] = PF2; + FunctionKey[3] = PF3; + FunctionKey[4] = PF4; + /* following are defined differently for vt220 / vt132 ... */ + FunctionKey[5] = "\u001b[15~"; + FunctionKey[6] = "\u001b[17~"; + FunctionKey[7] = "\u001b[18~"; + FunctionKey[8] = "\u001b[19~"; + FunctionKey[9] = "\u001b[20~"; + FunctionKey[10] = "\u001b[21~"; + FunctionKey[11] = "\u001b[23~"; + FunctionKey[12] = "\u001b[24~"; + FunctionKey[13] = "\u001b[25~"; + FunctionKey[14] = "\u001b[26~"; + FunctionKey[15] = Help; + FunctionKey[16] = Do; + FunctionKey[17] = "\u001b[31~"; + FunctionKey[18] = "\u001b[32~"; + FunctionKey[19] = "\u001b[33~"; + FunctionKey[20] = "\u001b[34~"; + FunctionKeyShift = new String[21]; + FunctionKeyAlt = new String[21]; + FunctionKeyCtrl = new String[21]; + + for (int i = 0; i < 20; i++) { + FunctionKeyShift[i] = ""; + FunctionKeyAlt[i] = ""; + FunctionKeyCtrl[i] = ""; + } + + FunctionKeyShift[15] = Find; + FunctionKeyShift[16] = Select; + TabKey[0] = "\u0009"; + TabKey[1] = "\u001bOP\u0009"; + TabKey[2] = TabKey[3] = ""; + KeyUp = new String[4]; + KeyUp[0] = "\u001b[A"; + KeyDown = new String[4]; + KeyDown[0] = "\u001b[B"; + KeyRight = new String[4]; + KeyRight[0] = "\u001b[C"; + KeyLeft = new String[4]; + KeyLeft[0] = "\u001b[D"; + Numpad = new String[10]; + Numpad[0] = "\u001bOp"; + Numpad[1] = "\u001bOq"; + Numpad[2] = "\u001bOr"; + Numpad[3] = "\u001bOs"; + Numpad[4] = "\u001bOt"; + Numpad[5] = "\u001bOu"; + Numpad[6] = "\u001bOv"; + Numpad[7] = "\u001bOw"; + Numpad[8] = "\u001bOx"; + Numpad[9] = "\u001bOy"; + KPMinus = PF4; + KPComma = "\u001bOl"; + KPPeriod = "\u001bOn"; + KPEnter = "\u001bOM"; + NUMPlus = new String[4]; + NUMPlus[0] = "+"; + NUMDot = new String[4]; + NUMDot[0] = "."; + } + + public void setBackspace(int type) { + switch (type) { + case DELETE_IS_DEL: + BackSpace[0] = "\u007f"; + BackSpace[1] = "\b"; + break; + + case DELETE_IS_BACKSPACE: + BackSpace[0] = "\b"; + BackSpace[1] = "\u007f"; + break; + } + } + + /** + * Create a default vt320 terminal with 80 columns and 24 lines. + */ + public vt320() { + this(80, 24); + } + + /** + * Terminal is mouse-aware and requires (x,y) coordinates of + * on the terminal (character coordinates) and the button clicked. + * @param x + * @param y + * @param modifiers + */ + public void mousePressed(int x, int y, int modifiers) { + if (mouserpt == 0) + return; + + int mods = modifiers; + mousebut = 3; + + if ((mods & 16) == 16) mousebut = 0; + + if ((mods & 8) == 8) mousebut = 1; + + if ((mods & 4) == 4) mousebut = 2; + + int mousecode; + + if (mouserpt == 9) /* X10 Mouse */ + mousecode = 0x20 | mousebut; + else /* normal xterm mouse reporting */ + mousecode = mousebut | 0x20 | ((mods & 7) << 2); + + byte b[] = new byte[6]; + b[0] = 27; + b[1] = (byte) '['; + b[2] = (byte) 'M'; + b[3] = (byte) mousecode; + b[4] = (byte)(0x20 + x + 1); + b[5] = (byte)(0x20 + y + 1); + write(b); // FIXME: writeSpecial here + } + + /** + * Terminal is mouse-aware and requires the coordinates and button + * of the release. + * @param x + * @param y + * @param modifiers + */ + public void mouseReleased(int x, int y, int modifiers) { + if (mouserpt == 0) + return; + + /* problem is tht modifiers still have the released button set in them. + int mods = modifiers; + mousebut = 3; + if ((mods & 16)==16) mousebut=0; + if ((mods & 8)==8 ) mousebut=1; + if ((mods & 4)==4 ) mousebut=2; + */ + int mousecode; + + if (mouserpt == 9) + mousecode = 0x20 + mousebut; /* same as press? appears so. */ + else + mousecode = '#'; + + byte b[] = new byte[6]; + b[0] = 27; + b[1] = (byte) '['; + b[2] = (byte) 'M'; + b[3] = (byte) mousecode; + b[4] = (byte)(0x20 + x + 1); + b[5] = (byte)(0x20 + y + 1); + write(b); // FIXME: writeSpecial here + mousebut = 0; + } + + + /** we should do localecho (passed from other modules). false is default */ + private boolean localecho = false; + + /** + * Enable or disable the local echo property of the terminal. + * @param echo true if the terminal should echo locally + */ + public void setLocalEcho(boolean echo) { + localecho = echo; + } + + /** + * Enable the VMS mode of the terminal to handle some things differently + * for VMS hosts. + * @param vms true for vms mode, false for normal mode + */ + public void setVMS(boolean vms) { + this.vms = vms; + } + + /** + * Enable the usage of the IBM character set used by some BBS's. Special + * graphical character are available in this mode. + * @param ibm true to use the ibm character set + */ + public void setIBMCharset(boolean ibm) { + useibmcharset = ibm; + } + + /** + * Override the standard key codes used by the terminal emulation. + * @param codes a properties object containing key code definitions + */ + public void setKeyCodes(Properties codes) { + String res, prefixes[] = {"", "S", "C", "A"}; + int i; + + for (i = 0; i < 10; i++) { + res = codes.getProperty("NUMPAD" + i); + + if (res != null) Numpad[i] = unEscape(res); + } + + for (i = 1; i < 20; i++) { + res = codes.getProperty("F" + i); + + if (res != null) FunctionKey[i] = unEscape(res); + + res = codes.getProperty("SF" + i); + + if (res != null) FunctionKeyShift[i] = unEscape(res); + + res = codes.getProperty("CF" + i); + + if (res != null) FunctionKeyCtrl[i] = unEscape(res); + + res = codes.getProperty("AF" + i); + + if (res != null) FunctionKeyAlt[i] = unEscape(res); + } + + for (i = 0; i < 4; i++) { + res = codes.getProperty(prefixes[i] + "PGUP"); + + if (res != null) PrevScn[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "PGDOWN"); + + if (res != null) NextScn[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "END"); + + if (res != null) KeyEnd[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "HOME"); + + if (res != null) KeyHome[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "INSERT"); + + if (res != null) Insert[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "REMOVE"); + + if (res != null) Remove[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "UP"); + + if (res != null) KeyUp[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "DOWN"); + + if (res != null) KeyDown[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "LEFT"); + + if (res != null) KeyLeft[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "RIGHT"); + + if (res != null) KeyRight[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "ESCAPE"); + + if (res != null) Escape[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "BACKSPACE"); + + if (res != null) BackSpace[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "TAB"); + + if (res != null) TabKey[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "NUMPLUS"); + + if (res != null) NUMPlus[i] = unEscape(res); + + res = codes.getProperty(prefixes[i] + "NUMDECIMAL"); + + if (res != null) NUMDot[i] = unEscape(res); + } + } + + /** + * Set the terminal id used to identify this terminal. + * @param terminalID the id string + */ + public void setTerminalID(String terminalID) { + this.terminalID = terminalID; + + if (terminalID.equals("scoansi")) { + FunctionKey[1] = "\u001b[M"; FunctionKey[2] = "\u001b[N"; + FunctionKey[3] = "\u001b[O"; FunctionKey[4] = "\u001b[P"; + FunctionKey[5] = "\u001b[Q"; FunctionKey[6] = "\u001b[R"; + FunctionKey[7] = "\u001b[S"; FunctionKey[8] = "\u001b[T"; + FunctionKey[9] = "\u001b[U"; FunctionKey[10] = "\u001b[V"; + FunctionKey[11] = "\u001b[W"; FunctionKey[12] = "\u001b[X"; + FunctionKey[13] = "\u001b[Y"; FunctionKey[14] = "?"; + FunctionKey[15] = "\u001b[a"; FunctionKey[16] = "\u001b[b"; + FunctionKey[17] = "\u001b[c"; FunctionKey[18] = "\u001b[d"; + FunctionKey[19] = "\u001b[e"; FunctionKey[20] = "\u001b[f"; + PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[I"; + NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[G"; + // more theoretically. + } + } + + public void setAnswerBack(String ab) { + this.answerBack = unEscape(ab); + } + + /** + * Get the terminal id used to identify this terminal. + */ + public String getTerminalID() { + return terminalID; + } + + /** + * A small conveniance method thar converts the string to a byte array + * for sending. + * @param s the string to be sent + */ + private boolean write(String s, boolean doecho) { + if (debug > 2) { + debugStr.append("write(|") + .append(s) + .append("|,") + .append(doecho); + debug(debugStr.toString()); + debugStr.setLength(0); + } + + if (s == null) // aka the empty string. + return true; + + /* NOTE: getBytes() honours some locale, it *CONVERTS* the string. + * However, we output only 7bit stuff towards the target, and *some* + * 8 bit control codes. We must not mess up the latter, so we do hand + * by hand copy. + */ + byte arr[] = new byte[s.length()]; + + for (int i = 0; i < s.length(); i++) { + arr[i] = (byte) s.charAt(i); + } + + write(arr); + + if (doecho) + putString(s); + + return true; + } + + private boolean write(int s, boolean doecho) { + if (debug > 2) { + debugStr.append("write(|") + .append(s) + .append("|,") + .append(doecho); + debug(debugStr.toString()); + debugStr.setLength(0); + } + + write(s); + + // TODO check if character is wide + if (doecho) + putChar((char)s, false, false); + + return true; + } + + private boolean write(String s) { + return write(s, localecho); + } + + // =================================================================== + // the actual terminal emulation code comes here: + // =================================================================== + + private String terminalID = "vt320"; + private String answerBack = "Use Terminal.answerback to set ...\n"; + + // X - COLUMNS, Y - ROWS + int R, C; + int attributes = 0; + + int Sc, Sr, Sa, Stm, Sbm; + char Sgr, Sgl; + char Sgx[]; + + int insertmode = 0; + int statusmode = 0; + boolean vt52mode = false; + boolean keypadmode = false; /* false - numeric, true - application */ + boolean output8bit = false; + int normalcursor = 0; + boolean moveoutsidemargins = true; + boolean wraparound = true; + boolean sendcrlf = true; + boolean capslock = false; + boolean numlock = false; + int mouserpt = 0; + byte mousebut = 0; + + boolean useibmcharset = false; + + int lastwaslf = 0; + boolean usedcharsets = false; + + private final static char ESC = 27; + private final static char IND = 132; + private final static char NEL = 133; + private final static char RI = 141; + private final static char SS2 = 142; + private final static char SS3 = 143; + private final static char DCS = 144; + private final static char HTS = 136; + private final static char CSI = 155; + private final static char OSC = 157; + private final static int TSTATE_DATA = 0; + private final static int TSTATE_ESC = 1; /* ESC */ + private final static int TSTATE_CSI = 2; /* ESC [ */ + private final static int TSTATE_DCS = 3; /* ESC P */ + private final static int TSTATE_DCEQ = 4; /* ESC [? */ + private final static int TSTATE_ESCSQUARE = 5; /* ESC # */ + private final static int TSTATE_OSC = 6; /* ESC ] */ + private final static int TSTATE_SETG0 = 7; /* ESC (? */ + private final static int TSTATE_SETG1 = 8; /* ESC )? */ + private final static int TSTATE_SETG2 = 9; /* ESC *? */ + private final static int TSTATE_SETG3 = 10; /* ESC +? */ + private final static int TSTATE_CSI_DOLLAR = 11; /* ESC [ Pn $ */ + private final static int TSTATE_CSI_EX = 12; /* ESC [ ! */ + private final static int TSTATE_ESCSPACE = 13; /* ESC <space> */ + private final static int TSTATE_VT52X = 14; + private final static int TSTATE_VT52Y = 15; + private final static int TSTATE_CSI_TICKS = 16; + private final static int TSTATE_CSI_EQUAL = 17; /* ESC [ = */ + private final static int TSTATE_TITLE = 18; /* xterm title */ + + /* Keys we support */ + public final static int KEY_PAUSE = 1; + public final static int KEY_F1 = 2; + public final static int KEY_F2 = 3; + public final static int KEY_F3 = 4; + public final static int KEY_F4 = 5; + public final static int KEY_F5 = 6; + public final static int KEY_F6 = 7; + public final static int KEY_F7 = 8; + public final static int KEY_F8 = 9; + public final static int KEY_F9 = 10; + public final static int KEY_F10 = 11; + public final static int KEY_F11 = 12; + public final static int KEY_F12 = 13; + public final static int KEY_F13 = 14; // only used by tn5250 + public final static int KEY_F14 = 15; // only used by tn5250 + public final static int KEY_F15 = 16; // only used by tn5250 + public final static int KEY_F16 = 17; // only used by tn5250 + public final static int KEY_F17 = 18; // only used by tn5250 + public final static int KEY_F18 = 19; // only used by tn5250 + public final static int KEY_F19 = 20; // only used by tn5250 + public final static int KEY_F20 = 21; // only used by tn5250 + public final static int KEY_F21 = 22; // only used by tn5250 + public final static int KEY_F22 = 23; // only used by tn5250 + public final static int KEY_F23 = 24; // only used by tn5250 + public final static int KEY_F24 = 25; // only used by tn5250 + public final static int KEY_UP = 26; + public final static int KEY_DOWN = 27; + public final static int KEY_LEFT = 28; + public final static int KEY_RIGHT = 29; + public final static int KEY_PAGE_DOWN = 30; + public final static int KEY_PAGE_UP = 31; + public final static int KEY_INSERT = 32; + public final static int KEY_DELETE = 33; + public final static int KEY_BACK_SPACE = 34; + public final static int KEY_HOME = 35; + public final static int KEY_END = 36; + public final static int KEY_NUM_LOCK = 37; + public final static int KEY_CAPS_LOCK = 38; + public final static int KEY_SHIFT = 39; + public final static int KEY_CONTROL = 40; + public final static int KEY_ALT = 41; + public final static int KEY_ENTER = 42; + public final static int KEY_NUMPAD0 = 43; + public final static int KEY_NUMPAD1 = 44; + public final static int KEY_NUMPAD2 = 45; + public final static int KEY_NUMPAD3 = 46; + public final static int KEY_NUMPAD4 = 47; + public final static int KEY_NUMPAD5 = 48; + public final static int KEY_NUMPAD6 = 49; + public final static int KEY_NUMPAD7 = 50; + public final static int KEY_NUMPAD8 = 51; + public final static int KEY_NUMPAD9 = 52; + public final static int KEY_DECIMAL = 53; + public final static int KEY_ADD = 54; + public final static int KEY_ESCAPE = 55; + public final static int KEY_TAB = 56; + public final static int KEY_SYSREQ = 57; // only used by tn5250 + + public final static int DELETE_IS_DEL = 0; + public final static int DELETE_IS_BACKSPACE = 1; + + /* The graphics charsets + * B - default ASCII + * A - ISO Latin 1 + * 0 - DEC SPECIAL + * < - User defined + * .... + */ + char gx[]; + char gl; // GL (left charset) + char gr; // GR (right charset) + int onegl; // single shift override for GL. + + // Map from scoansi linedrawing to DEC _and_ unicode (for the stuff which + // is not in linedrawing). Got from experimenting with scoadmin. + private final static String scoansi_acs = "Tm7k3x4u?kZl@mYjEnB\u2566DqCtAvM\u2550:\u2551N\u2557I\u2554;\u2557H\u255a0a<\u255d"; + // array to store DEC Special -> Unicode mapping + // Unicode DEC Unicode name (DEC name) + private static char DECSPECIAL[] = { + '\u0040', //5f blank + '\u2666', //60 black diamond + '\u2592', //61 grey square + '\u2409', //62 Horizontal tab (ht) pict. for control + '\u240c', //63 Form Feed (ff) pict. for control + '\u240d', //64 Carriage Return (cr) pict. for control + '\u240a', //65 Line Feed (lf) pict. for control + '\u00ba', //66 Masculine ordinal indicator + '\u00b1', //67 Plus or minus sign + '\u2424', //68 New Line (nl) pict. for control + '\u240b', //69 Vertical Tab (vt) pict. for control + '\u2518', //6a Forms light up and left + '\u2510', //6b Forms light down and left + '\u250c', //6c Forms light down and right + '\u2514', //6d Forms light up and right + '\u253c', //6e Forms light vertical and horizontal + '\u2594', //6f Upper 1/8 block (Scan 1) + '\u2580', //70 Upper 1/2 block (Scan 3) + '\u2500', //71 Forms light horizontal or ?em dash? (Scan 5) + '\u25ac', //72 \u25ac black rect. or \u2582 lower 1/4 (Scan 7) + '\u005f', //73 \u005f underscore or \u2581 lower 1/8 (Scan 9) + '\u251c', //74 Forms light vertical and right + '\u2524', //75 Forms light vertical and left + '\u2534', //76 Forms light up and horizontal + '\u252c', //77 Forms light down and horizontal + '\u2502', //78 vertical bar + '\u2264', //79 less than or equal + '\u2265', //7a greater than or equal + '\u00b6', //7b paragraph + '\u2260', //7c not equal + '\u00a3', //7d Pound Sign (british) + '\u00b7' //7e Middle Dot + }; + + /** Strings to send on function key pressing */ + private String Numpad[]; + private String FunctionKey[]; + private String FunctionKeyShift[]; + private String FunctionKeyCtrl[]; + private String FunctionKeyAlt[]; + private String TabKey[]; + private String KeyUp[], KeyDown[], KeyLeft[], KeyRight[]; + private String KPMinus, KPComma, KPPeriod, KPEnter; + private String PF1, PF2, PF3, PF4; + private String Help, Do, Find, Select; + + private String KeyHome[], KeyEnd[], Insert[], Remove[], PrevScn[], NextScn[]; + private String Escape[], BackSpace[], NUMDot[], NUMPlus[]; + + private String osc, dcs; /* to memorize OSC & DCS control sequence */ + + /** vt320 state variable (internal) */ + private int term_state = TSTATE_DATA; + /** in vms mode, set by Terminal.VMS property */ + private boolean vms = false; + /** Tabulators */ + private byte[] Tabs; + /** The list of integers as used by CSI */ + private int[] DCEvars = new int[30]; + private int DCEvar; + + /** + * Replace escape code characters (backslash + identifier) with their + * respective codes. + * @param tmp the string to be parsed + * @return a unescaped string + */ + static String unEscape(String tmp) { + int idx = 0, oldidx = 0; + String cmd; + // f.println("unescape("+tmp+")"); + cmd = ""; + + while ((idx = tmp.indexOf('\\', oldidx)) >= 0 && + ++idx <= tmp.length()) { + cmd += tmp.substring(oldidx, idx - 1); + + if (idx == tmp.length()) return cmd; + + switch (tmp.charAt(idx)) { + case 'b': + cmd += "\b"; + break; + + case 'e': + cmd += "\u001b"; + break; + + case 'n': + cmd += "\n"; + break; + + case 'r': + cmd += "\r"; + break; + + case 't': + cmd += "\t"; + break; + + case 'v': + cmd += "\u000b"; + break; + + case 'a': + cmd += "\u0012"; + break; + + default : + if ((tmp.charAt(idx) >= '0') && (tmp.charAt(idx) <= '9')) { + int i; + + for (i = idx; i < tmp.length(); i++) + if ((tmp.charAt(i) < '0') || (tmp.charAt(i) > '9')) + break; + + cmd += (char) Integer.parseInt(tmp.substring(idx, i)); + idx = i - 1; + } + else + cmd += tmp.substring(idx, ++idx); + + break; + } + + oldidx = ++idx; + } + + if (oldidx <= tmp.length()) cmd += tmp.substring(oldidx); + + return cmd; + } + + /** + * A small conveniance method thar converts a 7bit string to the 8bit + * version depending on VT52/Output8Bit mode. + * + * @param s the string to be sent + */ + private boolean writeSpecial(String s) { + if (s == null) + return true; + + if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == 'O'))) { + if (vt52mode) { + if ((s.charAt(2) >= 'P') && (s.charAt(2) <= 'S')) { + s = "\u001b" + s.substring(2); /* ESC x */ + } + else { + s = "\u001b?" + s.substring(2); /* ESC ? x */ + } + } + else { + if (output8bit) { + s = "\u008f" + s.substring(2); /* SS3 x */ + } /* else keep string as it is */ + } + } + + if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == '['))) { + if (output8bit) { + s = "\u009b" + s.substring(2); /* CSI ... */ + } /* else keep */ + } + + return write(s, false); + } + + /** + * main keytyping event handler for all the special function and modifier keys + * the normal keys are processed by write(byte b); + */ + public void keyPressed(int keyCode, char keyChar, int modifiers) { + boolean control = (modifiers & VDUInput.KEY_CONTROL) != 0; + boolean shift = (modifiers & VDUInput.KEY_SHIFT) != 0; + boolean alt = (modifiers & VDUInput.KEY_ALT) != 0; + + if (debug > 1) { + debugStr.append("keyPressed(") + .append(keyCode) + .append(", ") + .append((int)keyChar) + .append(", ") + .append(modifiers) + .append(')'); + debug(debugStr.toString()); + debugStr.setLength(0); + } + + int xind; + String fmap[]; + xind = 0; + fmap = FunctionKey; + + if (shift) { + fmap = FunctionKeyShift; + xind = 1; + } + + if (control) { + fmap = FunctionKeyCtrl; + xind = 2; + } + + if (alt) { + fmap = FunctionKeyAlt; + xind = 3; + } + + switch (keyCode) { + case KEY_PAUSE: + if (shift || control) + sendTelnetCommand((byte) 243); // BREAK + + break; + + case KEY_F1: + writeSpecial(fmap[1]); + break; + + case KEY_F2: + writeSpecial(fmap[2]); + break; + + case KEY_F3: + writeSpecial(fmap[3]); + break; + + case KEY_F4: + writeSpecial(fmap[4]); + break; + + case KEY_F5: + writeSpecial(fmap[5]); + break; + + case KEY_F6: + writeSpecial(fmap[6]); + break; + + case KEY_F7: + writeSpecial(fmap[7]); + break; + + case KEY_F8: + writeSpecial(fmap[8]); + break; + + case KEY_F9: + writeSpecial(fmap[9]); + break; + + case KEY_F10: + writeSpecial(fmap[10]); + break; + + case KEY_F11: + writeSpecial(fmap[11]); + break; + + case KEY_F12: + writeSpecial(fmap[12]); + break; + + case KEY_F13: + case KEY_F14: + case KEY_F15: + case KEY_F16: + case KEY_F17: + case KEY_F18: + case KEY_F19: + case KEY_F20: + case KEY_F21: + case KEY_F22: + case KEY_F23: + case KEY_F24: + break; + + case KEY_UP: + writeSpecial(KeyUp[xind]); + break; + + case KEY_DOWN: + writeSpecial(KeyDown[xind]); + break; + + case KEY_LEFT: + writeSpecial(KeyLeft[xind]); + break; + + case KEY_RIGHT: + writeSpecial(KeyRight[xind]); + break; + + case KEY_PAGE_DOWN: + writeSpecial(NextScn[xind]); + break; + + case KEY_PAGE_UP: + writeSpecial(PrevScn[xind]); + break; + + case KEY_INSERT: + writeSpecial(Insert[xind]); + break; + + case KEY_DELETE: + writeSpecial(Remove[xind]); + break; + + case KEY_BACK_SPACE: + writeSpecial(BackSpace[xind]); + + if (localecho) { + if (BackSpace[xind] == "\b") { + putString("\b \b"); // make the last char 'deleted' + } + else { + putString(BackSpace[xind]); // echo it + } + } + + break; + + case KEY_HOME: + writeSpecial(KeyHome[xind]); + break; + + case KEY_END: + writeSpecial(KeyEnd[xind]); + break; + + case KEY_NUM_LOCK: + if (vms && control) { + writeSpecial(PF1); + } + + if (!control) + numlock = !numlock; + + break; + + case KEY_CAPS_LOCK: + capslock = !capslock; + break; + + case KEY_SHIFT: + case KEY_CONTROL: + case KEY_ALT: + break; + + case KEY_ESCAPE: + writeSpecial(Escape[xind]); + break; + + case KEY_ENTER: + write(0x0d); + break; + + case KEY_TAB: + writeSpecial(TabKey[xind]); + break; + + default: + break; + } + } + + private void handle_dcs(String dcs) { + debugStr.append("DCS: ") + .append(dcs); + debug(debugStr.toString()); + debugStr.setLength(0); + } + + private void handle_osc(String osc) { + if (osc.length() > 2 && osc.substring(0, 2).equals("4;")) { + // Define color palette + String[] colorData = osc.split(";"); + + try { + int colorIndex = Integer.parseInt(colorData[1]); + + if ("rgb:".equals(colorData[2].substring(0, 4))) { + String[] rgb = colorData[2].substring(4).split("/"); + int red = Integer.parseInt(rgb[0].substring(0, 2), 16) & 0xFF; + int green = Integer.parseInt(rgb[1].substring(0, 2), 16) & 0xFF; + int blue = Integer.parseInt(rgb[2].substring(0, 2), 16) & 0xFF; + display.setColor(colorIndex, red, green, blue); + } + } + catch (Exception e) { + debugStr.append("OSC: invalid color sequence encountered: ") + .append(osc); + debug(debugStr.toString()); + debugStr.setLength(0); + } + } + else + debug("OSC: " + osc); + } + + private final static char unimap[] = { + //# + //# Name: cp437_DOSLatinUS to Unicode table + //# Unicode version: 1.1 + //# Table version: 1.1 + //# Table format: Format A + //# Date: 03/31/95 + //# Authors: Michel Suignard <michelsu@microsoft.com> + //# Lori Hoerth <lorih@microsoft.com> + //# General notes: none + //# + //# Format: Three tab-separated columns + //# Column #1 is the cp1255_WinHebrew code (in hex) + //# Column #2 is the Unicode (in hex as 0xXXXX) + //# Column #3 is the Unicode name (follows a comment sign, '#') + //# + //# The entries are in cp437_DOSLatinUS order + //# + + 0x0000, // #NULL + 0x0001, // #START OF HEADING + 0x0002, // #START OF TEXT + 0x0003, // #END OF TEXT + 0x0004, // #END OF TRANSMISSION + 0x0005, // #ENQUIRY + 0x0006, // #ACKNOWLEDGE + 0x0007, // #BELL + 0x0008, // #BACKSPACE + 0x0009, // #HORIZONTAL TABULATION + 0x000a, // #LINE FEED + 0x000b, // #VERTICAL TABULATION + 0x000c, // #FORM FEED + 0x000d, // #CARRIAGE RETURN + 0x000e, // #SHIFT OUT + 0x000f, // #SHIFT IN + 0x0010, // #DATA LINK ESCAPE + 0x0011, // #DEVICE CONTROL ONE + 0x0012, // #DEVICE CONTROL TWO + 0x0013, // #DEVICE CONTROL THREE + 0x0014, // #DEVICE CONTROL FOUR + 0x0015, // #NEGATIVE ACKNOWLEDGE + 0x0016, // #SYNCHRONOUS IDLE + 0x0017, // #END OF TRANSMISSION BLOCK + 0x0018, // #CANCEL + 0x0019, // #END OF MEDIUM + 0x001a, // #SUBSTITUTE + 0x001b, // #ESCAPE + 0x001c, // #FILE SEPARATOR + 0x001d, // #GROUP SEPARATOR + 0x001e, // #RECORD SEPARATOR + 0x001f, // #UNIT SEPARATOR + 0x0020, // #SPACE + 0x0021, // #EXCLAMATION MARK + 0x0022, // #QUOTATION MARK + 0x0023, // #NUMBER SIGN + 0x0024, // #DOLLAR SIGN + 0x0025, // #PERCENT SIGN + 0x0026, // #AMPERSAND + 0x0027, // #APOSTROPHE + 0x0028, // #LEFT PARENTHESIS + 0x0029, // #RIGHT PARENTHESIS + 0x002a, // #ASTERISK + 0x002b, // #PLUS SIGN + 0x002c, // #COMMA + 0x002d, // #HYPHEN-MINUS + 0x002e, // #FULL STOP + 0x002f, // #SOLIDUS + 0x0030, // #DIGIT ZERO + 0x0031, // #DIGIT ONE + 0x0032, // #DIGIT TWO + 0x0033, // #DIGIT THREE + 0x0034, // #DIGIT FOUR + 0x0035, // #DIGIT FIVE + 0x0036, // #DIGIT SIX + 0x0037, // #DIGIT SEVEN + 0x0038, // #DIGIT EIGHT + 0x0039, // #DIGIT NINE + 0x003a, // #COLON + 0x003b, // #SEMICOLON + 0x003c, // #LESS-THAN SIGN + 0x003d, // #EQUALS SIGN + 0x003e, // #GREATER-THAN SIGN + 0x003f, // #QUESTION MARK + 0x0040, // #COMMERCIAL AT + 0x0041, // #LATIN CAPITAL LETTER A + 0x0042, // #LATIN CAPITAL LETTER B + 0x0043, // #LATIN CAPITAL LETTER C + 0x0044, // #LATIN CAPITAL LETTER D + 0x0045, // #LATIN CAPITAL LETTER E + 0x0046, // #LATIN CAPITAL LETTER F + 0x0047, // #LATIN CAPITAL LETTER G + 0x0048, // #LATIN CAPITAL LETTER H + 0x0049, // #LATIN CAPITAL LETTER I + 0x004a, // #LATIN CAPITAL LETTER J + 0x004b, // #LATIN CAPITAL LETTER K + 0x004c, // #LATIN CAPITAL LETTER L + 0x004d, // #LATIN CAPITAL LETTER M + 0x004e, // #LATIN CAPITAL LETTER N + 0x004f, // #LATIN CAPITAL LETTER O + 0x0050, // #LATIN CAPITAL LETTER P + 0x0051, // #LATIN CAPITAL LETTER Q + 0x0052, // #LATIN CAPITAL LETTER R + 0x0053, // #LATIN CAPITAL LETTER S + 0x0054, // #LATIN CAPITAL LETTER T + 0x0055, // #LATIN CAPITAL LETTER U + 0x0056, // #LATIN CAPITAL LETTER V + 0x0057, // #LATIN CAPITAL LETTER W + 0x0058, // #LATIN CAPITAL LETTER X + 0x0059, // #LATIN CAPITAL LETTER Y + 0x005a, // #LATIN CAPITAL LETTER Z + 0x005b, // #LEFT SQUARE BRACKET + 0x005c, // #REVERSE SOLIDUS + 0x005d, // #RIGHT SQUARE BRACKET + 0x005e, // #CIRCUMFLEX ACCENT + 0x005f, // #LOW LINE + 0x0060, // #GRAVE ACCENT + 0x0061, // #LATIN SMALL LETTER A + 0x0062, // #LATIN SMALL LETTER B + 0x0063, // #LATIN SMALL LETTER C + 0x0064, // #LATIN SMALL LETTER D + 0x0065, // #LATIN SMALL LETTER E + 0x0066, // #LATIN SMALL LETTER F + 0x0067, // #LATIN SMALL LETTER G + 0x0068, // #LATIN SMALL LETTER H + 0x0069, // #LATIN SMALL LETTER I + 0x006a, // #LATIN SMALL LETTER J + 0x006b, // #LATIN SMALL LETTER K + 0x006c, // #LATIN SMALL LETTER L + 0x006d, // #LATIN SMALL LETTER M + 0x006e, // #LATIN SMALL LETTER N + 0x006f, // #LATIN SMALL LETTER O + 0x0070, // #LATIN SMALL LETTER P + 0x0071, // #LATIN SMALL LETTER Q + 0x0072, // #LATIN SMALL LETTER R + 0x0073, // #LATIN SMALL LETTER S + 0x0074, // #LATIN SMALL LETTER T + 0x0075, // #LATIN SMALL LETTER U + 0x0076, // #LATIN SMALL LETTER V + 0x0077, // #LATIN SMALL LETTER W + 0x0078, // #LATIN SMALL LETTER X + 0x0079, // #LATIN SMALL LETTER Y + 0x007a, // #LATIN SMALL LETTER Z + 0x007b, // #LEFT CURLY BRACKET + 0x007c, // #VERTICAL LINE + 0x007d, // #RIGHT CURLY BRACKET + 0x007e, // #TILDE + 0x007f, // #DELETE + 0x00c7, // #LATIN CAPITAL LETTER C WITH CEDILLA + 0x00fc, // #LATIN SMALL LETTER U WITH DIAERESIS + 0x00e9, // #LATIN SMALL LETTER E WITH ACUTE + 0x00e2, // #LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4, // #LATIN SMALL LETTER A WITH DIAERESIS + 0x00e0, // #LATIN SMALL LETTER A WITH GRAVE + 0x00e5, // #LATIN SMALL LETTER A WITH RING ABOVE + 0x00e7, // #LATIN SMALL LETTER C WITH CEDILLA + 0x00ea, // #LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb, // #LATIN SMALL LETTER E WITH DIAERESIS + 0x00e8, // #LATIN SMALL LETTER E WITH GRAVE + 0x00ef, // #LATIN SMALL LETTER I WITH DIAERESIS + 0x00ee, // #LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ec, // #LATIN SMALL LETTER I WITH GRAVE + 0x00c4, // #LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5, // #LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c9, // #LATIN CAPITAL LETTER E WITH ACUTE + 0x00e6, // #LATIN SMALL LIGATURE AE + 0x00c6, // #LATIN CAPITAL LIGATURE AE + 0x00f4, // #LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6, // #LATIN SMALL LETTER O WITH DIAERESIS + 0x00f2, // #LATIN SMALL LETTER O WITH GRAVE + 0x00fb, // #LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00f9, // #LATIN SMALL LETTER U WITH GRAVE + 0x00ff, // #LATIN SMALL LETTER Y WITH DIAERESIS + 0x00d6, // #LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00dc, // #LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00a2, // #CENT SIGN + 0x00a3, // #POUND SIGN + 0x00a5, // #YEN SIGN + 0x20a7, // #PESETA SIGN + 0x0192, // #LATIN SMALL LETTER F WITH HOOK + 0x00e1, // #LATIN SMALL LETTER A WITH ACUTE + 0x00ed, // #LATIN SMALL LETTER I WITH ACUTE + 0x00f3, // #LATIN SMALL LETTER O WITH ACUTE + 0x00fa, // #LATIN SMALL LETTER U WITH ACUTE + 0x00f1, // #LATIN SMALL LETTER N WITH TILDE + 0x00d1, // #LATIN CAPITAL LETTER N WITH TILDE + 0x00aa, // #FEMININE ORDINAL INDICATOR + 0x00ba, // #MASCULINE ORDINAL INDICATOR + 0x00bf, // #INVERTED QUESTION MARK + 0x2310, // #REVERSED NOT SIGN + 0x00ac, // #NOT SIGN + 0x00bd, // #VULGAR FRACTION ONE HALF + 0x00bc, // #VULGAR FRACTION ONE QUARTER + 0x00a1, // #INVERTED EXCLAMATION MARK + 0x00ab, // #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bb, // #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x2591, // #LIGHT SHADE + 0x2592, // #MEDIUM SHADE + 0x2593, // #DARK SHADE + 0x2502, // #BOX DRAWINGS LIGHT VERTICAL + 0x2524, // #BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x2561, // #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562, // #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2556, // #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2555, // #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2563, // #BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2551, // #BOX DRAWINGS DOUBLE VERTICAL + 0x2557, // #BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255d, // #BOX DRAWINGS DOUBLE UP AND LEFT + 0x255c, // #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255b, // #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x2510, // #BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514, // #BOX DRAWINGS LIGHT UP AND RIGHT + 0x2534, // #BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x252c, // #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x251c, // #BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2500, // #BOX DRAWINGS LIGHT HORIZONTAL + 0x253c, // #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x255e, // #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f, // #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x255a, // #BOX DRAWINGS DOUBLE UP AND RIGHT + 0x2554, // #BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2569, // #BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x2566, // #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2560, // #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2550, // #BOX DRAWINGS DOUBLE HORIZONTAL + 0x256c, // #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2567, // #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568, // #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2564, // #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565, // #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2559, // #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x2558, // #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2552, // #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553, // #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x256b, // #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256a, // #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x2518, // #BOX DRAWINGS LIGHT UP AND LEFT + 0x250c, // #BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2588, // #FULL BLOCK + 0x2584, // #LOWER HALF BLOCK + 0x258c, // #LEFT HALF BLOCK + 0x2590, // #RIGHT HALF BLOCK + 0x2580, // #UPPER HALF BLOCK + 0x03b1, // #GREEK SMALL LETTER ALPHA + 0x00df, // #LATIN SMALL LETTER SHARP S + 0x0393, // #GREEK CAPITAL LETTER GAMMA + 0x03c0, // #GREEK SMALL LETTER PI + 0x03a3, // #GREEK CAPITAL LETTER SIGMA + 0x03c3, // #GREEK SMALL LETTER SIGMA + 0x00b5, // #MICRO SIGN + 0x03c4, // #GREEK SMALL LETTER TAU + 0x03a6, // #GREEK CAPITAL LETTER PHI + 0x0398, // #GREEK CAPITAL LETTER THETA + 0x03a9, // #GREEK CAPITAL LETTER OMEGA + 0x03b4, // #GREEK SMALL LETTER DELTA + 0x221e, // #INFINITY + 0x03c6, // #GREEK SMALL LETTER PHI + 0x03b5, // #GREEK SMALL LETTER EPSILON + 0x2229, // #INTERSECTION + 0x2261, // #IDENTICAL TO + 0x00b1, // #PLUS-MINUS SIGN + 0x2265, // #GREATER-THAN OR EQUAL TO + 0x2264, // #LESS-THAN OR EQUAL TO + 0x2320, // #TOP HALF INTEGRAL + 0x2321, // #BOTTOM HALF INTEGRAL + 0x00f7, // #DIVISION SIGN + 0x2248, // #ALMOST EQUAL TO + 0x00b0, // #DEGREE SIGN + 0x2219, // #BULLET OPERATOR + 0x00b7, // #MIDDLE DOT + 0x221a, // #SQUARE ROOT + 0x207f, // #SUPERSCRIPT LATIN SMALL LETTER N + 0x00b2, // #SUPERSCRIPT TWO + 0x25a0, // #BLACK SQUARE + 0x00a0, // #NO-BREAK SPACE + }; + + public char map_cp850_unicode(char x) { + if (x >= 0x100) + return x; + + return unimap[x]; + } + + private void _SetCursor(int row, int col) { + int maxr = height - 1; + int tm = getTopMargin(); + R = (row < 0) ? 0 : row; + C = (col < 0) ? 0 : (col >= width) ? width - 1 : col; + + if (!moveoutsidemargins) { + R += tm; + maxr = getBottomMargin(); + } + + if (R > maxr) R = maxr; + } + + private void putChar(char c, boolean isWide, boolean doshowcursor) { + int rows = this.height; //statusline + int columns = this.width; + + // byte msg[]; +// if (debug > 4) { +// debugStr.append("putChar(") +// .append(c) +// .append(" [") +// .append((int) c) +// .append("]) at R=") +// .append(R) +// .append(" , C=") +// .append(C) +// .append(", columns=") +// .append(columns) +// .append(", rows=") +// .append(rows); +// debug(debugStr.toString()); +// debugStr.setLength(0); +// } +// markLine(R, 1); +// if (c > 255) { +// if (debug > 0) +// debug("char > 255:" + (int) c); +// //return; +// } + switch (term_state) { + case TSTATE_DATA: + + /* FIXME: we shouldn't use chars with bit 8 set if ibmcharset. + * probably... but some BBS do anyway... + */ + if (!useibmcharset) { + boolean doneflag = true; + + switch (c) { + case OSC: + osc = ""; + term_state = TSTATE_OSC; + break; + + case RI: + if (R > getTopMargin()) + R--; + else + insertLine(R, 1, SCROLL_DOWN); + + if (debug > 1) + debug("RI"); + + break; + + case IND: + if (debug > 2) { + debugStr.append("IND at ") + .append(R) + .append(", tm is ") + .append(getTopMargin()) + .append(", bm is ") + .append(getBottomMargin()); + debug(debugStr.toString()); + debugStr.setLength(0); + } + + if (R == getBottomMargin() || R == rows - 1) + insertLine(R, 1, SCROLL_UP); + else + R++; + + if (debug > 1) + debug("IND (at " + R + " )"); + + break; + + case NEL: + if (R == getBottomMargin() || R == rows - 1) + insertLine(R, 1, SCROLL_UP); + else + R++; + + C = 0; + + if (debug > 1) + debug("NEL (at " + R + " )"); + + break; + + case HTS: + Tabs[C] = 1; + + if (debug > 1) + debug("HTS"); + + break; + + case DCS: + dcs = ""; + term_state = TSTATE_DCS; + break; + + default: + doneflag = false; + break; + } + + if (doneflag) break; + } + + switch (c) { + case SS3: + onegl = 3; + break; + + case SS2: + onegl = 2; + break; + + case CSI: // should be in the 8bit section, but some BBS use this + DCEvar = 0; + DCEvars[0] = 0; + DCEvars[1] = 0; + DCEvars[2] = 0; + DCEvars[3] = 0; + term_state = TSTATE_CSI; + break; + + case ESC: + term_state = TSTATE_ESC; + lastwaslf = 0; + break; + + case 5: /* ENQ */ + write(answerBack, false); + break; + + case 12: + /* FormFeed, Home for the BBS world */ + deleteArea(0, 0, columns, rows, attributes); + C = R = 0; + break; + + case '\b': /* 8 */ + C--; + + if (C < 0) + C = 0; + + lastwaslf = 0; + break; + + case '\t': + do { + // Don't overwrite or insert! TABS are not destructive, but movement! + C++; + } + while (C < columns && (Tabs[C] == 0)); + + lastwaslf = 0; + break; + + case '\r': // 13 CR + C = 0; + break; + + case '\n': // 10 LF + if (debug > 3) + debug("R= " + R + ", bm " + getBottomMargin() + ", tm=" + getTopMargin() + ", rows=" + rows); + + if (!vms) { + if (lastwaslf != 0 && lastwaslf != c) // Ray: I do not understand this logic. + break; + + lastwaslf = c; + /*C = 0;*/ + } + + if (R == getBottomMargin() || R >= rows - 1) + insertLine(R, 1, SCROLL_UP); + else + R++; + + break; + + case 7: + beep(); + break; + + case '\016': /* SMACS , as */ + /* ^N, Shift out - Put G1 into GL */ + gl = 1; + usedcharsets = true; + break; + + case '\017': /* RMACS , ae */ + /* ^O, Shift in - Put G0 into GL */ + gl = 0; + usedcharsets = true; + break; + + default: { + int thisgl = gl; + + if (onegl >= 0) { + thisgl = onegl; + onegl = -1; + } + + lastwaslf = 0; + + if (c < 32) { + if (c != 0) + if (debug > 0) + debug("TSTATE_DATA char: " + ((int) c)); + + /*break; some BBS really want those characters, like hearst etc. */ + if (c == 0) /* print 0 ... you bet */ + break; + } + + if (C >= columns) { + if (wraparound) { + int bot = rows; + + // If we're in the scroll region, check against the bottom margin + if (R <= getBottomMargin() && R >= getTopMargin()) + bot = getBottomMargin() + 1; + + if (R < bot - 1) + R++; + else { + if (debug > 3) debug("scrolling due to wrap at " + R); + + insertLine(R, 1, SCROLL_UP); + } + + C = 0; + } + else { + // cursor stays on last character. + C = columns - 1; + } + } + + boolean mapped = false; + + // Mapping if DEC Special is chosen charset + if (usedcharsets) { + if (c >= '\u0020' && c <= '\u007f') { + switch (gx[thisgl]) { + case '0': + + // Remap SCOANSI line drawing to VT100 line drawing chars + // for our SCO using customers. + if (terminalID.equals("scoansi") || terminalID.equals("ansi")) { + for (int i = 0; i < scoansi_acs.length(); i += 2) { + if (c == scoansi_acs.charAt(i)) { + c = scoansi_acs.charAt(i + 1); + break; + } + } + } + + if (c >= '\u005f' && c <= '\u007e') { + c = DECSPECIAL[(short) c - 0x5f]; + mapped = true; + } + + break; + + case '<': // 'user preferred' is currently 'ISO Latin-1 suppl + c = (char)((c & 0x7f) | 0x80); + mapped = true; + break; + + case 'A': + case 'B': // Latin-1 , ASCII -> fall through + mapped = true; + break; + + default: + debug("Unsupported GL mapping: " + gx[thisgl]); + break; + } + } + + if (!mapped && (c >= '\u0080' && c <= '\u00ff')) { + switch (gx[gr]) { + case '0': + if (c >= '\u00df' && c <= '\u00fe') { + c = DECSPECIAL[c - '\u00df']; + mapped = true; + } + + break; + + case '<': + case 'A': + case 'B': + mapped = true; + break; + + default: + debug("Unsupported GR mapping: " + gx[gr]); + break; + } + } + } + + if (!mapped && useibmcharset) + c = map_cp850_unicode(c); + + /*if(true || (statusmode == 0)) { */ + if (isWide) { + if (C >= columns - 1) { + if (wraparound) { + int bot = rows; + + // If we're in the scroll region, check against the bottom margin + if (R <= getBottomMargin() && R >= getTopMargin()) + bot = getBottomMargin() + 1; + + if (R < bot - 1) + R++; + else { + if (debug > 3) debug("scrolling due to wrap at " + R); + + insertLine(R, 1, SCROLL_UP); + } + + C = 0; + } + else { + // cursor stays on last wide character. + C = columns - 2; + } + } + } + + if (insertmode == 1) { + if (isWide) { + insertChar(C++, R, c, attributes | FULLWIDTH); + insertChar(C, R, ' ', attributes | FULLWIDTH); + } + else + insertChar(C, R, c, attributes); + } + else { + if (isWide) { + putChar(C++, R, c, attributes | FULLWIDTH); + putChar(C, R, ' ', attributes | FULLWIDTH); + } + else + putChar(C, R, c, attributes); + } + + /* + } else { + if (insertmode==1) { + insertChar(C, rows, c, attributes); + } else { + putChar(C, rows, c, attributes); + } + } + */ + C++; + break; + } + } /* switch(c) */ + + break; + + case TSTATE_OSC: + if ((c < 0x20) && (c != ESC)) {// NP - No printing character + handle_osc(osc); + term_state = TSTATE_DATA; + break; + } + + //but check for vt102 ESC \ + if (c == '\\' && osc.charAt(osc.length() - 1) == ESC) { + handle_osc(osc); + term_state = TSTATE_DATA; + break; + } + + osc = osc + c; + break; + + case TSTATE_ESCSPACE: + term_state = TSTATE_DATA; + + switch (c) { + case 'F': /* S7C1T, Disable output of 8-bit controls, use 7-bit */ + output8bit = false; + break; + + case 'G': /* S8C1T, Enable output of 8-bit control codes*/ + output8bit = true; + break; + + default: + debug("ESC <space> " + c + " unhandled."); + } + + break; + + case TSTATE_ESC: + term_state = TSTATE_DATA; + + switch (c) { + case ' ': + term_state = TSTATE_ESCSPACE; + break; + + case '#': + term_state = TSTATE_ESCSQUARE; + break; + + case 'c': + /* Hard terminal reset */ + reset(); + break; + + case '[': + DCEvar = 0; + DCEvars[0] = 0; + DCEvars[1] = 0; + DCEvars[2] = 0; + DCEvars[3] = 0; + term_state = TSTATE_CSI; + break; + + case ']': + osc = ""; + term_state = TSTATE_OSC; + break; + + case 'P': + dcs = ""; + term_state = TSTATE_DCS; + break; + + case 'A': /* CUU */ + R--; + + if (R < 0) R = 0; + + break; + + case 'B': /* CUD */ + R++; + + if (R >= rows) R = rows - 1; + + break; + + case 'C': + C++; + + if (C >= columns) C = columns - 1; + + break; + + case 'I': // RI + insertLine(R, 1, SCROLL_DOWN); + break; + + case 'E': /* NEL */ + if (R == getBottomMargin() || R == rows - 1) + insertLine(R, 1, SCROLL_UP); + else + R++; + + C = 0; + + if (debug > 1) + debug("ESC E (at " + R + ")"); + + break; + + case 'D': /* IND */ + if (R == getBottomMargin() || R == rows - 1) + insertLine(R, 1, SCROLL_UP); + else + R++; + + if (debug > 1) + debug("ESC D (at " + R + " )"); + + break; + + case 'J': /* erase to end of screen */ + if (R < rows - 1) + deleteArea(0, R + 1, columns, rows - R - 1, attributes); + + if (C < columns - 1) + deleteArea(C, R, columns - C, 1, attributes); + + break; + + case 'K': + if (C < columns - 1) + deleteArea(C, R, columns - C, 1, attributes); + + break; + + case 'M': // RI + debug("ESC M : R is " + R + ", tm is " + getTopMargin() + ", bm is " + getBottomMargin()); + + if (R > getTopMargin()) { // just go up 1 line. + R--; + } + else { // scroll down + insertLine(R, 1, SCROLL_DOWN); + } + + /* else do nothing ; */ + if (debug > 2) + debug("ESC M "); + + break; + + case 'H': + if (debug > 1) + debug("ESC H at " + C); + + /* right border probably ...*/ + if (C >= columns) + C = columns - 1; + + Tabs[C] = 1; + break; + + case 'N': // SS2 + onegl = 2; + break; + + case 'O': // SS3 + onegl = 3; + break; + + case '=': + + /*application keypad*/ + if (debug > 0) + debug("ESC ="); + + keypadmode = true; + break; + + case '<': /* vt52 mode off */ + vt52mode = false; + break; + + case '>': /*normal keypad*/ + if (debug > 0) + debug("ESC >"); + + keypadmode = false; + break; + + case '7': /* DECSC: save cursor, attributes */ + Sc = C; + Sr = R; + Sgl = gl; + Sgr = gr; + Sa = attributes; + Sgx = new char[4]; + + for (int i = 0; i < 4; i++) Sgx[i] = gx[i]; + + if (debug > 1) + debug("ESC 7"); + + break; + + case '8': /* DECRC: restore cursor, attributes */ + C = Sc; + R = Sr; + gl = Sgl; + gr = Sgr; + + if (Sgx != null) + for (int i = 0; i < 4; i++) gx[i] = Sgx[i]; + + attributes = Sa; + + if (debug > 1) + debug("ESC 8"); + + break; + + case '(': /* Designate G0 Character set (ISO 2022) */ + term_state = TSTATE_SETG0; + usedcharsets = true; + break; + + case ')': /* Designate G1 character set (ISO 2022) */ + term_state = TSTATE_SETG1; + usedcharsets = true; + break; + + case '*': /* Designate G2 Character set (ISO 2022) */ + term_state = TSTATE_SETG2; + usedcharsets = true; + break; + + case '+': /* Designate G3 Character set (ISO 2022) */ + term_state = TSTATE_SETG3; + usedcharsets = true; + break; + + case '~': /* Locking Shift 1, right */ + gr = 1; + usedcharsets = true; + break; + + case 'n': /* Locking Shift 2 */ + gl = 2; + usedcharsets = true; + break; + + case '}': /* Locking Shift 2, right */ + gr = 2; + usedcharsets = true; + break; + + case 'o': /* Locking Shift 3 */ + gl = 3; + usedcharsets = true; + break; + + case '|': /* Locking Shift 3, right */ + gr = 3; + usedcharsets = true; + break; + + case 'Y': /* vt52 cursor address mode , next chars are x,y */ + term_state = TSTATE_VT52Y; + break; + + case '_': + term_state = TSTATE_TITLE; + break; + + case '\\': + // TODO save title + term_state = TSTATE_DATA; + break; + + default: + debug("ESC unknown letter: " + c + " (" + ((int) c) + ")"); + break; + } + + break; + + case TSTATE_VT52X: + C = c - 37; + + if (C < 0) + C = 0; + else if (C >= width) + C = width - 1; + + term_state = TSTATE_VT52Y; + break; + + case TSTATE_VT52Y: + R = c - 37; + + if (R < 0) + R = 0; + else if (R >= height) + R = height - 1; + + term_state = TSTATE_DATA; + break; + + case TSTATE_SETG0: + if (c != '0' && c != 'A' && c != 'B' && c != '<') + debug("ESC ( " + c + ": G0 char set? (" + ((int) c) + ")"); + else { + if (debug > 2) debug("ESC ( : G0 char set (" + c + " " + ((int) c) + ")"); + + gx[0] = c; + } + + term_state = TSTATE_DATA; + break; + + case TSTATE_SETG1: + if (c != '0' && c != 'A' && c != 'B' && c != '<') { + debug("ESC ) " + c + " (" + ((int) c) + ") :G1 char set?"); + } + else { + if (debug > 2) debug("ESC ) :G1 char set (" + c + " " + ((int) c) + ")"); + + gx[1] = c; + } + + term_state = TSTATE_DATA; + break; + + case TSTATE_SETG2: + if (c != '0' && c != 'A' && c != 'B' && c != '<') + debug("ESC*:G2 char set? (" + ((int) c) + ")"); + else { + if (debug > 2) debug("ESC*:G2 char set (" + c + " " + ((int) c) + ")"); + + gx[2] = c; + } + + term_state = TSTATE_DATA; + break; + + case TSTATE_SETG3: + if (c != '0' && c != 'A' && c != 'B' && c != '<') + debug("ESC+:G3 char set? (" + ((int) c) + ")"); + else { + if (debug > 2) debug("ESC+:G3 char set (" + c + " " + ((int) c) + ")"); + + gx[3] = c; + } + + term_state = TSTATE_DATA; + break; + + case TSTATE_ESCSQUARE: + switch (c) { + case '8': + for (int i = 0; i < columns; i++) + for (int j = 0; j < rows; j++) + putChar(i, j, 'E', 0); + + break; + + default: + debug("ESC # " + c + " not supported."); + break; + } + + term_state = TSTATE_DATA; + break; + + case TSTATE_DCS: + if (c == '\\' && dcs.charAt(dcs.length() - 1) == ESC) { + handle_dcs(dcs); + term_state = TSTATE_DATA; + break; + } + + dcs = dcs + c; + break; + + case TSTATE_DCEQ: + term_state = TSTATE_DATA; + + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48; + term_state = TSTATE_DCEQ; + break; + + case ';': + DCEvar++; + DCEvars[DCEvar] = 0; + term_state = TSTATE_DCEQ; + break; + + case 's': // XTERM_SAVE missing! + if (true || debug > 1) + debug("ESC [ ? " + DCEvars[0] + " s unimplemented!"); + + break; + + case 'r': // XTERM_RESTORE + if (true || debug > 1) + debug("ESC [ ? " + DCEvars[0] + " r"); + + /* DEC Mode reset */ + for (int i = 0; i <= DCEvar; i++) { + switch (DCEvars[i]) { + case 3: /* 80 columns*/ + setScreenSize(80, height, true); + break; + + case 4: /* scrolling mode, smooth */ + break; + + case 5: /* light background */ + break; + + case 6: /* DECOM (Origin Mode) move inside margins. */ + moveoutsidemargins = true; + break; + + case 7: /* DECAWM: Autowrap Mode */ + wraparound = false; + break; + + case 12:/* local echo off */ + break; + + case 9: /* X10 mouse */ + case 1000: /* xterm style mouse report on */ + case 1001: + case 1002: + case 1003: + mouserpt = DCEvars[i]; + break; + + default: + debug("ESC [ ? " + DCEvars[0] + " r, unimplemented!"); + } + } + + break; + + case 'h': // DECSET + if (debug > 0) + debug("ESC [ ? " + DCEvars[0] + " h"); + + /* DEC Mode set */ + for (int i = 0; i <= DCEvar; i++) { + switch (DCEvars[i]) { + case 1: /* Application cursor keys */ + KeyUp[0] = "\u001bOA"; + KeyDown[0] = "\u001bOB"; + KeyRight[0] = "\u001bOC"; + KeyLeft[0] = "\u001bOD"; + break; + + case 2: /* DECANM */ + vt52mode = false; + break; + + case 3: /* 132 columns*/ + setScreenSize(132, height, true); + break; + + case 6: /* DECOM: move inside margins. */ + moveoutsidemargins = false; + break; + + case 7: /* DECAWM: Autowrap Mode */ + wraparound = true; + break; + + case 25: /* turn cursor on */ + showCursor(true); + break; + + case 9: /* X10 mouse */ + case 1000: /* xterm style mouse report on */ + case 1001: + case 1002: + case 1003: + mouserpt = DCEvars[i]; + break; + + /* unimplemented stuff, fall through */ + /* 4 - scrolling mode, smooth */ + /* 5 - light background */ + /* 12 - local echo off */ + /* 18 - DECPFF - Printer Form Feed Mode -> On */ + /* 19 - DECPEX - Printer Extent Mode -> Screen */ + default: + debug("ESC [ ? " + DCEvars[0] + " h, unsupported."); + break; + } + } + + break; + + case 'i': // DEC Printer Control, autoprint, echo screenchars to printer + + // This is different to CSI i! + // Also: "Autoprint prints a final display line only when the + // cursor is moved off the line by an autowrap or LF, FF, or + // VT (otherwise do not print the line)." + switch (DCEvars[0]) { + case 1: + if (debug > 1) + debug("CSI ? 1 i : Print line containing cursor"); + + break; + + case 4: + if (debug > 1) + debug("CSI ? 4 i : Start passthrough printing"); + + break; + + case 5: + if (debug > 1) + debug("CSI ? 4 i : Stop passthrough printing"); + + break; + } + + break; + + case 'l': //DECRST + + /* DEC Mode reset */ + if (debug > 0) + debug("ESC [ ? " + DCEvars[0] + " l"); + + for (int i = 0; i <= DCEvar; i++) { + switch (DCEvars[i]) { + case 1: /* Application cursor keys */ + KeyUp[0] = "\u001b[A"; + KeyDown[0] = "\u001b[B"; + KeyRight[0] = "\u001b[C"; + KeyLeft[0] = "\u001b[D"; + break; + + case 2: /* DECANM */ + vt52mode = true; + break; + + case 3: /* 80 columns*/ + setScreenSize(80, height, true); + break; + + case 6: /* DECOM: move outside margins. */ + moveoutsidemargins = true; + break; + + case 7: /* DECAWM: Autowrap Mode OFF */ + wraparound = false; + break; + + case 25: /* turn cursor off */ + showCursor(false); + break; + + /* Unimplemented stuff: */ + /* 4 - scrolling mode, jump */ + /* 5 - dark background */ + /* 7 - DECAWM - no wrap around mode */ + /* 12 - local echo on */ + /* 18 - DECPFF - Printer Form Feed Mode -> Off*/ + /* 19 - DECPEX - Printer Extent Mode -> Scrolling Region */ + case 9: /* X10 mouse */ + case 1000: /* xterm style mouse report OFF */ + case 1001: + case 1002: + case 1003: + mouserpt = 0; + break; + + default: + debug("ESC [ ? " + DCEvars[0] + " l, unsupported."); + break; + } + } + + break; + + case 'n': + if (debug > 0) + debug("ESC [ ? " + DCEvars[0] + " n"); + + switch (DCEvars[0]) { + case 15: + /* printer? no printer. */ + write((ESC) + "[?13n", false); + debug("ESC[5n"); + break; + + default: + debug("ESC [ ? " + DCEvars[0] + " n, unsupported."); + break; + } + + break; + + default: + debug("ESC [ ? " + DCEvars[0] + " " + c + ", unsupported."); + break; + } + + break; + + case TSTATE_CSI_EX: + term_state = TSTATE_DATA; + + switch (c) { + case ESC: + term_state = TSTATE_ESC; + break; + + default: + debug("Unknown character ESC[! character is " + (int) c); + break; + } + + break; + + case TSTATE_CSI_TICKS: + term_state = TSTATE_DATA; + + switch (c) { + case 'p': + debug("Conformance level: " + DCEvars[0] + " (unsupported)," + DCEvars[1]); + + if (DCEvars[0] == 61) { + output8bit = false; + break; + } + + if (DCEvars[1] == 1) { + output8bit = false; + } + else { + output8bit = true; /* 0 or 2 */ + } + + break; + + default: + debug("Unknown ESC [... \"" + c); + break; + } + + break; + + case TSTATE_CSI_EQUAL: + term_state = TSTATE_DATA; + + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48; + term_state = TSTATE_CSI_EQUAL; + break; + + case ';': + DCEvar++; + DCEvars[DCEvar] = 0; + term_state = TSTATE_CSI_EQUAL; + break; + + case 'F': { /* SCO ANSI foreground */ + int newcolor; + debug("ESC [ = " + DCEvars[0] + " F"); + attributes &= ~COLOR_FG; + newcolor = ((DCEvars[0] & 1) << 2) | + (DCEvars[0] & 2) | + ((DCEvars[0] & 4) >> 2) ; + attributes |= (newcolor + 1) << COLOR_FG_SHIFT; + break; + } + + case 'G': { /* SCO ANSI background */ + int newcolor; + debug("ESC [ = " + DCEvars[0] + " G"); + attributes &= ~COLOR_BG; + newcolor = ((DCEvars[0] & 1) << 2) | + (DCEvars[0] & 2) | + ((DCEvars[0] & 4) >> 2) ; + attributes |= (newcolor + 1) << COLOR_BG_SHIFT; + break; + } + + default: + debugStr.append("Unknown ESC [ = "); + + for (int i = 0; i <= DCEvar; i++) { + debugStr.append(DCEvars[i]) + .append(','); + } + + debugStr.append(c); + debug(debugStr.toString()); + debugStr.setLength(0); + break; + } + + break; + + case TSTATE_CSI_DOLLAR: + term_state = TSTATE_DATA; + + switch (c) { + case '}': + debug("Active Status Display now " + DCEvars[0]); + statusmode = DCEvars[0]; + break; + + /* bad documentation? + case '-': + debug("Set Status Display now "+DCEvars[0]); + break; + */ + case '~': + debug("Status Line mode now " + DCEvars[0]); + break; + + default: + debug("UNKNOWN Status Display code " + c + ", with Pn=" + DCEvars[0]); + break; + } + + break; + + case TSTATE_CSI: + term_state = TSTATE_DATA; + + switch (c) { + case '"': + term_state = TSTATE_CSI_TICKS; + break; + + case '$': + term_state = TSTATE_CSI_DOLLAR; + break; + + case '=': + term_state = TSTATE_CSI_EQUAL; + break; + + case '!': + term_state = TSTATE_CSI_EX; + break; + + case '?': + DCEvar = 0; + DCEvars[0] = 0; + term_state = TSTATE_DCEQ; + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48; + term_state = TSTATE_CSI; + break; + + case ';': + DCEvar++; + DCEvars[DCEvar] = 0; + term_state = TSTATE_CSI; + break; + + case 'c':/* send primary device attributes */ + /* send (ESC[?61c) */ + String subcode = ""; + + if (terminalID.equals("vt320")) subcode = "63;"; + + if (terminalID.equals("vt220")) subcode = "62;"; + + if (terminalID.equals("vt100")) subcode = "61;"; + + write((ESC) + "[?" + subcode + "1;2c", false); + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " c"); + + break; + + case 'q': + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " q"); + + break; + + case 'g': + + /* used for tabsets */ + switch (DCEvars[0]) { + case 3:/* clear them */ + Tabs = new byte[width]; + break; + + case 0: + Tabs[C] = 0; + break; + } + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " g"); + + break; + + case 'h': + switch (DCEvars[0]) { + case 4: + insertmode = 1; + break; + + case 20: + debug("Setting CRLF to TRUE"); + sendcrlf = true; + break; + + default: + debug("unsupported: ESC [ " + DCEvars[0] + " h"); + break; + } + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " h"); + + break; + + case 'i': // Printer Controller mode. + + // "Transparent printing sends all output, except the CSI 4 i + // termination string, to the printer and not the screen, + // uses an 8-bit channel if no parity so NUL and DEL will be + // seen by the printer and by the termination recognizer code, + // and all translation and character set selections are + // bypassed." + switch (DCEvars[0]) { + case 0: + if (debug > 1) + debug("CSI 0 i: Print Screen, not implemented."); + + break; + + case 4: + if (debug > 1) + debug("CSI 4 i: Enable Transparent Printing, not implemented."); + + break; + + case 5: + if (debug > 1) + debug("CSI 4/5 i: Disable Transparent Printing, not implemented."); + + break; + + default: + debug("ESC [ " + DCEvars[0] + " i, unimplemented!"); + } + + break; + + case 'l': + switch (DCEvars[0]) { + case 4: + insertmode = 0; + break; + + case 20: + debug("Setting CRLF to FALSE"); + sendcrlf = false; + break; + + default: + debug("ESC [ " + DCEvars[0] + " l, unimplemented!"); + break; + } + + break; + + case 'A': { // CUU + int limit; + + /* FIXME: xterm only cares about 0 and topmargin */ + if (R >= getTopMargin()) { + limit = getTopMargin(); + } + else + limit = 0; + + if (DCEvars[0] == 0) + R--; + else + R -= DCEvars[0]; + + if (R < limit) + R = limit; + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " A"); + + break; + } + + case 'B': // CUD + /* cursor down n (1) times */ + { + int limit; + + if (R <= getBottomMargin()) { + limit = getBottomMargin(); + } + else + limit = rows - 1; + + if (DCEvars[0] == 0) + R++; + else + R += DCEvars[0]; + + if (R > limit) + R = limit; + else { + if (debug > 2) debug("Not limited."); + } + + if (debug > 2) debug("to: " + R); + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " B (at C=" + C + ")"); + + break; + } + + case 'C': + if (DCEvars[0] == 0) + DCEvars[0] = 1; + + while (DCEvars[0]-- > 0) { + C++; + } + + if (C >= columns) + C = columns - 1; + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " C"); + + break; + + case 'd': // CVA + R = DCEvars[0] - 1; + + if (R < 0) + R = 0; + else if (R >= height) + R = height - 1; + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " d"); + + break; + + case 'D': + if (DCEvars[0] == 0) + DCEvars[0] = 1; + + while (DCEvars[0]-- > 0) { + C--; + } + + if (C < 0) C = 0; + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " D"); + + break; + + case 'r': // DECSTBM + if (DCEvar > 0) { // Ray: Any argument is optional + R = DCEvars[1] - 1; + + if (R < 0) + R = rows - 1; + else if (R >= rows) { + R = rows - 1; + } + } + else + R = rows - 1; + + int bot = R; + + if (R >= DCEvars[0]) { + R = DCEvars[0] - 1; + + if (R < 0) + R = 0; + } + + setMargins(R, bot); + _SetCursor(0, 0); + + if (debug > 1) + debug("ESC [" + DCEvars[0] + " ; " + DCEvars[1] + " r"); + + break; + + case 'G': /* CUP / cursor absolute column */ + C = DCEvars[0]; + + if (C < 0) + C = 0; + else if (C >= width) + C = width - 1; + + if (debug > 1) debug("ESC [ " + DCEvars[0] + " G"); + + break; + + case 'H': /* CUP / cursor position */ + /* gets 2 arguments */ + _SetCursor(DCEvars[0] - 1, DCEvars[1] - 1); + + if (debug > 2) { + debug("ESC [ " + DCEvars[0] + ";" + DCEvars[1] + " H, moveoutsidemargins " + moveoutsidemargins); + debug(" -> R now " + R + ", C now " + C); + } + + break; + + case 'f': /* move cursor 2 */ + /* gets 2 arguments */ + R = DCEvars[0] - 1; + C = DCEvars[1] - 1; + + if (C < 0) + C = 0; + else if (C >= width) + C = width - 1; + + if (R < 0) + R = 0; + else if (R >= height) + R = height - 1; + + if (debug > 2) + debug("ESC [ " + DCEvars[0] + ";" + DCEvars[1] + " f"); + + break; + + case 'S': /* ind aka 'scroll forward' */ + if (DCEvars[0] == 0) + insertLine(getBottomMargin(), SCROLL_UP); + else + insertLine(getBottomMargin(), DCEvars[0], SCROLL_UP); + + break; + + case 'L': + + /* insert n lines */ + if (DCEvars[0] == 0) + insertLine(R, SCROLL_DOWN); + else + insertLine(R, DCEvars[0], SCROLL_DOWN); + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + "" + (c) + " (at R " + R + ")"); + + break; + + case 'T': /* 'ri' aka scroll backward */ + if (DCEvars[0] == 0) + insertLine(getTopMargin(), SCROLL_DOWN); + else + insertLine(getTopMargin(), DCEvars[0], SCROLL_DOWN); + + break; + + case 'M': + if (debug > 1) + debug("ESC [ " + DCEvars[0] + "" + (c) + " at R=" + R); + + if (DCEvars[0] == 0) + deleteLine(R); + else + for (int i = 0; i < DCEvars[0]; i++) + deleteLine(R); + + break; + + case 'K': + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " K"); + + /* clear in line */ + switch (DCEvars[0]) { + case 6: /* 97801 uses ESC[6K for delete to end of line */ + case 0:/*clear to right*/ + if (C < columns - 1) + deleteArea(C, R, columns - C, 1, attributes); + + break; + + case 1:/*clear to the left, including this */ + if (C > 0) + deleteArea(0, R, C + 1, 1, attributes); + + break; + + case 2:/*clear whole line */ + deleteArea(0, R, columns, 1, attributes); + break; + } + + break; + + case 'J': + + /* clear below current line */ + switch (DCEvars[0]) { + case 0: + if (R < rows - 1) + deleteArea(0, R + 1, columns, rows - R - 1, attributes); + + if (C < columns - 1) + deleteArea(C, R, columns - C, 1, attributes); + + break; + + case 1: + if (R > 0) + deleteArea(0, 0, columns, R, attributes); + + if (C > 0) + deleteArea(0, R, C + 1, 1, attributes); // include up to and including current + + break; + + case 2: + deleteArea(0, 0, columns, rows, attributes); + break; + } + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " J"); + + break; + + case '@': + if (DCEvars[0] == 0) DCEvars[0] = 1; + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " @"); + + for (int i = 0; i < DCEvars[0]; i++) + insertChar(C, R, ' ', attributes); + + break; + + case 'X': { + int toerase = DCEvars[0]; + + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " X, C=" + C + ",R=" + R); + + if (toerase == 0) + toerase = 1; + + if (toerase + C > columns) + toerase = columns - C; + + deleteArea(C, R, toerase, 1, attributes); + // does not change cursor position + break; + } + + case 'P': + if (debug > 1) + debug("ESC [ " + DCEvars[0] + " P, C=" + C + ",R=" + R); + + if (DCEvars[0] == 0) DCEvars[0] = 1; + + for (int i = 0; i < DCEvars[0]; i++) + deleteChar(C, R); + + break; + + case 'n': + switch (DCEvars[0]) { + case 5: /* malfunction? No malfunction. */ + writeSpecial((ESC) + "[0n"); + + if (debug > 1) + debug("ESC[5n"); + + break; + + case 6: + // DO NOT offset R and C by 1! (checked against /usr/X11R6/bin/resize + // FIXME check again. + // FIXME: but vttest thinks different??? + writeSpecial((ESC) + "[" + R + ";" + C + "R"); + + if (debug > 1) + debug("ESC[6n"); + + break; + + default: + if (debug > 0) + debug("ESC [ " + DCEvars[0] + " n??"); + + break; + } + + break; + + case 's': /* DECSC - save cursor */ + Sc = C; + Sr = R; + Sa = attributes; + + if (debug > 3) + debug("ESC[s"); + + break; + + case 'u': /* DECRC - restore cursor */ + C = Sc; + R = Sr; + attributes = Sa; + + if (debug > 3) + debug("ESC[u"); + + break; + + case 'm': /* attributes as color, bold , blink,*/ + if (debug > 3) + debug("ESC [ "); + + if (DCEvar == 0 && DCEvars[0] == 0) + attributes = 0; + + for (int i = 0; i <= DCEvar; i++) { + switch (DCEvars[i]) { + case 0: + if (DCEvar > 0) { + if (terminalID.equals("scoansi")) { + attributes &= COLOR; /* Keeps color. Strange but true. */ + } + else { + attributes = 0; + } + } + + break; + + case 1: + attributes |= BOLD; + attributes &= ~LOW; + break; + + case 2: + + /* SCO color hack mode */ + if (terminalID.equals("scoansi") && ((DCEvar - i) >= 2)) { + int ncolor; + attributes &= ~(COLOR | BOLD); + ncolor = DCEvars[i + 1]; + + if ((ncolor & 8) == 8) + attributes |= BOLD; + + ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2); + attributes |= ((ncolor) + 1) << COLOR_FG_SHIFT; + ncolor = DCEvars[i + 2]; + ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2); + attributes |= ((ncolor) + 1) << COLOR_BG_SHIFT; + i += 2; + } + else { + attributes |= LOW; + } + + break; + + case 3: /* italics */ + attributes |= INVERT; + break; + + case 4: + attributes |= UNDERLINE; + break; + + case 7: + attributes |= INVERT; + break; + + case 8: + attributes |= INVISIBLE; + break; + + case 5: /* blink on */ + break; + + /* 10 - ANSI X3.64-1979, select primary font, don't display control + * chars, don't set bit 8 on output */ + case 10: + gl = 0; + usedcharsets = true; + break; + + /* 11 - ANSI X3.64-1979, select second alt. font, display control + * chars, set bit 8 on output */ + case 11: /* SMACS , as */ + case 12: + gl = 1; + usedcharsets = true; + break; + + case 21: /* normal intensity */ + attributes &= ~(LOW | BOLD); + break; + + case 23: /* italics off */ + attributes &= ~INVERT; + break; + + case 25: /* blinking off */ + break; + + case 27: + attributes &= ~INVERT; + break; + + case 28: + attributes &= ~INVISIBLE; + break; + + case 24: + attributes &= ~UNDERLINE; + break; + + case 22: + attributes &= ~BOLD; + break; + + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + attributes &= ~COLOR_FG; + attributes |= ((DCEvars[i] - 30) + 1) << COLOR_FG_SHIFT; + break; + + case 38: + if (DCEvars[i + 1] == 5) { + attributes &= ~COLOR_FG; + attributes |= ((DCEvars[i + 2]) + 1) << COLOR_FG_SHIFT; + i += 2; + } + + break; + + case 39: + attributes &= ~COLOR_FG; + break; + + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + attributes &= ~COLOR_BG; + attributes |= ((DCEvars[i] - 40) + 1) << COLOR_BG_SHIFT; + break; + + case 48: + if (DCEvars[i + 1] == 5) { + attributes &= ~COLOR_BG; + attributes |= (DCEvars[i + 2] + 1) << COLOR_BG_SHIFT; + i += 2; + } + + break; + + case 49: + attributes &= ~COLOR_BG; + break; + + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + attributes &= ~COLOR_FG; + attributes |= ((DCEvars[i] - 82) + 1) << COLOR_FG_SHIFT; + break; + + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + attributes &= ~COLOR_BG; + attributes |= ((DCEvars[i] - 92) + 1) << COLOR_BG_SHIFT; + break; + + default: + debugStr.append("ESC [ ") + .append(DCEvars[i]) + .append(" m unknown..."); + debug(debugStr.toString()); + debugStr.setLength(0); + break; + } + + if (debug > 3) { + debugStr.append(DCEvars[i]) + .append(';'); + debug(debugStr.toString()); + debugStr.setLength(0); + } + } + + if (debug > 3) { + debugStr.append(" (attributes = ") + .append(attributes) + .append(")m"); + debug(debugStr.toString()); + debugStr.setLength(0); + } + + break; + + default: + debugStr.append("ESC [ unknown letter: ") + .append(c) + .append(" (") + .append((int)c) + .append(')'); + debug(debugStr.toString()); + debugStr.setLength(0); + break; + } + + break; + + case TSTATE_TITLE: + switch (c) { + case ESC: + term_state = TSTATE_ESC; + break; + + default: + // TODO save title + break; + } + + break; + + default: + term_state = TSTATE_DATA; + break; + } + + setCursorPosition(C, R); + } + + /* hard reset the terminal */ + public void reset() { + gx[0] = 'B'; + gx[1] = 'B'; + gx[2] = 'B'; + gx[3] = 'B'; + gl = 0; // default GL to G0 + gr = 2; // default GR to G2 + onegl = -1; // Single shift override + /* reset tabs */ + int nw = width; + + if (nw < 132) nw = 132; + + Tabs = new byte[nw]; + + for (int i = 0; i < nw; i += 8) { + Tabs[i] = 1; + } + + deleteArea(0, 0, width, height, attributes); + setMargins(0, height); + C = R = 0; + _SetCursor(0, 0); + + if (display != null) + display.resetColors(); + + showCursor(true); + /*FIXME:*/ + term_state = TSTATE_DATA; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/Authentication.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,34 @@ +package net.sourceforge.jsocks; + +/** + The Authentication interface provides for performing method specific + authentication for SOCKS5 connections. +*/ +public interface Authentication{ + /** + This method is called when SOCKS5 server have selected a particular + authentication method, for whch an implementaion have been registered. + + <p> + This method should return an array {inputstream,outputstream + [,UDPEncapsulation]}. The reason for that is that SOCKS5 protocol + allows to have method specific encapsulation of data on the socket for + purposes of integrity or security. And this encapsulation should be + performed by those streams returned from the method. It is also possible + to encapsulate datagrams. If authentication method supports such + encapsulation an instance of the UDPEncapsulation interface should be + returned as third element of the array, otherwise either null should be + returned as third element, or array should contain only 2 elements. + + @param methodId Authentication method selected by the server. + @param proxySocket Socket used to conect to the proxy. + @return Two or three element array containing + Input/Output streams which should be used on this connection. + Third argument is optional and should contain an instance + of UDPEncapsulation. It should be provided if the authentication + method used requires any encapsulation to be done on the + datagrams. + */ + Object[] doSocksAuthentication(int methodId,java.net.Socket proxySocket) + throws java.io.IOException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/AuthenticationNone.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,17 @@ +package net.sourceforge.jsocks; + +/** + SOCKS5 none authentication. Dummy class does almost nothing. +*/ +public class AuthenticationNone implements Authentication{ + + public Object[] doSocksAuthentication(int methodId, + java.net.Socket proxySocket) + throws java.io.IOException{ + + if(methodId!=0) return null; + + return new Object[] { proxySocket.getInputStream(), + proxySocket.getOutputStream()}; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/CProxy.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,488 @@ +package net.sourceforge.jsocks; +import java.net.*; +import java.io.*; +import java.util.Hashtable; +import java.util.Enumeration; + +/** + Abstract class CProxy, base for classes Socks4Proxy and Socks5Proxy. + Defines methods for specifying default proxy, to be + used by all classes of this package. +*/ + +public abstract class CProxy{ + +//Data members + protected InetRange directHosts = new InetRange(); + + protected InetAddress proxyIP = null; + protected String proxyHost = null; + protected int proxyPort; + protected Socket proxySocket = null; + + protected InputStream in; + protected OutputStream out; + + protected int version; + + protected CProxy chainProxy = null; + + +//Protected static/class variables + protected static CProxy defaultProxy = null; + +//Constructors +//==================== + CProxy(CProxy chainProxy, + String proxyHost,int proxyPort)throws UnknownHostException{ + this.chainProxy = chainProxy; + this.proxyHost = proxyHost; + + if(chainProxy == null) + this.proxyIP = InetAddress.getByName(proxyHost); + + this.proxyPort = proxyPort; + } + + + CProxy(String proxyHost,int proxyPort)throws UnknownHostException{ + this(null,proxyHost,proxyPort); + } + + CProxy(CProxy chainProxy,InetAddress proxyIP,int proxyPort){ + this.chainProxy = chainProxy; + this.proxyIP = proxyIP; + this.proxyPort = proxyPort; + } + + CProxy(InetAddress proxyIP,int proxyPort){ + this(null,proxyIP,proxyPort); + } + + CProxy(CProxy p){ + this.proxyIP = p.proxyIP; + this.proxyPort = p.proxyPort; + this.version = p.version; + this.directHosts = p.directHosts; + } + +//Public instance methods +//======================== + + /** + Get the port on which proxy server is running. + * @return CProxy port. + */ + public int getPort(){ + return proxyPort; + } + /** + Get the ip address of the proxy server host. + * @return CProxy InetAddress. + */ + public InetAddress getInetAddress(){ + return proxyIP; + } + /** + * Adds given ip to the list of direct addresses. + * This machine will be accessed without using proxy. + */ + public void addDirect(InetAddress ip){ + directHosts.add(ip); + } + /** + * Adds host to the list of direct addresses. + * This machine will be accessed without using proxy. + */ + public boolean addDirect(String host){ + return directHosts.add(host); + } + /** + * Adds given range of addresses to the lsit of direct addresses, + * machines within this range will be accessed without using proxy. + */ + public void addDirect(InetAddress from,InetAddress to){ + directHosts.add(from,to); + } + /** + * Sets given InetRange as the list of direct address, previous + * list will be discarded, any changes done previously with + * addDirect(Inetaddress) will be lost. + * The machines in this range will be accessed without using proxy. + * @param ir InetRange which should be used to look up direct addresses. + * @see InetRange + */ + public void setDirect(InetRange ir){ + directHosts = ir; + } + + /** + Get the list of direct hosts. + * @return Current range of direct address as InetRange object. + * @see InetRange + */ + public InetRange getDirect(){ + return directHosts; + } + /** + Check wether the given host is on the list of direct address. + @param host Host name to check. + * @return true if the given host is specified as the direct addresses. + */ + public boolean isDirect(String host){ + return directHosts.contains(host); + } + /** + Check wether the given host is on the list of direct addresses. + @param host Host address to check. + * @return true if the given host is specified as the direct address. + */ + public boolean isDirect(InetAddress host){ + return directHosts.contains(host); + } + /** + Set the proxy which should be used to connect to given proxy. + @param chainProxy CProxy to use to connect to this proxy. + */ + public void setChainProxy(CProxy chainProxy){ + this.chainProxy = chainProxy; + } + + /** + Get proxy which is used to connect to this proxy. + @return CProxy which is used to connect to this proxy, or null + if proxy is to be contacted directly. + */ + public CProxy getChainProxy(){ + return chainProxy; + } + + /** + Get string representation of this proxy. + * @returns string in the form:proxyHost:proxyPort \t Version versionNumber + */ + public String toString(){ + return (""+proxyIP.getHostName()+":"+proxyPort+"\tVersion "+version); + } + + +//Public Static(Class) Methods +//============================== + + /** + * Sets SOCKS4 proxy as default. + @param hostName Host name on which SOCKS4 server is running. + @param port Port on which SOCKS4 server is running. + @param user Username to use for communications with proxy. + */ + public static void setDefaultProxy(String hostName,int port,String user) + throws UnknownHostException{ + defaultProxy = new Socks4Proxy(hostName,port,user); + } + + /** + * Sets SOCKS4 proxy as default. + @param ipAddress Host address on which SOCKS4 server is running. + @param port Port on which SOCKS4 server is running. + @param user Username to use for communications with proxy. + */ + public static void setDefaultProxy(InetAddress ipAddress,int port, + String user){ + defaultProxy = new Socks4Proxy(ipAddress,port,user); + } + /** + * Sets SOCKS5 proxy as default. + * Default proxy only supports no-authentication. + @param hostName Host name on which SOCKS5 server is running. + @param port Port on which SOCKS5 server is running. + */ + public static void setDefaultProxy(String hostName,int port) + throws UnknownHostException{ + defaultProxy = new Socks5Proxy(hostName,port); + } + /** + * Sets SOCKS5 proxy as default. + * Default proxy only supports no-authentication. + @param ipAddress Host address on which SOCKS5 server is running. + @param port Port on which SOCKS5 server is running. + */ + public static void setDefaultProxy(InetAddress ipAddress,int port){ + defaultProxy = new Socks5Proxy(ipAddress,port); + } + /** + * Sets default proxy. + @param p CProxy to use as default proxy. + */ + public static void setDefaultProxy(CProxy p){ + defaultProxy = p; + } + + /** + Get current default proxy. + * @return Current default proxy, or null if none is set. + */ + public static CProxy getDefaultProxy(){ + return defaultProxy; + } + + /** + Parses strings in the form: host[:port:user:password], and creates + proxy from information obtained from parsing. + <p> + Defaults: port = 1080.<br> + If user specified but not password, creates Socks4Proxy, if user + not specified creates Socks5Proxy, if both user and password are + speciefied creates Socks5Proxy with user/password authentication. + @param proxy_entry String in the form host[:port:user:password] + @return CProxy created from the string, null if entry was somehow + invalid(host unknown for example, or empty string) + */ + public static CProxy parseProxy(String proxy_entry){ + + String proxy_host; + int proxy_port = 1080; + String proxy_user = null; + String proxy_password = null; + CProxy proxy; + + java.util.StringTokenizer st = new java.util.StringTokenizer( + proxy_entry,":"); + if(st.countTokens() < 1) return null; + + proxy_host = st.nextToken(); + if(st.hasMoreTokens()) + try{ + proxy_port = Integer.parseInt(st.nextToken().trim()); + }catch(NumberFormatException nfe){} + + if(st.hasMoreTokens()) + proxy_user = st.nextToken(); + + if(st.hasMoreTokens()) + proxy_password = st.nextToken(); + + try{ + if(proxy_user == null) + proxy = new Socks5Proxy(proxy_host,proxy_port); + else if(proxy_password == null) + proxy = new Socks4Proxy(proxy_host,proxy_port,proxy_user); + else{ + proxy = new Socks5Proxy(proxy_host,proxy_port); + UserPasswordAuthentication upa = new UserPasswordAuthentication( + proxy_user, proxy_password); + + ((Socks5Proxy)proxy).setAuthenticationMethod(upa.METHOD_ID,upa); + } + }catch(UnknownHostException uhe){ + return null; + } + + return proxy; + } + + +//Protected Methods +//================= + + protected void startSession()throws SocksException{ + try{ + if(chainProxy == null) + proxySocket = new Socket(proxyIP,proxyPort); + else if(proxyIP != null) + proxySocket = new SocksSocket(chainProxy,proxyIP,proxyPort); + else + proxySocket = new SocksSocket(chainProxy,proxyHost,proxyPort); + + in = proxySocket.getInputStream(); + out = proxySocket.getOutputStream(); + }catch(SocksException se){ + throw se; + }catch(IOException io_ex){ + throw new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex); + } + } + + protected abstract CProxy copy(); + protected abstract ProxyMessage formMessage(int cmd,InetAddress ip,int port); + protected abstract ProxyMessage formMessage(int cmd,String host,int port) + throws UnknownHostException; + protected abstract ProxyMessage formMessage(InputStream in) + throws SocksException, + IOException; + + + protected ProxyMessage connect(InetAddress ip,int port) + throws SocksException{ + try{ + startSession(); + ProxyMessage request = formMessage(SOCKS_CMD_CONNECT, + ip,port); + return exchange(request); + }catch(SocksException se){ + endSession(); + throw se; + } + } + protected ProxyMessage connect(String host,int port) + throws UnknownHostException,SocksException{ + try{ + startSession(); + ProxyMessage request = formMessage(SOCKS_CMD_CONNECT, + host,port); + return exchange(request); + }catch(SocksException se){ + endSession(); + throw se; + } + } + + protected ProxyMessage bind(InetAddress ip,int port) + throws SocksException{ + try{ + startSession(); + ProxyMessage request = formMessage(SOCKS_CMD_BIND, + ip,port); + return exchange(request); + }catch(SocksException se){ + endSession(); + throw se; + } + } + protected ProxyMessage bind(String host,int port) + throws UnknownHostException,SocksException{ + try{ + startSession(); + ProxyMessage request = formMessage(SOCKS_CMD_BIND, + host,port); + return exchange(request); + }catch(SocksException se){ + endSession(); + throw se; + } + } + + protected ProxyMessage accept() + throws IOException,SocksException{ + ProxyMessage msg; + try{ + msg = formMessage(in); + }catch(InterruptedIOException iioe){ + throw iioe; + }catch(IOException io_ex){ + endSession(); + throw new SocksException(SOCKS_PROXY_IO_ERROR,"While Trying accept:" + +io_ex); + } + return msg; + } + + protected ProxyMessage udpAssociate(InetAddress ip,int port) + throws SocksException{ + try{ + startSession(); + ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE, + ip,port); + if(request != null) + return exchange(request); + }catch(SocksException se){ + endSession(); + throw se; + } + //Only get here if request was null + endSession(); + throw new SocksException(SOCKS_METHOD_NOTSUPPORTED, + "This version of proxy does not support UDP associate, use version 5"); + } + protected ProxyMessage udpAssociate(String host,int port) + throws UnknownHostException,SocksException{ + try{ + startSession(); + ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE, + host,port); + if(request != null) return exchange(request); + }catch(SocksException se){ + endSession(); + throw se; + } + //Only get here if request was null + endSession(); + throw new SocksException(SOCKS_METHOD_NOTSUPPORTED, + "This version of proxy does not support UDP associate, use version 5"); + } + + + protected void endSession(){ + try{ + if(proxySocket!=null) proxySocket.close(); + proxySocket = null; + }catch(IOException io_ex){ + } + } + + /** + *Sends the request to SOCKS server + */ + protected void sendMsg(ProxyMessage msg)throws SocksException, + IOException{ + msg.write(out); + } + + /** + * Reads the reply from the SOCKS server + */ + protected ProxyMessage readMsg()throws SocksException, + IOException{ + return formMessage(in); + } + /** + *Sends the request reads reply and returns it + *throws exception if something wrong with IO + *or the reply code is not zero + */ + protected ProxyMessage exchange(ProxyMessage request) + throws SocksException{ + ProxyMessage reply; + try{ + request.write(out); + reply = formMessage(in); + }catch(SocksException s_ex){ + throw s_ex; + }catch(IOException ioe){ + throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+ioe)); + } + return reply; + } + + +//Private methods +//=============== + + +//Constants + + public static final int SOCKS_SUCCESS =0; + public static final int SOCKS_FAILURE =1; + public static final int SOCKS_BADCONNECT =2; + public static final int SOCKS_BADNETWORK =3; + public static final int SOCKS_HOST_UNREACHABLE =4; + public static final int SOCKS_CONNECTION_REFUSED =5; + public static final int SOCKS_TTL_EXPIRE =6; + public static final int SOCKS_CMD_NOT_SUPPORTED =7; + public static final int SOCKS_ADDR_NOT_SUPPORTED =8; + + public static final int SOCKS_NO_PROXY =1<<16; + public static final int SOCKS_PROXY_NO_CONNECT =2<<16; + public static final int SOCKS_PROXY_IO_ERROR =3<<16; + public static final int SOCKS_AUTH_NOT_SUPPORTED =4<<16; + public static final int SOCKS_AUTH_FAILURE =5<<16; + public static final int SOCKS_JUST_ERROR =6<<16; + + public static final int SOCKS_DIRECT_FAILED =7<<16; + public static final int SOCKS_METHOD_NOTSUPPORTED =8<<16; + + + public static final int SOCKS_CMD_CONNECT =0x1; + static final int SOCKS_CMD_BIND =0x2; + static final int SOCKS_CMD_UDP_ASSOCIATE =0x3; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/InetRange.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,440 @@ +package net.sourceforge.jsocks; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.*; + +/** + * Class InetRange provides the means of defining the range of inetaddresses. + * It's used by Proxy class to store and look up addresses of machines, that + * should be contacted directly rather then through the proxy. + * <P> + * InetRange provides several methods to add either standalone addresses, or + * ranges (e.g. 100.200.300.0:100.200.300.255, which covers all addresses + * on on someones local network). It also provides methods for checking wether + * given address is in this range. Any number of ranges and standalone + * addresses can be added to the range. + */ +public class InetRange implements Cloneable{ + + Hashtable host_names; + Vector all; + Vector end_names; + + boolean useSeparateThread = true; + + /** + * Creates the empty range. + */ + public InetRange(){ + all = new Vector(); + host_names = new Hashtable(); + end_names = new Vector(); + } + + /** + * Adds another host or range to this range. + The String can be one of those: + <UL> + <li> Host name. eg.(Athena.myhost.com or 45.54.56.65) + + <li> Range in the form .myhost.net.au <BR> + In which case anything that ends with .myhost.net.au will + be considered in the range. + + <li> Range in the form ddd.ddd.ddd. <BR> + This will be treated as range ddd.ddd.ddd.0 to ddd.ddd.ddd.255. + It is not necessary to specify 3 first bytes you can use just + one or two. For example 130. will cover address between 130.0.0.0 + and 13.255.255.255. + + <li> Range in the form host_from[: \t\n\r\f]host_to. <br> + That is two hostnames or ips separated by either whitespace + or colon. + </UL> + */ + public synchronized boolean add(String s){ + if(s == null) return false; + + s = s.trim(); + if(s.length() == 0) return false; + + Object[] entry; + + if(s.charAt(s.length()-1) == '.'){ + //thing like: 111.222.33. + //it is being treated as range 111.222.33.000 - 111.222.33.255 + + int[] addr = ip2intarray(s); + long from,to; + from = to = 0; + + if(addr == null) return false; + for(int i = 0; i< 4;++i){ + if(addr[i]>=0) + from += (((long)addr[i]) << 8*(3-i)); + else{ + to = from; + while(i<4) + to += 255l << 8*(3-i++); + break; + } + } + entry = new Object[] {s,null,new Long(from),new Long(to)}; + all.addElement(entry); + + }else if(s.charAt(0) == '.'){ + //Thing like: .myhost.com + + end_names.addElement(s); + all.addElement(new Object[]{s,null,null,null}); + }else{ + StringTokenizer tokens = new StringTokenizer(s," \t\r\n\f:"); + if(tokens.countTokens() > 1){ + entry = new Object[] {s,null,null,null}; + resolve(entry,tokens.nextToken(),tokens.nextToken()); + all.addElement(entry); + }else{ + entry = new Object[] {s,null,null,null}; + all.addElement(entry); + host_names.put(s,entry); + resolve(entry); + } + + } + + return true; + } + + /** + * Adds another ip for this range. + @param ip IP os the host which should be added to this range. + */ + public synchronized void add(InetAddress ip){ + long from, to; + from = to = ip2long(ip); + all.addElement(new Object[]{ip.getHostName(),ip,new Long(from), + new Long(to)}); + } + + /** + * Adds another range of ips for this range.Any host with ip address + greater than or equal to the address of from and smaller than or equal + to the address of to will be included in the range. + @param from IP from where range starts(including). + @param to IP where range ends(including). + */ + public synchronized void add(InetAddress from,InetAddress to){ + all.addElement(new Object[]{from.getHostAddress()+":"+to.getHostAddress() + ,null,new Long(ip2long(from)), + new Long(ip2long(to))}); + } + + /** + * Checks wether the givan host is in the range. Attempts to resolve + host name if required. + @param host Host name to check. + @return true If host is in the range, false otherwise. + * @see InetRange#contains(String,boolean) + */ + public synchronized boolean contains(String host){ + return contains(host,true); + } + + /** + * Checks wether the given host is in the range. + * <P> + * Algorithm: <BR> + * <ol> + * <li>Look up if the hostname is in the range (in the Hashtable). + * <li>Check if it ends with one of the speciefied endings. + * <li>Check if it is ip(eg.130.220.35.98). If it is check if it is + * in the range. + * <li>If attemptResolve is true, host is name, rather than ip, and + * all previous attempts failed, try to resolve the hostname, and + * check wether the ip associated with the host is in the range.It + * also repeats all previos steps with the hostname obtained from + * InetAddress, but the name is not allways the full name,it is + * quite likely to be the same. Well it was on my machine. + * </ol> + @param host Host name to check. + @param attemptResolve Wether to lookup ip address which corresponds + to the host,if required. + @return true If host is in the range, false otherwise. + */ + public synchronized boolean contains(String host,boolean attemptResolve){ + if(all.size() ==0) return false; //Empty range + + host = host.trim(); + if(host.length() == 0) return false; + + if(checkHost(host)) return true; + if(checkHostEnding(host)) return true; + + long l = host2long(host); + if(l >=0) return contains(l); + + if(!attemptResolve) return false; + + try{ + InetAddress ip = InetAddress.getByName(host); + return contains(ip); + }catch(UnknownHostException uhe){ + + } + + return false; + } + + /** + * Checks wether the given ip is in the range. + @param ip Address of the host to check. + @return true If host is in the range, false otherwise. + */ + public synchronized boolean contains(InetAddress ip){ + if(checkHostEnding(ip.getHostName())) return true; + if(checkHost(ip.getHostName())) return true; + return contains(ip2long(ip)); + } + /** + Get all entries in the range as strings. <BR> + These strings can be used to delete entries from the range + with remove function. + @return Array of entries as strings. + @see InetRange#remove(String) + */ + public synchronized String[] getAll(){ + int size = all.size(); + Object entry[]; + String all_names[] = new String[size]; + + for(int i=0;i<size;++i){ + entry = (Object[]) all.elementAt(i); + all_names[i] = (String) entry[0]; + } + return all_names; + } + /** + Removes an entry from this range.<BR> + @param s Entry to remove. + @return true if successfull. + */ + public synchronized boolean remove(String s){ + Enumeration eEnum = all.elements(); + while(eEnum.hasMoreElements()){ + Object[] entry = (Object[]) eEnum.nextElement(); + if(s.equals(entry[0])){ + all.removeElement(entry); + end_names.removeElement(s); + host_names.remove(s); + return true; + } + } + return false; + } + + /** Get string representaion of this Range.*/ + public String toString(){ + String all[] = getAll(); + if(all.length == 0) return ""; + + String s = all[0]; + for(int i=1;i<all.length;++i) + s += "; "+all[i]; + return s; + } + + /** Creates a clone of this Object*/ + public Object clone(){ + InetRange new_range = new InetRange(); + new_range.all = (Vector)all.clone(); + new_range.end_names = (Vector) end_names.clone(); + new_range.host_names = (Hashtable)host_names.clone(); + return new_range; + } + + +//Private methods +///////////////// + /** + * Same as previous but used internally, to avoid + * unnecessary convertion of IPs, when checking subranges + */ + private synchronized boolean contains(long ip){ + Enumeration eEnum = all.elements(); + while(eEnum.hasMoreElements()){ + Object[] obj = (Object[]) eEnum.nextElement(); + Long from = obj[2]==null?null:(Long)obj[2]; + Long to = obj[3]==null?null:(Long)obj[3]; + if(from != null && from.longValue()<= ip + && to.longValue() >= ip) return true; + + } + return false; + } + + private boolean checkHost(String host){ + return host_names.containsKey(host); + } + private boolean checkHostEnding(String host){ + Enumeration eEnum = end_names.elements(); + while(eEnum.hasMoreElements()){ + if(host.endsWith((String) eEnum.nextElement())) return true; + } + return false; + } + private void resolve(Object[] entry){ + //First check if it's in the form ddd.ddd.ddd.ddd. + long ip = host2long((String) entry[0]); + if(ip >= 0){ + entry[2] = entry[3] = new Long(ip); + }else{ + InetRangeResolver res = new InetRangeResolver(entry); + res.resolve(useSeparateThread); + } + } + private void resolve(Object[] entry,String from,String to){ + long f,t; + if((f=host2long(from))>= 0 && (t=host2long(to)) >= 0){ + entry[2] = new Long(f); + entry[3] = new Long(t); + }else{ + InetRangeResolver res = new InetRangeResolver(entry,from,to); + res.resolve(useSeparateThread); + } + } + + + +//Class methods +/////////////// + + //Converts ipv4 to long value(unsigned int) + /////////////////////////////////////////// + static long ip2long(InetAddress ip){ + long l=0; + byte[] addr = ip.getAddress(); + + if(addr.length ==4){ //IPV4 + for(int i=0;i<4;++i) + l += (((long)addr[i] &0xFF) << 8*(3-i)); + }else{ //IPV6 + return 0; //Have no idea how to deal with those + } + return l; + } + + + long host2long(String host){ + long ip=0; + + //check if it's ddd.ddd.ddd.ddd + if(!Character.isDigit(host.charAt(0))) return -1; + + int[] addr = ip2intarray(host); + if(addr == null) return -1; + + for(int i=0;i<addr.length;++i) + ip += ((long)(addr[i]>=0 ? addr[i] : 0)) << 8*(3-i); + + return ip; + } + + static int[] ip2intarray(String host){ + int[] address = {-1,-1,-1,-1}; + int i=0; + StringTokenizer tokens = new StringTokenizer(host,"."); + if(tokens.countTokens() > 4) return null; + while(tokens.hasMoreTokens()){ + try{ + address[i++] = Integer.parseInt(tokens.nextToken()) & 0xFF; + }catch(NumberFormatException nfe){ + return null; + } + + } + return address; + } + + +/* +//* This was the test main function +//********************************** + + public static void main(String args[])throws UnknownHostException{ + int i; + + InetRange ir = new InetRange(); + + + for(i=0;i<args.length;++i){ + System.out.println("Adding:" + args[i]); + ir.add(args[i]); + } + + String host; + java.io.DataInputStream din = new java.io.DataInputStream(System.in); + try{ + host = din.readLine(); + while(host!=null){ + if(ir.contains(host)){ + System.out.println("Range contains ip:"+host); + }else{ + System.out.println(host+" is not in the range"); + } + host = din.readLine(); + } + }catch(java.io.IOException io_ex){ + io_ex.printStackTrace(); + } + } +********************/ + +} + + +class InetRangeResolver implements Runnable{ + + Object[] entry; + + String from, to; + + InetRangeResolver(Object[] entry){ + this.entry = entry; + from = to = null; + } + InetRangeResolver(Object[] entry,String from,String to){ + this.entry = entry; + this.from = from; + this.to = to; + } + public final void resolve(){ + resolve(true); + } + public final void resolve(boolean inSeparateThread){ + if(inSeparateThread){ + Thread t = new Thread(this); + t.start(); + }else + run(); + + } + public void run(){ + try{ + if(from == null){ + InetAddress ip = InetAddress.getByName((String) entry[0]); + entry[1] = ip; + Long l = new Long(InetRange.ip2long(ip)); + entry[2] = entry[3] = l; + }else{ + InetAddress f = InetAddress.getByName(from); + InetAddress t = InetAddress.getByName(to); + entry[2] = new Long(InetRange.ip2long(f)); + entry[3] = new Long(InetRange.ip2long(t)); + + } + }catch(UnknownHostException uhe){ + //System.err.println("Resolve failed for "+from+','+to+','+entry[0]); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/ProxyMessage.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,110 @@ +package net.sourceforge.jsocks; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.DataInputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + Abstract class which describes SOCKS4/5 response/request. +*/ +public abstract class ProxyMessage{ + /** Host as an IP address */ + public InetAddress ip=null; + /** SOCKS version, or version of the response for SOCKS4*/ + public int version; + /** Port field of the request/response*/ + public int port; + /** Request/response code as an int*/ + public int command; + /** Host as string.*/ + public String host=null; + /** User field for SOCKS4 request messages*/ + public String user=null; + + ProxyMessage(int command,InetAddress ip,int port){ + this.command = command; + this.ip = ip; + this.port = port; + } + + ProxyMessage(){ + } + + + /** + Initialises Message from the stream. Reads server response from + given stream. + @param in Input stream to read response from. + @throws SocksException If server response code is not SOCKS_SUCCESS(0), or + if any error with protocol occurs. + @throws IOException If any error happens with I/O. + */ + public abstract void read(InputStream in) + throws SocksException, + IOException; + + + /** + Initialises Message from the stream. Reads server response or client + request from given stream. + + @param in Input stream to read response from. + @param clinetMode If true read server response, else read client request. + @throws SocksException If server response code is not SOCKS_SUCCESS(0) and + reading in client mode, or if any error with protocol occurs. + @throws IOException If any error happens with I/O. + */ + public abstract void read(InputStream in,boolean client_mode) + throws SocksException, + IOException; + + + /** + Writes the message to the stream. + @param out Output stream to which message should be written. + */ + public abstract void write(OutputStream out)throws SocksException, + IOException; + + /** + Get the Address field of this message as InetAddress object. + @return Host address or null, if one can't be determined. + */ + public InetAddress getInetAddress() throws UnknownHostException{ + return ip; + } + + + /** + Get string representaion of this message. + @return string representation of this message. + */ + public String toString(){ + return + "Proxy Message:\n"+ + "Version:"+ version+"\n"+ + "Command:"+ command+"\n"+ + "IP: "+ ip+"\n"+ + "Port: "+ port+"\n"+ + "User: "+ user+"\n" ; + } + +//Package methods +////////////////// + + static final String bytes2IPV4(byte[] addr,int offset){ + String hostName = ""+(addr[offset] & 0xFF); + for(int i = offset+1;i<offset+4;++i) + hostName+="."+(addr[i] & 0xFF); + return hostName; + } + + static final String bytes2IPV6(byte[] addr,int offset){ + //Have no idea how they look like! + return null; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/ProxyServer.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,604 @@ +package net.sourceforge.jsocks; +import net.sourceforge.jsocks.server.ServerAuthenticator; +import java.net.*; +import java.io.*; + +/** + SOCKS4 and SOCKS5 proxy, handles both protocols simultaniously. + Implements all SOCKS commands, including UDP relaying. + <p> + In order to use it you will need to implement ServerAuthenticator + interface. There is an implementation of this interface which does + no authentication ServerAuthenticatorNone, but it is very dangerous + to use, as it will give access to your local network to anybody + in the world. One should never use this authentication scheme unless + one have pretty good reason to do so. + There is a couple of other authentication schemes in socks.server package. + @see socks.server.ServerAuthenticator +*/ +public class ProxyServer implements Runnable{ + + ServerAuthenticator auth; + ProxyMessage msg = null; + + Socket sock=null,remote_sock=null; + ServerSocket ss=null; + UDPRelayServer relayServer = null; + InputStream in,remote_in; + OutputStream out,remote_out; + + int mode; + static final int START_MODE = 0; + static final int ACCEPT_MODE = 1; + static final int PIPE_MODE = 2; + static final int ABORT_MODE = 3; + + static final int BUF_SIZE = 8192; + + Thread pipe_thread1,pipe_thread2; + long lastReadTime; + + static int iddleTimeout = 180000; //3 minutes + static int acceptTimeout = 180000; //3 minutes + + static PrintStream log = null; + static CProxy proxy; + + +//Public Constructors +///////////////////// + + + /** + Creates a proxy server with given Authentication scheme. + @param auth Authentication scheme to be used. + */ + public ProxyServer(ServerAuthenticator auth){ + this.auth = auth; + } + +//Other constructors +//////////////////// + + ProxyServer(ServerAuthenticator auth,Socket s){ + this.auth = auth; + this.sock = s; + mode = START_MODE; + } + +//Public methods +///////////////// + + /** + Set the logging stream. Specifying null disables logging. + */ + public static void setLog(OutputStream out){ + if(out == null){ + log = null; + }else{ + log = new PrintStream(out,true); + } + + UDPRelayServer.log = log; + } + + /** + Set proxy. + <p> + Allows CProxy chaining so that one CProxy server is connected to another + and so on. If proxy supports SOCKSv4, then only some SOCKSv5 requests + can be handled, UDP would not work, however CONNECT and BIND will be + translated. + + @param p CProxy which should be used to handle user requests. + */ + public static void setProxy(CProxy p){ + proxy =p; + UDPRelayServer.proxy = proxy; + } + + /** + Get proxy. + @return CProxy wich is used to handle user requests. + */ + public static CProxy getProxy(){ + return proxy; + } + + /** + Sets the timeout for connections, how long shoud server wait + for data to arrive before dropping the connection.<br> + Zero timeout implies infinity.<br> + Default timeout is 3 minutes. + */ + public static void setIddleTimeout(int timeout){ + iddleTimeout = timeout; + } + /** + Sets the timeout for BIND command, how long the server should + wait for the incoming connection.<br> + Zero timeout implies infinity.<br> + Default timeout is 3 minutes. + */ + public static void setAcceptTimeout(int timeout){ + acceptTimeout = timeout; + } + + /** + Sets the timeout for UDPRelay server.<br> + Zero timeout implies infinity.<br> + Default timeout is 3 minutes. + */ + public static void setUDPTimeout(int timeout){ + UDPRelayServer.setTimeout(timeout); + } + + /** + Sets the size of the datagrams used in the UDPRelayServer.<br> + Default size is 64K, a bit more than maximum possible size of the + datagram. + */ + public static void setDatagramSize(int size){ + UDPRelayServer.setDatagramSize(size); + } + + + /** + Start the CProxy server at given port.<br> + This methods blocks. + */ + public void start(int port){ + start(port,5,null); + } + + /** + Create a server with the specified port, listen backlog, and local + IP address to bind to. The localIP argument can be used on a multi-homed + host for a ServerSocket that will only accept connect requests to one of + its addresses. If localIP is null, it will default accepting connections + on any/all local addresses. The port must be between 0 and 65535, + inclusive. <br> + This methods blocks. + */ + public void start(int port,int backlog,InetAddress localIP){ + try{ + ss = new ServerSocket(port,backlog,localIP); + log("Starting SOCKS Proxy on:"+ss.getInetAddress().getHostAddress()+":" + +ss.getLocalPort()); + while(true){ + Socket s = ss.accept(); + log("Accepted from:"+s.getInetAddress().getHostName()+":" + +s.getPort()); + ProxyServer ps = new ProxyServer(auth,s); + (new Thread(ps)).start(); + } + }catch(IOException ioe){ + ioe.printStackTrace(); + }finally{ + } + } + + /** + Stop server operation.It would be wise to interrupt thread running the + server afterwards. + */ + public void stop(){ + try{ + if(ss != null) ss.close(); + }catch(IOException ioe){ + } + } + +//Runnable interface +//////////////////// + public void run(){ + switch(mode){ + case START_MODE: + try{ + startSession(); + }catch(IOException ioe){ + handleException(ioe); + //ioe.printStackTrace(); + }finally{ + abort(); + if(auth!=null) auth.endSession(); + log("Main thread(client->remote)stopped."); + } + break; + case ACCEPT_MODE: + try{ + doAccept(); + mode = PIPE_MODE; + pipe_thread1.interrupt(); //Tell other thread that connection have + //been accepted. + pipe(remote_in,out); + }catch(IOException ioe){ + //log("Accept exception:"+ioe); + handleException(ioe); + }finally{ + abort(); + log("Accept thread(remote->client) stopped"); + } + break; + case PIPE_MODE: + try{ + pipe(remote_in,out); + }catch(IOException ioe){ + }finally{ + abort(); + log("Support thread(remote->client) stopped"); + } + break; + case ABORT_MODE: + break; + default: + log("Unexpected MODE "+mode); + } + } + +//Private methods +///////////////// + private void startSession() throws IOException{ + sock.setSoTimeout(iddleTimeout); + + try{ + auth = auth.startSession(sock); + }catch(IOException ioe){ + log("Auth throwed exception:"+ioe); + auth = null; + return; + } + + if(auth == null){ //Authentication failed + log("Authentication failed"); + return; + } + + in = auth.getInputStream(); + out = auth.getOutputStream(); + + msg = readMsg(in); + handleRequest(msg); + } + + private void handleRequest(ProxyMessage msg) + throws IOException{ + if(!auth.checkRequest(msg)) throw new + SocksException(CProxy.SOCKS_FAILURE); + + if(msg.ip == null){ + if(msg instanceof Socks5Message){ + msg.ip = InetAddress.getByName(msg.host); + }else + throw new SocksException(CProxy.SOCKS_FAILURE); + } + log(msg); + + switch(msg.command){ + case CProxy.SOCKS_CMD_CONNECT: + onConnect(msg); + break; + case CProxy.SOCKS_CMD_BIND: + onBind(msg); + break; + case CProxy.SOCKS_CMD_UDP_ASSOCIATE: + onUDP(msg); + break; + default: + throw new SocksException(CProxy.SOCKS_CMD_NOT_SUPPORTED); + } + } + + private void handleException(IOException ioe){ + //If we couldn't read the request, return; + if(msg == null) return; + //If have been aborted by other thread + if(mode == ABORT_MODE) return; + //If the request was successfully completed, but exception happened later + if(mode == PIPE_MODE) return; + + int error_code = CProxy.SOCKS_FAILURE; + + if(ioe instanceof SocksException) + error_code = ((SocksException)ioe).errCode; + else if(ioe instanceof NoRouteToHostException) + error_code = CProxy.SOCKS_HOST_UNREACHABLE; + else if(ioe instanceof ConnectException) + error_code = CProxy.SOCKS_CONNECTION_REFUSED; + else if(ioe instanceof InterruptedIOException) + error_code = CProxy.SOCKS_TTL_EXPIRE; + + if(error_code > CProxy.SOCKS_ADDR_NOT_SUPPORTED || error_code < 0){ + error_code = CProxy.SOCKS_FAILURE; + } + + sendErrorMessage(error_code); + } + + private void onConnect(ProxyMessage msg) throws IOException { + Socket s = null; + ProxyMessage response = null; + int iSock5Cmd = CProxy.SOCKS_FAILURE; //defaulting to failure + int iSock4Msg = Socks4Message.REPLY_NO_CONNECT; + InetAddress sIp = null; int iPort = 0; + + try { + if (proxy == null) { + s = new Socket(msg.ip, msg.port); + } else { + s = new SocksSocket(proxy, msg.ip, msg.port); + } + log("Connected to " + s.getInetAddress() + ":" + s.getPort()); + + iSock5Cmd = CProxy.SOCKS_SUCCESS; iSock4Msg = Socks4Message.REPLY_OK; + sIp = s.getInetAddress(); iPort = s.getPort(); + + } + catch (Exception sE) { + log("Failed connecting to remote socket. Exception: " + sE.getLocalizedMessage()); + + //TBD Pick proper socks error for corresponding socket error, below is too generic + iSock5Cmd = CProxy.SOCKS_CONNECTION_REFUSED; iSock4Msg = Socks4Message.REPLY_NO_CONNECT; + } + + if (msg instanceof Socks5Message) { + response = new Socks5Message(iSock5Cmd, sIp, iPort); + } else { + response = new Socks4Message(iSock4Msg, sIp, iPort); + } + + response.write(out); + + if (s != null) { + startPipe(s); + } + else { + throw (new RuntimeException("onConnect() Failed to create Socket()")); + } + + return; + } + + + private void onBind(ProxyMessage msg) throws IOException{ + ProxyMessage response = null; + + if(proxy == null) + ss = new ServerSocket(0); + else + ss = new SocksServerSocket(proxy, msg.ip, msg.port); + + ss.setSoTimeout(acceptTimeout); + + log("Trying accept on "+ss.getInetAddress()+":"+ss.getLocalPort()); + + if(msg.version == 5) + response = new Socks5Message(CProxy.SOCKS_SUCCESS,ss.getInetAddress(), + ss.getLocalPort()); + else + response = new Socks4Message(Socks4Message.REPLY_OK, + ss.getInetAddress(), + ss.getLocalPort()); + response.write(out); + + mode = ACCEPT_MODE; + + pipe_thread1 = Thread.currentThread(); + pipe_thread2 = new Thread(this); + pipe_thread2.start(); + + //Make timeout infinit. + sock.setSoTimeout(0); + int eof=0; + + try{ + while((eof=in.read())>=0){ + if(mode != ACCEPT_MODE){ + if(mode != PIPE_MODE) return;//Accept failed + + remote_out.write(eof); + break; + } + } + }catch(EOFException eofe){ + //System.out.println("EOF exception"); + return;//Connection closed while we were trying to accept. + }catch(InterruptedIOException iioe){ + //Accept thread interrupted us. + //System.out.println("Interrupted"); + if(mode != PIPE_MODE) + return;//If accept thread was not successfull return. + }finally{ + //System.out.println("Finnaly!"); + } + + if(eof < 0)//Connection closed while we were trying to accept; + return; + + //Do not restore timeout, instead timeout is set on the + //remote socket. It does not make any difference. + + pipe(in,remote_out); + } + + private void onUDP(ProxyMessage msg) throws IOException{ + if(msg.ip.getHostAddress().equals("0.0.0.0")) + msg.ip = sock.getInetAddress(); + log("Creating UDP relay server for "+msg.ip+":"+msg.port); + relayServer = new UDPRelayServer(msg.ip,msg.port, + Thread.currentThread(),sock,auth); + + ProxyMessage response; + + response = new Socks5Message(CProxy.SOCKS_SUCCESS, + relayServer.relayIP,relayServer.relayPort); + + response.write(out); + + relayServer.start(); + + //Make timeout infinit. + sock.setSoTimeout(0); + try{ + while(in.read()>=0) /*do nothing*/; + }catch(EOFException eofe){ + } + } + +//Private methods +////////////////// + + private void doAccept() throws IOException{ + Socket s; + long startTime = System.currentTimeMillis(); + + while(true){ + s = ss.accept(); + if(s.getInetAddress().equals(msg.ip)){ + //got the connection from the right host + //Close listenning socket. + ss.close(); + break; + }else if(ss instanceof SocksServerSocket){ + //We can't accept more then one connection + s.close(); + ss.close(); + throw new SocksException(CProxy.SOCKS_FAILURE); + }else{ + if(acceptTimeout!=0){ //If timeout is not infinit + int newTimeout = acceptTimeout-(int)(System.currentTimeMillis()- + startTime); + if(newTimeout <= 0) throw new InterruptedIOException( + "In doAccept()"); + ss.setSoTimeout(newTimeout); + } + s.close(); //Drop all connections from other hosts + } + } + + //Accepted connection + remote_sock = s; + remote_in = s.getInputStream(); + remote_out = s.getOutputStream(); + + //Set timeout + remote_sock.setSoTimeout(iddleTimeout); + + log("Accepted from "+s.getInetAddress()+":"+s.getPort()); + + ProxyMessage response; + + if(msg.version == 5) + response = new Socks5Message(CProxy.SOCKS_SUCCESS, s.getInetAddress(), + s.getPort()); + else + response = new Socks4Message(Socks4Message.REPLY_OK, + s.getInetAddress(), s.getPort()); + response.write(out); + } + + private ProxyMessage readMsg(InputStream in) throws IOException{ + PushbackInputStream push_in; + if(in instanceof PushbackInputStream) + push_in = (PushbackInputStream) in; + else + push_in = new PushbackInputStream(in); + + int version = push_in.read(); + push_in.unread(version); + + + ProxyMessage msg; + + if(version == 5){ + msg = new Socks5Message(push_in,false); + }else if(version == 4){ + msg = new Socks4Message(push_in,false); + }else{ + throw new SocksException(CProxy.SOCKS_FAILURE); + } + return msg; + } + + private void startPipe(Socket s){ + mode = PIPE_MODE; + remote_sock = s; + try{ + remote_in = s.getInputStream(); + remote_out = s.getOutputStream(); + pipe_thread1 = Thread.currentThread(); + pipe_thread2 = new Thread(this); + pipe_thread2.start(); + pipe(in,remote_out); + }catch(IOException ioe){ + } + } + + private void sendErrorMessage(int error_code){ + ProxyMessage err_msg; + if(msg instanceof Socks4Message) + err_msg = new Socks4Message(Socks4Message.REPLY_REJECTED); + else + err_msg = new Socks5Message(error_code); + try{ + err_msg.write(out); + }catch(IOException ioe){} + } + + private synchronized void abort(){ + if(mode == ABORT_MODE) return; + mode = ABORT_MODE; + try{ + log("Aborting operation"); + if(remote_sock != null) remote_sock.close(); + if(sock != null) sock.close(); + if(relayServer!=null) relayServer.stop(); + if(ss!=null) ss.close(); + if(pipe_thread1 != null) pipe_thread1.interrupt(); + if(pipe_thread2 != null) pipe_thread2.interrupt(); + }catch(IOException ioe){} + } + + static final void log(String s){ + if(log != null){ + log.println(s); + log.flush(); + } + } + + static final void log(ProxyMessage msg){ + log("Request version:"+msg.version+ + "\tCommand: "+command2String(msg.command)); + log("IP:"+msg.ip +"\tPort:"+msg.port+ + (msg.version==4?"\tUser:"+msg.user:"")); + } + + private void pipe(InputStream in,OutputStream out) throws IOException{ + lastReadTime = System.currentTimeMillis(); + byte[] buf = new byte[BUF_SIZE]; + int len = 0; + while(len >= 0){ + try{ + if(len!=0){ + out.write(buf,0,len); + out.flush(); + } + len= in.read(buf); + lastReadTime = System.currentTimeMillis(); + }catch(InterruptedIOException iioe){ + if(iddleTimeout == 0) return;//Other thread interrupted us. + long timeSinceRead = System.currentTimeMillis() - lastReadTime; + if(timeSinceRead >= iddleTimeout - 1000) //-1s for adjustment. + return; + len = 0; + + } + } + } + static final String command_names[] = {"CONNECT","BIND","UDP_ASSOCIATE"}; + + static final String command2String(int cmd){ + if(cmd > 0 && cmd < 4) return command_names[cmd-1]; + else return "Unknown Command "+cmd; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/Socks4Message.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,157 @@ +package net.sourceforge.jsocks; +import java.io.*; +import java.net.*; + +/** + SOCKS4 Reply/Request message. +*/ + +public class Socks4Message extends ProxyMessage{ + + private byte[] msgBytes; + private int msgLength; + + /** + * Server failed reply, cmd command for failed request + */ + public Socks4Message(int cmd){ + super(cmd,null,0); + this.user = null; + + msgLength = 2; + msgBytes = new byte[2]; + + msgBytes[0] = (byte) 0; + msgBytes[1] = (byte) command; + } + + /** + * Server successfull reply + */ + public Socks4Message(int cmd,InetAddress ip,int port){ + this(0,cmd,ip,port,null); + } + + /** + * Client request + */ + public Socks4Message(int cmd,InetAddress ip,int port,String user){ + this(SOCKS_VERSION,cmd,ip,port,user); + } + + /** + * Most general constructor + */ + public Socks4Message(int version, int cmd, + InetAddress ip,int port,String user){ + super(cmd,ip,port); + this.user = user; + this.version = version; + + msgLength = user == null?8:9+user.length(); + msgBytes = new byte[msgLength]; + + msgBytes[0] = (byte) version; + msgBytes[1] = (byte) command; + msgBytes[2] = (byte) (port >> 8); + msgBytes[3] = (byte) port; + + byte[] addr; + + if(ip != null) + addr = ip.getAddress(); + else{ + addr = new byte[4]; + addr[0]=addr[1]=addr[2]=addr[3]=0; + } + System.arraycopy(addr,0,msgBytes,4,4); + + if(user != null){ + byte[] buf = user.getBytes(); + System.arraycopy(buf,0,msgBytes,8,buf.length); + msgBytes[msgBytes.length -1 ] = 0; + } + } + + /** + *Initialise from the stream + *If clientMode is true attempts to read a server response + *otherwise reads a client request + *see read for more detail + */ + public Socks4Message(InputStream in, boolean clientMode) throws IOException{ + msgBytes = null; + read(in,clientMode); + } + + public void read(InputStream in) throws IOException{ + read(in,true); + } + + public void read(InputStream in, boolean clientMode) throws IOException{ + DataInputStream d_in = new DataInputStream(in); + version= d_in.readUnsignedByte(); + command = d_in.readUnsignedByte(); + if(clientMode && command != REPLY_OK){ + String errMsg; + if(command >REPLY_OK && command < REPLY_BAD_IDENTD) + errMsg = replyMessage[command-REPLY_OK]; + else + errMsg = "Unknown Reply Code"; + throw new SocksException(command,errMsg); + } + port = d_in.readUnsignedShort(); + byte[] addr = new byte[4]; + d_in.readFully(addr); + ip=bytes2IP(addr); + host = ip.getHostName(); + if(!clientMode){ + int b = in.read(); + //Hope there are no idiots with user name bigger than this + byte[] userBytes = new byte[256]; + int i = 0; + for(i =0;i<userBytes.length && b>0;++i){ + userBytes[i] = (byte) b; + b = in.read(); + } + user = new String(userBytes,0,i); + } + } + public void write(OutputStream out) throws IOException{ + if(msgBytes == null){ + Socks4Message msg = new Socks4Message(version,command,ip,port,user); + msgBytes = msg.msgBytes; + msgLength = msg.msgLength; + } + out.write(msgBytes); + } + + //Class methods + static InetAddress bytes2IP(byte[] addr){ + String s = bytes2IPV4(addr,0); + try{ + return InetAddress.getByName(s); + }catch(UnknownHostException uh_ex){ + return null; + } + } + + //Constants + + static final String[] replyMessage ={ + "Request Granted", + "Request Rejected or Failed", + "Failed request, can't connect to Identd", + "Failed request, bad user name"}; + + static final int SOCKS_VERSION = 4; + + public final static int REQUEST_CONNECT = 1; + public final static int REQUEST_BIND = 2; + + public final static int REPLY_OK = 90; + public final static int REPLY_REJECTED = 91; + public final static int REPLY_NO_CONNECT = 92; + public final static int REPLY_BAD_IDENTD = 93; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/Socks4Proxy.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,121 @@ +package net.sourceforge.jsocks; +import java.net.*; +import java.io.*; +import java.util.Hashtable; +import java.util.Enumeration; + +/** + CProxy which describes SOCKS4 proxy. +*/ + +public class Socks4Proxy extends CProxy implements Cloneable{ + +//Data members + String user; + +//Public Constructors +//==================== + + /** + Creates the SOCKS4 proxy + @param p CProxy to use to connect to this proxy, allows proxy chaining. + @param proxyHost Address of the proxy server. + @param proxyPort Port of the proxy server + @param user User name to use for identification purposes. + @throws UnknownHostException If proxyHost can't be resolved. + */ + public Socks4Proxy(CProxy p,String proxyHost,int proxyPort,String user) + throws UnknownHostException{ + super(p,proxyHost,proxyPort); + this.user = new String(user); + version = 4; + } + + /** + Creates the SOCKS4 proxy + @param proxyHost Address of the proxy server. + @param proxyPort Port of the proxy server + @param user User name to use for identification purposes. + @throws UnknownHostException If proxyHost can't be resolved. + */ + public Socks4Proxy(String proxyHost,int proxyPort,String user) + throws UnknownHostException{ + this(null,proxyHost,proxyPort,user); + } + + /** + Creates the SOCKS4 proxy + @param p CProxy to use to connect to this proxy, allows proxy chaining. + @param proxyIP Address of the proxy server. + @param proxyPort Port of the proxy server + @param user User name to use for identification purposes. + */ + public Socks4Proxy(CProxy p,InetAddress proxyIP,int proxyPort,String user){ + super(p,proxyIP,proxyPort); + this.user = new String(user); + version = 4; + } + + /** + Creates the SOCKS4 proxy + @param proxyIP Address of the proxy server. + @param proxyPort Port of the proxy server + @param user User name to use for identification purposes. + */ + public Socks4Proxy(InetAddress proxyIP,int proxyPort,String user){ + this(null,proxyIP,proxyPort,user); + } + +//Public instance methods +//======================== + + /** + * Creates a clone of this proxy. Changes made to the clone should not + * affect this object. + */ + public Object clone(){ + Socks4Proxy newProxy = new Socks4Proxy(proxyIP,proxyPort,user); + newProxy.directHosts = (InetRange)directHosts.clone(); + newProxy.chainProxy = chainProxy; + return newProxy; + } + + +//Public Static(Class) Methods +//============================== + + +//Protected Methods +//================= + + protected CProxy copy(){ + Socks4Proxy copy = new Socks4Proxy(proxyIP,proxyPort,user); + copy.directHosts = this.directHosts; + copy.chainProxy = chainProxy; + return copy; + } + + protected ProxyMessage formMessage(int cmd,InetAddress ip,int port){ + switch(cmd){ + case SOCKS_CMD_CONNECT: + cmd = Socks4Message.REQUEST_CONNECT; + break; + case SOCKS_CMD_BIND: + cmd = Socks4Message.REQUEST_BIND; + break; + default: + return null; + } + return new Socks4Message(cmd,ip,port,user); + } + protected ProxyMessage formMessage(int cmd,String host,int port) + throws UnknownHostException{ + return formMessage(cmd,InetAddress.getByName(host),port); + } + protected ProxyMessage formMessage(InputStream in) + throws SocksException, + IOException{ + return new Socks4Message(in,true); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/Socks5DatagramSocket.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,487 @@ +package net.sourceforge.jsocks; +import java.net.*; +import java.io.*; + +/** + Datagram socket to interract through the firewall.<BR> + Can be used same way as the normal DatagramSocket. One should + be carefull though with the datagram sizes used, as additional data + is present in both incomming and outgoing datagrams. + <p> + SOCKS5 protocol allows to send host address as either: + <ul> + <li> IPV4, normal 4 byte address. (10 bytes header size) + <li> IPV6, version 6 ip address (not supported by Java as for now). + 22 bytes header size. + <li> Host name,(7+length of the host name bytes header size). + </ul> + As with other Socks equivalents, direct addresses are handled + transparently, that is data will be send directly when required + by the proxy settings. + <p> + <b>NOTE:</b><br> + Unlike other SOCKS Sockets, it <b>does not</b> support proxy chaining, + and will throw an exception if proxy has a chain proxy attached. The + reason for that is not my laziness, but rather the restrictions of + the SOCKSv5 protocol. Basicaly SOCKSv5 proxy server, needs to know from + which host:port datagrams will be send for association, and returns address + to which datagrams should be send by the client, but it does not + inform client from which host:port it is going to send datagrams, in fact + there is even no guarantee they will be send at all and from the same address + each time. + + */ +public class Socks5DatagramSocket extends DatagramSocket{ + + InetAddress relayIP; + int relayPort; + Socks5Proxy proxy; + private boolean server_mode = false; + UDPEncapsulation encapsulation; + + + /** + Construct Datagram socket for communication over SOCKS5 proxy + server. This constructor uses default proxy, the one set with + CProxy.setDefaultProxy() method. If default proxy is not set or + it is set to version4 proxy, which does not support datagram + forwarding, throws SocksException. + + */ + public Socks5DatagramSocket() throws SocksException, + IOException{ + this(CProxy.defaultProxy,0,null); + } + /** + Construct Datagram socket for communication over SOCKS5 proxy + server. And binds it to the specified local port. + This constructor uses default proxy, the one set with + CProxy.setDefaultProxy() method. If default proxy is not set or + it is set to version4 proxy, which does not support datagram + forwarding, throws SocksException. + */ + public Socks5DatagramSocket(int port) throws SocksException, + IOException{ + this(CProxy.defaultProxy,port,null); + } + /** + Construct Datagram socket for communication over SOCKS5 proxy + server. And binds it to the specified local port and address. + This constructor uses default proxy, the one set with + CProxy.setDefaultProxy() method. If default proxy is not set or + it is set to version4 proxy, which does not support datagram + forwarding, throws SocksException. + */ + public Socks5DatagramSocket(int port,InetAddress ip) throws SocksException, + IOException{ + this(CProxy.defaultProxy,port,ip); + } + + /** + Constructs datagram socket for communication over specified proxy. + And binds it to the given local address and port. Address of null + and port of 0, signify any availabale port/address. + Might throw SocksException, if: + <ol> + <li> Given version of proxy does not support UDP_ASSOCIATE. + <li> CProxy can't be reached. + <li> Authorization fails. + <li> CProxy does not want to perform udp forwarding, for any reason. + </ol> + Might throw IOException if binding dtagram socket to given address/port + fails. + See java.net.DatagramSocket for more details. + */ + public Socks5DatagramSocket(CProxy p,int port,InetAddress ip) + throws SocksException, + IOException{ + super(port,ip); + if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); + if(!(p instanceof Socks5Proxy)) + throw new SocksException(-1,"Datagram Socket needs Proxy version 5"); + + if(p.chainProxy != null) + throw new SocksException(CProxy.SOCKS_JUST_ERROR, + "Datagram Sockets do not support proxy chaining."); + + proxy =(Socks5Proxy) p.copy(); + + ProxyMessage msg = proxy.udpAssociate(super.getLocalAddress(), + super.getLocalPort()); + relayIP = msg.ip; + if(relayIP.getHostAddress().equals("0.0.0.0")) relayIP = proxy.proxyIP; + relayPort = msg.port; + + encapsulation = proxy.udp_encapsulation; + + //debug("Datagram Socket:"+getLocalAddress()+":"+getLocalPort()+"\n"); + //debug("Socks5Datagram: "+relayIP+":"+relayPort+"\n"); + } + + /** + Used by UDPRelayServer. + */ + Socks5DatagramSocket(boolean server_mode,UDPEncapsulation encapsulation, + InetAddress relayIP,int relayPort) + throws IOException{ + super(); + this.server_mode = server_mode; + this.relayIP = relayIP; + this.relayPort = relayPort; + this.encapsulation = encapsulation; + this.proxy = null; + } + + /** + Sends the Datagram either through the proxy or directly depending + on current proxy settings and destination address. <BR> + + <B> NOTE: </B> DatagramPacket size should be at least 10 bytes less + than the systems limit. + + <P> + See documentation on java.net.DatagramSocket + for full details on how to use this method. + @param dp Datagram to send. + @throws IOException If error happens with I/O. + */ + public void send(DatagramPacket dp) throws IOException{ + //If the host should be accessed directly, send it as is. + if(!server_mode && proxy.isDirect(dp.getAddress())){ + super.send(dp); + //debug("Sending directly:"); + return; + } + + byte[] head = formHeader(dp.getAddress(),dp.getPort()); + byte[] buf = new byte[head.length + dp.getLength()]; + byte[] data = dp.getData(); + //Merge head and data + System.arraycopy(head,0,buf,0,head.length); + //System.arraycopy(data,dp.getOffset(),buf,head.length,dp.getLength()); + System.arraycopy(data,0,buf,head.length,dp.getLength()); + + if(encapsulation != null) + buf = encapsulation.udpEncapsulate(buf,true); + + super.send(new DatagramPacket(buf,buf.length,relayIP,relayPort)); + } + /** + This method allows to send datagram packets with address type DOMAINNAME. + SOCKS5 allows to specify host as names rather than ip addresses.Using + this method one can send udp datagrams through the proxy, without having + to know the ip address of the destination host. + <p> + If proxy specified for that socket has an option resolveAddrLocally set + to true host will be resolved, and the datagram will be send with address + type IPV4, if resolve fails, UnknownHostException is thrown. + @param dp Datagram to send, it should contain valid port and data + @param host Host name to which datagram should be send. + @throws IOException If error happens with I/O, or the host can't be + resolved when proxy settings say that hosts should be resolved locally. + @see Socks5Proxy#resolveAddrLocally(boolean) + */ + public void send(DatagramPacket dp, String host) throws IOException{ + if(proxy.isDirect(host)){ + dp.setAddress(InetAddress.getByName(host)); + super.send(dp); + return; + } + + if(((Socks5Proxy)proxy).resolveAddrLocally){ + dp.setAddress(InetAddress.getByName(host)); + } + + byte[] head = formHeader(host,dp.getPort()); + byte[] buf = new byte[head.length + dp.getLength()]; + byte[] data = dp.getData(); + //Merge head and data + System.arraycopy(head,0,buf,0,head.length); + //System.arraycopy(data,dp.getOffset(),buf,head.length,dp.getLength()); + System.arraycopy(data,0,buf,head.length,dp.getLength()); + + if(encapsulation != null) + buf = encapsulation.udpEncapsulate(buf,true); + + super.send(new DatagramPacket(buf,buf.length,relayIP,relayPort)); + } + + /** + * Receives udp packet. If packet have arrived from the proxy relay server, + * it is processed and address and port of the packet are set to the + * address and port of sending host.<BR> + * If the packet arrived from anywhere else it is not changed.<br> + * <B> NOTE: </B> DatagramPacket size should be at least 10 bytes bigger + * than the largest packet you expect (this is for IPV4 addresses). + * For hostnames and IPV6 it is even more. + @param dp Datagram in which all relevent information will be copied. + */ + public void receive(DatagramPacket dp) throws IOException{ + super.receive(dp); + + if(server_mode){ + //Drop all datagrams not from relayIP/relayPort + int init_length = dp.getLength(); + int initTimeout = getSoTimeout(); + long startTime = System.currentTimeMillis(); + + while(!relayIP.equals(dp.getAddress()) || + relayPort != dp.getPort()){ + + //Restore datagram size + dp.setLength(init_length); + + //If there is a non-infinit timeout on this socket + //Make sure that it happens no matter how often unexpected + //packets arrive. + if(initTimeout != 0){ + int newTimeout = initTimeout - (int)(System.currentTimeMillis() - + startTime); + if(newTimeout <= 0) throw new InterruptedIOException( + "In Socks5DatagramSocket->receive()"); + setSoTimeout(newTimeout); + } + + super.receive(dp); + } + + //Restore timeout settings + if(initTimeout != 0) setSoTimeout(initTimeout); + + }else if(!relayIP.equals(dp.getAddress()) || + relayPort != dp.getPort()) + return; // Recieved direct packet + //If the datagram is not from the relay server, return it it as is. + + byte[] data; + data = dp.getData(); + + if(encapsulation != null) + data = encapsulation.udpEncapsulate(data,false); + + int offset = 0; //Java 1.1 + //int offset = dp.getOffset(); //Java 1.2 + + ByteArrayInputStream bIn = new ByteArrayInputStream(data,offset, + dp.getLength()); + + + ProxyMessage msg = new Socks5Message(bIn); + dp.setPort(msg.port); + dp.setAddress(msg.getInetAddress()); + + //what wasn't read by the Message is the data + int data_length = bIn.available(); + //Shift data to the left + System.arraycopy(data,offset+dp.getLength()-data_length, + data,offset,data_length); + + + dp.setLength(data_length); + } + + /** + * Returns port assigned by the proxy, to which datagrams are relayed. + * It is not the same port to which other party should send datagrams. + @return Port assigned by socks server to which datagrams are send + for association. + */ + public int getLocalPort(){ + if(server_mode) return super.getLocalPort(); + return relayPort; + } + /** + * Address assigned by the proxy, to which datagrams are send for relay. + * It is not necesseraly the same address, to which other party should send + * datagrams. + @return Address to which datagrams are send for association. + */ + public InetAddress getLocalAddress(){ + if(server_mode) return super.getLocalAddress(); + return relayIP; + } + + /** + * Closes datagram socket, and proxy connection. + */ + public void close(){ + if(!server_mode) proxy.endSession(); + super.close(); + } + + /** + This method checks wether proxy still runs udp forwarding service + for this socket. + <p> + This methods checks wether the primary connection to proxy server + is active. If it is, chances are that proxy continues to forward + datagrams being send from this socket. If it was closed, most likely + datagrams are no longer being forwarded by the server. + <p> + CProxy might decide to stop forwarding datagrams, in which case it + should close primary connection. This method allows to check, wether + this have been done. + <p> + You can specify timeout for which we should be checking EOF condition + on the primary connection. Timeout is in milliseconds. Specifying 0 as + timeout implies infinity, in which case method will block, until + connection to proxy is closed or an error happens, and then return false. + <p> + One possible scenario is to call isProxyactive(0) in separate thread, + and once it returned notify other threads about this event. + + @param timeout For how long this method should block, before returning. + @return true if connection to proxy is active, false if eof or error + condition have been encountered on the connection. + */ + public boolean isProxyAlive(int timeout){ + if(server_mode) return false; + if(proxy != null){ + try{ + proxy.proxySocket.setSoTimeout(timeout); + + int eof = proxy.in.read(); + if(eof < 0) return false; // EOF encountered. + else return true; // This really should not happen + + }catch(InterruptedIOException iioe){ + return true; // read timed out. + }catch(IOException ioe){ + return false; + } + } + return false; + } + +//PRIVATE METHODS +////////////////// + + + private byte[] formHeader(InetAddress ip, int port){ + Socks5Message request = new Socks5Message(0,ip,port); + request.data[0] = 0; + return request.data; + } + + + private byte[] formHeader(String host,int port){ + Socks5Message request = new Socks5Message(0,host,port); + request.data[0] = 0; + return request.data; + } + + +/*====================================================================== + +//Mainly Test functions +////////////////////// + + private String bytes2String(byte[] b){ + String s=""; + char[] hex_digit = { '0','1','2','3','4','5','6','7','8','9', + 'A','B','C','D','E','F'}; + for(int i=0;i<b.length;++i){ + int i1 = (b[i] & 0xF0) >> 4; + int i2 = b[i] & 0xF; + s+=hex_digit[i1]; + s+=hex_digit[i2]; + s+=" "; + } + return s; + } + private static final void debug(String s){ + if(DEBUG) + System.out.print(s); + } + + private static final boolean DEBUG = true; + + + public static void usage(){ + System.err.print( + "Usage: java Socks.SocksDatagramSocket host port [socksHost socksPort]\n"); + } + + static final int defaultProxyPort = 1080; //Default Port + static final String defaultProxyHost = "www-proxy"; //Default proxy + + public static void main(String args[]){ + int port; + String host; + int proxyPort; + String proxyHost; + InetAddress ip; + + if(args.length > 1 && args.length < 5){ + try{ + + host = args[0]; + port = Integer.parseInt(args[1]); + + proxyPort =(args.length > 3)? Integer.parseInt(args[3]) + : defaultProxyPort; + + host = args[0]; + ip = InetAddress.getByName(host); + + proxyHost =(args.length > 2)? args[2] + : defaultProxyHost; + + CProxy.setDefaultProxy(proxyHost,proxyPort); + CProxy p = CProxy.getDefaultProxy(); + p.addDirect("lux"); + + + DatagramSocket ds = new Socks5DatagramSocket(); + + + BufferedReader in = new BufferedReader( + new InputStreamReader(System.in)); + String s; + + System.out.print("Enter line:"); + s = in.readLine(); + + while(s != null){ + byte[] data = (s+"\r\n").getBytes(); + DatagramPacket dp = new DatagramPacket(data,0,data.length, + ip,port); + System.out.println("Sending to: "+ip+":"+port); + ds.send(dp); + dp = new DatagramPacket(new byte[1024],1024); + + System.out.println("Trying to recieve on port:"+ + ds.getLocalPort()); + ds.receive(dp); + System.out.print("Recieved:\n"+ + "From:"+dp.getAddress()+":"+dp.getPort()+ + "\n\n"+ + new String(dp.getData(),dp.getOffset(),dp.getLength())+"\n" + ); + System.out.print("Enter line:"); + s = in.readLine(); + + } + ds.close(); + System.exit(1); + + }catch(SocksException s_ex){ + System.err.println("SocksException:"+s_ex); + s_ex.printStackTrace(); + System.exit(1); + }catch(IOException io_ex){ + io_ex.printStackTrace(); + System.exit(1); + }catch(NumberFormatException num_ex){ + usage(); + num_ex.printStackTrace(); + System.exit(1); + } + + }else{ + usage(); + } + } +*/ + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/Socks5Message.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,291 @@ +package net.sourceforge.jsocks; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.DataInputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + SOCKS5 request/response message. +*/ + +public class Socks5Message extends ProxyMessage{ + /** Address type of given message*/ + public int addrType; + + byte[] data; + + /** + Server error response. + @param cmd Error code. + */ + public Socks5Message(int cmd){ + super(cmd,null,0); + data = new byte[3]; + data[0] = SOCKS_VERSION; //Version. + data[1] = (byte)cmd; //Reply code for some kind of failure. + data[2] = 0; //Reserved byte. + } + + /** + Construct client request or server response. + @param cmd - Request/Response code. + @param ip - IP field. + @paarm port - port field. + */ + public Socks5Message(int cmd,InetAddress ip,int port){ + super(cmd,ip,port); + this.host = ip==null?"0.0.0.0":ip.getHostName(); + this.version = SOCKS_VERSION; + + byte[] addr; + + if(ip == null){ + addr = new byte[4]; + addr[0]=addr[1]=addr[2]=addr[3]=0; + }else + addr = ip.getAddress(); + + addrType = addr.length == 4 ? SOCKS_ATYP_IPV4 + : SOCKS_ATYP_IPV6; + + data = new byte[6+addr.length]; + data[0] = (byte) SOCKS_VERSION; //Version + data[1] = (byte) command; //Command + data[2] = (byte) 0; //Reserved byte + data[3] = (byte) addrType; //Address type + + //Put Address + System.arraycopy(addr,0,data,4,addr.length); + //Put port + data[data.length-2] = (byte)(port>>8); + data[data.length-1] = (byte)(port); + } + + + /** + Construct client request or server response. + @param cmd - Request/Response code. + @param hostName - IP field as hostName, uses ADDR_TYPE of HOSTNAME. + @paarm port - port field. + */ + public Socks5Message(int cmd,String hostName,int port){ + super(cmd,null,port); + this.host = hostName; + this.version = SOCKS_VERSION; + + //System.out.println("Doing ATYP_DOMAINNAME"); + + addrType = SOCKS_ATYP_DOMAINNAME; + byte addr[] = hostName.getBytes(); + + data =new byte[7+addr.length]; + data[0] = (byte) SOCKS_VERSION; //Version + data[1] = (byte) command; //Command + data[2] = (byte) 0; //Reserved byte + data[3] = (byte) SOCKS_ATYP_DOMAINNAME; //Address type + data[4] = (byte) addr.length; //Length of the address + + //Put Address + System.arraycopy(addr,0,data,5,addr.length); + //Put port + data[data.length-2] = (byte)(port >>8); + data[data.length-1] = (byte)(port); + } + + /** + Initialises Message from the stream. Reads server response from + given stream. + @param in Input stream to read response from. + @throws SocksException If server response code is not SOCKS_SUCCESS(0), or + if any error with protocol occurs. + @throws IOException If any error happens with I/O. + */ + public Socks5Message(InputStream in) throws SocksException, + IOException{ + this(in,true); + } + + /** + Initialises Message from the stream. Reads server response or client + request from given stream. + + @param in Input stream to read response from. + @param clinetMode If true read server response, else read client request. + @throws SocksException If server response code is not SOCKS_SUCCESS(0) and + reading in client mode, or if any error with protocol occurs. + @throws IOException If any error happens with I/O. + */ + public Socks5Message(InputStream in,boolean clientMode)throws SocksException, + IOException{ + read(in,clientMode); + } + + + /** + Initialises Message from the stream. Reads server response from + given stream. + @param in Input stream to read response from. + @throws SocksException If server response code is not SOCKS_SUCCESS(0), or + if any error with protocol occurs. + @throws IOException If any error happens with I/O. + */ + public void read(InputStream in) throws SocksException, + IOException{ + read(in,true); + } + + + /** + Initialises Message from the stream. Reads server response or client + request from given stream. + + @param in Input stream to read response from. + @param clinetMode If true read server response, else read client request. + @throws SocksException If server response code is not SOCKS_SUCCESS(0) and + reading in client mode, or if any error with protocol occurs. + @throws IOException If any error happens with I/O. + */ + public void read(InputStream in,boolean clientMode) throws SocksException, + IOException{ + data = null; + ip = null; + + DataInputStream di = new DataInputStream(in); + + version = di.readUnsignedByte(); + command = di.readUnsignedByte(); + if(clientMode && command != 0) + throw new SocksException(command); + + int reserved = di.readUnsignedByte(); + addrType = di.readUnsignedByte(); + + byte addr[]; + + switch(addrType){ + case SOCKS_ATYP_IPV4: + addr = new byte[4]; + di.readFully(addr); + host = bytes2IPV4(addr,0); + break; + case SOCKS_ATYP_IPV6: + addr = new byte[SOCKS_IPV6_LENGTH];//I believe it is 16 bytes,huge! + di.readFully(addr); + host = bytes2IPV6(addr,0); + break; + case SOCKS_ATYP_DOMAINNAME: + //System.out.println("Reading ATYP_DOMAINNAME"); + addr = new byte[di.readUnsignedByte()];//Next byte shows the length + di.readFully(addr); + host = new String(addr); + break; + default: + throw(new SocksException(CProxy.SOCKS_JUST_ERROR)); + } + + port = di.readUnsignedShort(); + + if(addrType != SOCKS_ATYP_DOMAINNAME && doResolveIP){ + try{ + ip = InetAddress.getByName(host); + }catch(UnknownHostException uh_ex){ + } + } + } + + /** + Writes the message to the stream. + @param out Output stream to which message should be written. + */ + public void write(OutputStream out)throws SocksException, + IOException{ + if(data == null){ + Socks5Message msg; + + if(addrType == SOCKS_ATYP_DOMAINNAME) + msg = new Socks5Message(command,host,port); + else{ + if(ip == null){ + try{ + ip = InetAddress.getByName(host); + }catch(UnknownHostException uh_ex){ + throw new SocksException(CProxy.SOCKS_JUST_ERROR); + } + } + msg = new Socks5Message(command,ip,port); + } + data = msg.data; + } + out.write(data); + } + + /** + Returns IP field of the message as IP, if the message was created + with ATYP of HOSTNAME, it will attempt to resolve the hostname, + which might fail. + @throws UnknownHostException if host can't be resolved. + */ + public InetAddress getInetAddress() throws UnknownHostException{ + if(ip!=null) return ip; + + return (ip=InetAddress.getByName(host)); + } + + /** + Returns string representation of the message. + */ + public String toString(){ + String s= + "Socks5Message:"+"\n"+ + "VN "+version+"\n"+ + "CMD "+command+"\n"+ + "ATYP "+addrType+"\n"+ + "ADDR "+host+"\n"+ + "PORT "+port+"\n"; + return s; + } + + + /** + *Wether to resolve hostIP returned from SOCKS server + *that is wether to create InetAddress object from the + *hostName string + */ + static public boolean resolveIP(){ return doResolveIP;} + + /** + *Wether to resolve hostIP returned from SOCKS server + *that is wether to create InetAddress object from the + *hostName string + *@param doResolve Wether to resolve hostIP from SOCKS server. + *@return Previous value. + */ + static public boolean resolveIP(boolean doResolve){ + boolean old = doResolveIP; + doResolveIP = doResolve; + return old; + } + + /* + private static final void debug(String s){ + if(DEBUG) + System.out.print(s); + } + private static final boolean DEBUG = false; + */ + + //SOCKS5 constants + public static final int SOCKS_VERSION =5; + + public static final int SOCKS_ATYP_IPV4 =0x1; //Where is 2?? + public static final int SOCKS_ATYP_DOMAINNAME =0x3; //!!!!rfc1928 + public static final int SOCKS_ATYP_IPV6 =0x4; + + public static final int SOCKS_IPV6_LENGTH =16; + + static boolean doResolveIP = true; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/Socks5Proxy.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,248 @@ +package net.sourceforge.jsocks; +import java.net.*; +import java.io.*; +import java.util.Hashtable; +import java.util.Enumeration; + +/** + SOCKS5 CProxy. +*/ + +public class Socks5Proxy extends CProxy implements Cloneable{ + +//Data members + private Hashtable authMethods = new Hashtable(); + private int selectedMethod; + + boolean resolveAddrLocally = true; + UDPEncapsulation udp_encapsulation=null; + + +//Public Constructors +//==================== + + /** + Creates SOCKS5 proxy. + @param p CProxy to use to connect to this proxy, allows proxy chaining. + @param proxyHost Host on which a CProxy server runs. + @param proxyPort Port on which a CProxy server listens for connections. + @throws UnknownHostException If proxyHost can't be resolved. + */ + public Socks5Proxy(CProxy p,String proxyHost,int proxyPort) + throws UnknownHostException{ + super(p,proxyHost,proxyPort); + version = 5; + setAuthenticationMethod(0,new AuthenticationNone()); + } + + /** + Creates SOCKS5 proxy. + @param proxyHost Host on which a CProxy server runs. + @param proxyPort Port on which a CProxy server listens for connections. + @throws UnknownHostException If proxyHost can't be resolved. + */ + public Socks5Proxy(String proxyHost,int proxyPort) + throws UnknownHostException{ + this(null,proxyHost,proxyPort); + } + + + /** + Creates SOCKS5 proxy. + @param p CProxy to use to connect to this proxy, allows proxy chaining. + @param proxyIP Host on which a CProxy server runs. + @param proxyPort Port on which a CProxy server listens for connections. + */ + public Socks5Proxy(CProxy p,InetAddress proxyIP,int proxyPort){ + super(p,proxyIP,proxyPort); + version = 5; + setAuthenticationMethod(0,new AuthenticationNone()); + } + + /** + Creates SOCKS5 proxy. + @param proxyIP Host on which a CProxy server runs. + @param proxyPort Port on which a CProxy server listens for connections. + */ + public Socks5Proxy(InetAddress proxyIP,int proxyPort){ + this(null,proxyIP,proxyPort); + } + +//Public instance methods +//======================== + + + /** + * Wether to resolve address locally or to let proxy do so. + <p> + SOCKS5 protocol allows to send host names rather then IPs in the + requests, this option controls wether the hostnames should be send + to the proxy server as names, or should they be resolved locally. + @param doResolve Wether to perform resolution locally. + @return Previous settings. + */ + public boolean resolveAddrLocally(boolean doResolve){ + boolean old = resolveAddrLocally; + resolveAddrLocally = doResolve; + return old; + } + /** + Get current setting on how the addresses should be handled. + @return Current setting for address resolution. + @see Socks5Proxy#resolveAddrLocally(boolean doResolve) + */ + public boolean resolveAddrLocally(){ + return resolveAddrLocally; + } + + /** + Adds another authentication method. + @param methodId Authentication method id, see rfc1928 + @param method Implementation of Authentication + @see Authentication + */ + public boolean setAuthenticationMethod(int methodId, + Authentication method){ + if(methodId<0 || methodId > 255) + return false; + if(method == null){ + //Want to remove a particular method + return (authMethods.remove(new Integer(methodId)) != null); + }else{//Add the method, or rewrite old one + authMethods.put(new Integer(methodId),method); + } + return true; + } + + /** + Get authentication method, which corresponds to given method id + @param methodId Authentication method id. + @return Implementation for given method or null, if one was not set. + */ + public Authentication getAuthenticationMethod(int methodId){ + Object method = authMethods.get(new Integer(methodId)); + if(method == null) return null; + return (Authentication)method; + } + + /** + Creates a clone of this CProxy. + */ + public Object clone(){ + Socks5Proxy newProxy = new Socks5Proxy(proxyIP,proxyPort); + newProxy.authMethods = (Hashtable) this.authMethods.clone(); + newProxy.directHosts = (InetRange)directHosts.clone(); + newProxy.resolveAddrLocally = resolveAddrLocally; + newProxy.chainProxy = chainProxy; + return newProxy; + } + +//Public Static(Class) Methods +//============================== + + +//Protected Methods +//================= + + protected CProxy copy(){ + Socks5Proxy copy = new Socks5Proxy(proxyIP,proxyPort); + copy.authMethods = this.authMethods; //same Hash, no copy + copy.directHosts = this.directHosts; + copy.chainProxy = this.chainProxy; + copy.resolveAddrLocally = this.resolveAddrLocally; + return copy; + } + /** + * + * + */ + protected void startSession()throws SocksException{ + super.startSession(); + Authentication auth; + Socket ps = proxySocket; //The name is too long + + try{ + + byte nMethods = (byte) authMethods.size(); //Number of methods + + byte[] buf = new byte[2+nMethods]; //2 is for VER,NMETHODS + buf[0] = (byte) version; + buf[1] = nMethods; //Number of methods + int i=2; + + Enumeration ids = authMethods.keys(); + while(ids.hasMoreElements()) + buf[i++] = (byte)((Integer)ids.nextElement()).intValue(); + + out.write(buf); + out.flush(); + + int versionNumber = in.read(); + selectedMethod = in.read(); + + if(versionNumber < 0 || selectedMethod < 0){ + //EOF condition was reached + endSession(); + throw(new SocksException(SOCKS_PROXY_IO_ERROR, + "Connection to proxy lost.")); + } + if(versionNumber < version){ + //What should we do?? + } + if(selectedMethod == 0xFF){ //No method selected + ps.close(); + throw ( new SocksException(SOCKS_AUTH_NOT_SUPPORTED)); + } + + auth = getAuthenticationMethod(selectedMethod); + if(auth == null){ + //This shouldn't happen, unless method was removed by other + //thread, or the server stuffed up + throw(new SocksException(SOCKS_JUST_ERROR, + "Speciefied Authentication not found!")); + } + Object[] in_out = auth.doSocksAuthentication(selectedMethod,ps); + if(in_out == null){ + //Authentication failed by some reason + throw(new SocksException(SOCKS_AUTH_FAILURE)); + } + //Most authentication methods are expected to return + //simply the input/output streams associated with + //the socket. However if the auth. method requires + //some kind of encryption/decryption being done on the + //connection it should provide classes to handle I/O. + + in = (InputStream) in_out[0]; + out = (OutputStream) in_out[1]; + if(in_out.length > 2) + udp_encapsulation = (UDPEncapsulation) in_out[2]; + + }catch(SocksException s_ex){ + throw s_ex; + }catch(UnknownHostException uh_ex){ + throw(new SocksException(SOCKS_PROXY_NO_CONNECT)); + }catch(SocketException so_ex){ + throw(new SocksException(SOCKS_PROXY_NO_CONNECT)); + }catch(IOException io_ex){ + //System.err.println(io_ex); + throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex)); + } + } + + protected ProxyMessage formMessage(int cmd,InetAddress ip,int port){ + return new Socks5Message(cmd,ip,port); + } + protected ProxyMessage formMessage(int cmd,String host,int port) + throws UnknownHostException{ + if(resolveAddrLocally) + return formMessage(cmd,InetAddress.getByName(host),port); + else + return new Socks5Message(cmd,host,port); + } + protected ProxyMessage formMessage(InputStream in) + throws SocksException, + IOException{ + return new Socks5Message(in); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/SocksException.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,78 @@ +package net.sourceforge.jsocks; + +/** + Exception thrown by various socks classes to indicate errors + with protocol or unsuccessfull server responses. +*/ +public class SocksException extends java.io.IOException{ + /** + Construct a SocksException with given errorcode. + <p> + Tries to look up message which corresponds to this error code. + @param errCode Error code for this exception. + */ + public SocksException(int errCode){ + this.errCode = errCode; + if((errCode >> 16) == 0){ + //Server reply error message + errString = errCode <= serverReplyMessage.length ? + serverReplyMessage[errCode] : + UNASSIGNED_ERROR_MESSAGE; + }else{ + //Local error + errCode = (errCode >> 16) -1; + errString = errCode <= localErrorMessage.length ? + localErrorMessage[errCode] : + UNASSIGNED_ERROR_MESSAGE; + } + } + /** + Constructs a SocksException with given error code and message. + @param errCode Error code. + @param errString Error Message. + */ + public SocksException(int errCode,String errString){ + this.errCode = errCode; + this.errString = errString; + } + /** + Get the error code associated with this exception. + @return Error code associated with this exception. + */ + public int getErrorCode(){ + return errCode; + } + /** + Get human readable representation of this exception. + @return String represntation of this exception. + */ + public String toString(){ + return errString; + } + + static final String UNASSIGNED_ERROR_MESSAGE = + "Unknown error message"; + static final String serverReplyMessage[] = { + "Succeeded", + "General SOCKS server failure", + "Connection not allowed by ruleset", + "Network unreachable", + "Host unreachable", + "Connection refused", + "TTL expired", + "Command not supported", + "Address type not supported" }; + + static final String localErrorMessage[] ={ + "SOCKS server not specified", + "Unable to contact SOCKS server", + "IO error", + "None of Authentication methods are supported", + "Authentication failed", + "General SOCKS fault" }; + + String errString; + public int errCode; + +}//End of SocksException class +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/SocksServerSocket.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,207 @@ +package net.sourceforge.jsocks; + +import java.net.*; +import java.io.*; + +/** + SocksServerSocket allows to accept connections from one particular + host through the SOCKS4 or SOCKS5 proxy. +*/ +public class SocksServerSocket extends ServerSocket{ + //Data members + protected CProxy proxy; + protected String localHost; + protected InetAddress localIP; + protected int localPort; + + boolean doing_direct = false; + InetAddress remoteAddr; + + /** + * Creates ServerSocket capable of accepting one connection + * through the firewall, uses default CProxy. + *@param host Host from which the connection should be recieved. + *@param port Port number of the primary connection. + */ + public SocksServerSocket(String host,int port) + throws SocksException,UnknownHostException,IOException{ + this(CProxy.defaultProxy,host,port); + } + /** + *Creates ServerSocket capable of accepting one connection + *through the firewall, uses given proxy. + *@param p CProxy object to use. + *@param host Host from which the connection should be recieved. + *@param port Port number of the primary connection. + */ + public SocksServerSocket(CProxy p,String host,int port) + throws SocksException,UnknownHostException,IOException{ + + + super(0); + if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); + //proxy=p; + proxy = p.copy(); + if(proxy.isDirect(host)){ + remoteAddr = InetAddress.getByName(host); + proxy = null; + doDirect(); + }else{ + processReply(proxy.bind(host,port)); + } + } + + /** + * Creates ServerSocket capable of accepting one connection + * through the firewall, uses default CProxy. + *@param ip Host from which the connection should be recieved. + *@param port Port number of the primary connection. + */ + public SocksServerSocket(InetAddress ip, int port) throws SocksException, + IOException{ + this(CProxy.defaultProxy,ip,port); + } + + /** + *Creates ServerSocket capable of accepting one connection + *through the firewall, uses given proxy. + *@param p CProxy object to use. + *@param ip Host from which the connection should be recieved. + *@param port Port number of the primary connection. + */ + public SocksServerSocket(CProxy p,InetAddress ip, int port) + throws SocksException,IOException{ + super(0); + + if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); + this.proxy = p.copy(); + + if(proxy.isDirect(ip)){ + remoteAddr = ip; + doDirect(); + }else{ + processReply(proxy.bind(ip,port)); + } + } + + + /** + * Accepts the incoming connection. + */ + public Socket accept() throws IOException{ + Socket s; + + if(!doing_direct){ + if(proxy == null) return null; + + ProxyMessage msg = proxy.accept(); + s = msg.ip == null? new SocksSocket(msg.host,msg.port,proxy) + : new SocksSocket(msg.ip,msg.port,proxy); + //Set timeout back to 0 + proxy.proxySocket.setSoTimeout(0); + }else{ //Direct Connection + + //Mimic the proxy behaviour, + //only accept connections from the speciefed host. + while(true){ + s = super.accept(); + if(s.getInetAddress().equals(remoteAddr)){ + //got the connection from the right host + //Close listenning socket. + break; + }else + s.close(); //Drop all connections from other hosts + } + + } + proxy = null; + //Return accepted socket + return s; + } + + /** + * Closes the connection to proxy if socket have not been accepted, if + * the direct connection is used, closes direct ServerSocket. If the + * client socket have been allready accepted, does nothing. + */ + public void close() throws IOException{ + super.close(); + if(proxy != null) proxy.endSession(); + proxy = null; + } + + /** + Get the name of the host proxy is using to listen for incoming + connection. + <P> + Usefull when address is returned by proxy as the hostname. + @return the hostname of the address proxy is using to listen + for incoming connection. + */ + public String getHost(){ + return localHost; + } + + /** + * Get address assigned by proxy to listen for incomming + * connections, or the local machine address if doing direct + * connection. + */ + public InetAddress getInetAddress(){ + if(localIP == null){ + try{ + localIP = InetAddress.getByName(localHost); + }catch(UnknownHostException e){ + return null; + } + } + return localIP; + } + + /** + * Get port assigned by proxy to listen for incoming connections, or + the port chosen by local system, if accepting directly. + */ + public int getLocalPort(){ + return localPort; + } + + /** + Set Timeout. + + @param timeout Amount of time in milliseconds, accept should wait for + incoming connection before failing with exception. + Zero timeout implies infinity. + */ + public void setSoTimeout(int timeout) throws SocketException{ + super.setSoTimeout(timeout); + if(!doing_direct) proxy.proxySocket.setSoTimeout(timeout); + } + + +//Private Methods +////////////////// + + private void processReply(ProxyMessage reply)throws SocksException{ + localPort = reply.port; + /* + * If the server have assigned same host as it was contacted on + * it might return an address of all zeros + */ + if(reply.host.equals("0.0.0.0")){ + localIP = proxy.proxyIP; + localHost = localIP.getHostName(); + }else{ + localHost = reply.host; + localIP = reply.ip; + } + } + + private void doDirect(){ + doing_direct = true; + localPort = super.getLocalPort(); + localIP = super.getInetAddress(); + localHost = localIP.getHostName(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/SocksSocket.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,332 @@ +package net.sourceforge.jsocks; + +import java.net.*; +import java.io.*; + +/** + * SocksSocket tryies to look very similar to normal Socket, + * while allowing connections through the SOCKS4 or 5 proxy. + * To use this class you will have to identify proxy you need + * to use, CProxy class allows you to set default proxy, which + * will be used by all Socks aware sockets. You can also create + * either Socks4Proxy or Socks5Proxy, and use them by passing to the + * appropriate constructors. + * <P> + * Using Socks package can be as easy as that: + * + * <pre><tt> + * + * import Socks.*; + * .... + * + * try{ + * //Specify SOCKS5 proxy + * CProxy.setDefaultProxy("socks-proxy",1080); + * + * //OR you still use SOCKS4 + * //Code below uses SOCKS4 proxy + * //CProxy.setDefaultProxy("socks-proxy",1080,userName); + * + * Socket s = SocksSocket("some.host.of.mine",13); + * readTimeFromSock(s); + * }catch(SocksException sock_ex){ + * //Usually it will turn in more or less meaningfull message + * System.err.println("SocksException:"+sock_ex); + * } + * + * </tt></pre> + *<P> + * However if the need exist for more control, like resolving addresses + * remotely, or using some non-trivial authentication schemes, it can be done. + */ + +public class SocksSocket extends Socket{ + //Data members + protected CProxy proxy; + protected String localHost, remoteHost; + protected InetAddress localIP, remoteIP; + protected int localPort,remotePort; + + private Socket directSock = null; + + /** + * Tryies to connect to given host and port + * using default proxy. If no default proxy speciefied + * it throws SocksException with error code SOCKS_NO_PROXY. + @param host Machine to connect to. + @param port Port to which to connect. + * @see SocksSocket#SocksSocket(CProxy,String,int) + * @see Socks5Proxy#resolveAddrLocally + */ + public SocksSocket(String host,int port) + throws SocksException,UnknownHostException{ + this(CProxy.defaultProxy,host,port); + } + /** + * Connects to host port using given proxy server. + @param p CProxy to use. + @param host Machine to connect to. + @param port Port to which to connect. + @throws UnknownHostException + If one of the following happens: + <ol> + + <li> CProxy settings say that address should be resolved locally, but + this fails. + <li> CProxy settings say that the host should be contacted directly but + host name can't be resolved. + </ol> + @throws SocksException + If one of the following happens: + <ul> + <li> CProxy is is null. + <li> CProxy settings say that the host should be contacted directly but + this fails. + <li> Socks Server can't be contacted. + <li> Authentication fails. + <li> Connection is not allowed by the SOCKS proxy. + <li> SOCKS proxy can't establish the connection. + <li> Any IO error occured. + <li> Any protocol error occured. + </ul> + @throws IOexception if anything is wrong with I/O. + @see Socks5Proxy#resolveAddrLocally + */ + public SocksSocket(CProxy p,String host,int port) + throws SocksException,UnknownHostException{ + + + if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); + //proxy=p; + proxy = p.copy(); + remoteHost = host; + remotePort = port; + if(proxy.isDirect(host)){ + remoteIP = InetAddress.getByName(host); + doDirect(); + } + else + processReply(proxy.connect(host,port)); + } + + + /** + * Tryies to connect to given ip and port + * using default proxy. If no default proxy speciefied + * it throws SocksException with error code SOCKS_NO_PROXY. + @param ip Machine to connect to. + @param port Port to which to connect. + * @see SocksSocket#SocksSocket(CProxy,String,int) + */ + public SocksSocket(InetAddress ip, int port) throws SocksException{ + this(CProxy.defaultProxy,ip,port); + } + + /** + Connects to given ip and port using given CProxy server. + @param p CProxy to use. + @param ip Machine to connect to. + @param port Port to which to connect. + + */ + public SocksSocket(CProxy p,InetAddress ip, int port) throws SocksException{ + if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); + this.proxy = p.copy(); + this.remoteIP = ip; + this.remotePort = port; + this.remoteHost = ip.getHostName(); + if(proxy.isDirect(remoteIP)) + doDirect(); + else + processReply(proxy.connect(ip,port)); + } + + + /** + * These 2 constructors are used by the SocksServerSocket. + * This socket simply overrides remoteHost, remotePort + */ + protected SocksSocket(String host,int port,CProxy proxy){ + this.remotePort = port; + this.proxy = proxy; + this.localIP = proxy.proxySocket.getLocalAddress(); + this.localPort = proxy.proxySocket.getLocalPort(); + this.remoteHost = host; + } + protected SocksSocket(InetAddress ip,int port,CProxy proxy){ + remoteIP = ip; + remotePort = port; + this.proxy = proxy; + this.localIP = proxy.proxySocket.getLocalAddress(); + this.localPort = proxy.proxySocket.getLocalPort(); + remoteHost = remoteIP.getHostName(); + } + + /** + * Same as Socket + */ + public void close() throws IOException{ + if(proxy!= null)proxy.endSession(); + proxy = null; + } + /** + * Same as Socket + */ + public InputStream getInputStream(){ + return proxy.in; + } + /** + * Same as Socket + */ + public OutputStream getOutputStream(){ + return proxy.out; + } + /** + * Same as Socket + */ + public int getPort(){ + return remotePort; + } + /** + * Returns remote host name, it is usefull in cases when addresses + * are resolved by proxy, and we can't create InetAddress object. + @return The name of the host this socket is connected to. + */ + public String getHost(){ + return remoteHost; + } + /** + * Get remote host as InetAddress object, might return null if + * addresses are resolved by proxy, and it is not possible to resolve + * it locally + @return Ip address of the host this socket is connected to, or null + if address was returned by the proxy as DOMAINNAME and can't be + resolved locally. + */ + public InetAddress getInetAddress(){ + if(remoteIP == null){ + try{ + remoteIP = InetAddress.getByName(remoteHost); + }catch(UnknownHostException e){ + return null; + } + } + return remoteIP; + } + + /** + * Get the port assigned by the proxy for the socket, not + * the port on locall machine as in Socket. + @return Port of the socket used on the proxy server. + */ + public int getLocalPort(){ + return localPort; + } + + /** + * Get address assigned by proxy to make a remote connection, + * it might be different from the host specified for the proxy. + * Can return null if socks server returned this address as hostname + * and it can't be resolved locally, use getLocalHost() then. + @return Address proxy is using to make a connection. + */ + public InetAddress getLocalAddress(){ + if(localIP == null){ + try{ + localIP = InetAddress.getByName(localHost); + }catch(UnknownHostException e){ + return null; + } + } + return localIP; + } + /** + Get name of the host, proxy has assigned to make a remote connection + for this socket. This method is usefull when proxy have returned + address as hostname, and we can't resolve it on this machine. + @return The name of the host proxy is using to make a connection. + */ + public String getLocalHost(){ + return localHost; + } + + /** + Same as socket. + */ + public void setSoLinger(boolean on,int val) throws SocketException{ + proxy.proxySocket.setSoLinger(on,val); + } + /** + Same as socket. + */ + public int getSoLinger(int timeout) throws SocketException{ + return proxy.proxySocket.getSoLinger(); + } + /** + Same as socket. + */ + public void setSoTimeout(int timeout) throws SocketException{ + proxy.proxySocket.setSoTimeout(timeout); + } + /** + Same as socket. + */ + public int getSoTimeout(int timeout) throws SocketException{ + return proxy.proxySocket.getSoTimeout(); + } + /** + Same as socket. + */ + public void setTcpNoDelay(boolean on) throws SocketException{ + proxy.proxySocket.setTcpNoDelay(on); + } + /** + Same as socket. + */ + public boolean getTcpNoDelay() throws SocketException{ + return proxy.proxySocket.getTcpNoDelay(); + } + + /** + Get string representation of the socket. + */ + public String toString(){ + if(directSock!=null) return "Direct connection:"+directSock; + return ("Proxy:"+proxy+";"+"addr:"+remoteHost+",port:"+remotePort + +",localport:"+localPort); + + } + +//Private Methods +////////////////// + + private void processReply(ProxyMessage reply)throws SocksException{ + localPort = reply.port; + /* + * If the server have assigned same host as it was contacted on + * it might return an address of all zeros + */ + if(reply.host.equals("0.0.0.0")){ + localIP = proxy.proxyIP; + localHost = localIP.getHostName(); + }else{ + localHost = reply.host; + localIP = reply.ip; + } + } + private void doDirect()throws SocksException{ + try{ + //System.out.println("IP:"+remoteIP+":"+remotePort); + directSock = new Socket(remoteIP,remotePort); + proxy.out = directSock.getOutputStream(); + proxy.in = directSock.getInputStream(); + proxy.proxySocket = directSock; + localIP = directSock.getLocalAddress(); + localPort = directSock.getLocalPort(); + }catch(IOException io_ex){ + throw new SocksException(CProxy.SOCKS_DIRECT_FAILED, + "Direct connect failed:"+io_ex); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/UDPEncapsulation.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,29 @@ +package net.sourceforge.jsocks; +/** + This interface provides for datagram encapsulation for SOCKSv5 protocol. + <p> + SOCKSv5 allows for datagrams to be encapsulated for purposes of integrity + and/or authenticity. How it should be done is aggreed during the + authentication stage, and is authentication dependent. This interface is + provided to allow this encapsulation. + @see Authentication +*/ +public interface UDPEncapsulation{ + + /** + This method should provide any authentication depended transformation + on datagrams being send from/to the client. + + @param data Datagram data (including any SOCKS related bytes), to be + encapsulated/decapsulated. + @param out Wether the data is being send out. If true method should + encapsulate/encrypt data, otherwise it should decapsulate/ + decrypt data. + @throw IOException if for some reason data can be transformed correctly. + @return Should return byte array containing data after transformation. + It is possible to return same array as input, if transformation + only involves bit mangling, and no additional data is being + added or removed. + */ + byte[] udpEncapsulate(byte[] data, boolean out) throws java.io.IOException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/UDPRelayServer.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,212 @@ +package net.sourceforge.jsocks; +import net.sourceforge.jsocks.server.*; +import java.net.*; +import java.io.*; + +/** + UDP Relay server, used by ProxyServer to perform udp forwarding. +*/ +class UDPRelayServer implements Runnable{ + + + DatagramSocket client_sock; + DatagramSocket remote_sock; + + Socket controlConnection; + + int relayPort; + InetAddress relayIP; + + Thread pipe_thread1,pipe_thread2; + Thread master_thread; + + ServerAuthenticator auth; + + long lastReadTime; + + static PrintStream log = null; + static CProxy proxy = null; + static int datagramSize = 0xFFFF;//64K, a bit more than max udp size + static int iddleTimeout = 180000;//3 minutes + + + /** + Constructs UDP relay server to communicate with client + on given ip and port. + @param clientIP Address of the client from whom datagrams + will be recieved and to whom they will be forwarded. + @param clientPort Clients port. + @param master_thread Thread which will be interrupted, when + UDP relay server stoppes for some reason. + @param controlConnection Socket which will be closed, before + interrupting the master thread, it is introduced due to a bug + in windows JVM which does not throw InterruptedIOException in + threads which block in I/O operation. + */ + public UDPRelayServer(InetAddress clientIP,int clientPort, + Thread master_thread, + Socket controlConnection, + ServerAuthenticator auth) + throws IOException{ + this.master_thread = master_thread; + this.controlConnection = controlConnection; + this.auth = auth; + + client_sock = new Socks5DatagramSocket(true,auth.getUdpEncapsulation(), + clientIP,clientPort); + relayPort = client_sock.getLocalPort(); + relayIP = client_sock.getLocalAddress(); + + if(relayIP.getHostAddress().equals("0.0.0.0")) + relayIP = InetAddress.getLocalHost(); + + if(proxy == null) + remote_sock = new DatagramSocket(); + else + remote_sock = new Socks5DatagramSocket(proxy,0,null); + } + + +//Public methods +///////////////// + + + /** + Sets the timeout for UDPRelay server.<br> + Zero timeout implies infinity.<br> + Default timeout is 3 minutes. + */ + + static public void setTimeout(int timeout){ + iddleTimeout = timeout; + } + + + /** + Sets the size of the datagrams used in the UDPRelayServer.<br> + Default size is 64K, a bit more than maximum possible size of the + datagram. + */ + static public void setDatagramSize(int size){ + datagramSize = size; + } + + /** + Port to which client should send datagram for association. + */ + public int getRelayPort(){ + return relayPort; + } + /** + IP address to which client should send datagrams for association. + */ + public InetAddress getRelayIP(){ + return relayIP; + } + + /** + Starts udp relay server. + Spawns two threads of execution and returns. + */ + public void start() throws IOException{ + remote_sock.setSoTimeout(iddleTimeout); + client_sock.setSoTimeout(iddleTimeout); + + log("Starting UDP relay server on "+relayIP+":"+relayPort); + log("Remote socket "+remote_sock.getLocalAddress()+":"+ + remote_sock.getLocalPort()); + + pipe_thread1 = new Thread(this,"pipe1"); + pipe_thread2 = new Thread(this,"pipe2"); + + lastReadTime = System.currentTimeMillis(); + + pipe_thread1.start(); + pipe_thread2.start(); + } + + /** + Stops Relay server. + <p> + Does not close control connection, does not interrupt master_thread. + */ + public synchronized void stop(){ + master_thread = null; + controlConnection = null; + abort(); + } + +//Runnable interface +//////////////////// + public void run(){ + try{ + if(Thread.currentThread().getName().equals("pipe1")) + pipe(remote_sock,client_sock,false); + else + pipe(client_sock,remote_sock,true); + }catch(IOException ioe){ + }finally{ + abort(); + log("UDP Pipe thread "+Thread.currentThread().getName()+" stopped."); + } + + } + +//Private methods +///////////////// + private synchronized void abort(){ + if(pipe_thread1 == null) return; + + log("Aborting UDP Relay Server"); + + remote_sock.close(); + client_sock.close(); + + if(controlConnection != null) + try{ controlConnection.close();} catch(IOException ioe){} + + if(master_thread!=null) master_thread.interrupt(); + + pipe_thread1.interrupt(); + pipe_thread2.interrupt(); + + pipe_thread1 = null; + } + + + static private void log(String s){ + if(log != null){ + log.println(s); + log.flush(); + } + } + + private void pipe(DatagramSocket from,DatagramSocket to,boolean out) + throws IOException{ + byte[] data = new byte[datagramSize]; + DatagramPacket dp = new DatagramPacket(data,data.length); + + while(true){ + try{ + from.receive(dp); + lastReadTime = System.currentTimeMillis(); + + if(auth.checkRequest(dp,out)) + to.send(dp); + + }catch(UnknownHostException uhe){ + log("Dropping datagram for unknown host"); + }catch(InterruptedIOException iioe){ + //log("Interrupted: "+iioe); + //If we were interrupted by other thread. + if(iddleTimeout == 0) return; + + //If last datagram was received, long time ago, return. + long timeSinceRead = System.currentTimeMillis() - lastReadTime; + if(timeSinceRead >= iddleTimeout -100) //-100 for adjustment + return; + } + dp.setLength(data.length); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/UserPasswordAuthentication.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,75 @@ +package net.sourceforge.jsocks; + +/** + SOCKS5 User Password authentication scheme. +*/ +public class UserPasswordAuthentication implements Authentication{ + + /**SOCKS ID for User/Password authentication method*/ + public final static int METHOD_ID = 2; + + String userName, password; + byte[] request; + + /** + Create an instance of UserPasswordAuthentication. + @param userName User Name to send to SOCKS server. + @param password Password to send to SOCKS server. + */ + public UserPasswordAuthentication(String userName,String password){ + this.userName = userName; + this.password = password; + formRequest(); + } + /** Get the user name. + @return User name. + */ + public String getUser(){ + return userName; + } + /** Get password + @return Password + */ + public String getPassword(){ + return password; + } + /** + Does User/Password authentication as defined in rfc1929. + @return An array containnig in, out streams, or null if authentication + fails. + */ + public Object[] doSocksAuthentication(int methodId, + java.net.Socket proxySocket) + throws java.io.IOException{ + + if(methodId != METHOD_ID) return null; + + java.io.InputStream in = proxySocket.getInputStream(); + java.io.OutputStream out = proxySocket.getOutputStream(); + + out.write(request); + int version = in.read(); + if(version < 0) return null; //Server closed connection + int status = in.read(); + if(status != 0) return null; //Server closed connection, or auth failed. + + return new Object[] {in,out}; + } + +//Private methods +////////////////// + +/** Convert UserName password in to binary form, ready to be send to server*/ + private void formRequest(){ + byte[] user_bytes = userName.getBytes(); + byte[] password_bytes = password.getBytes(); + + request = new byte[3+user_bytes.length+password_bytes.length]; + request[0] = (byte) 1; + request[1] = (byte) user_bytes.length; + System.arraycopy(user_bytes,0,request,2,user_bytes.length); + request[2+user_bytes.length] = (byte) password_bytes.length; + System.arraycopy(password_bytes,0, + request,3+user_bytes.length,password_bytes.length); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/server/Ident.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,158 @@ +package net.sourceforge.jsocks.server; +import net.sourceforge.jsocks.*; +import java.net.*; +import java.io.*; +import java.util.StringTokenizer; + +/** + Class Ident provides means to obtain user name of the owner of the socket + on remote machine, providing remote machine runs identd daemon. + <p> + To use it: + <tt><pre> + Socket s = ss.accept(); + Ident id = new Ident(s); + if(id.successful) goUseUser(id.userName); + else handleIdentError(id.errorCode,id.errorMessage) + </pre></tt> +*/ +public class Ident{ + + /** Error Message can be null.*/ + public String errorMessage; + /** Host type as returned by daemon, can be null, if error happened*/ + public String hostType; + /** User name as returned by the identd daemon, or null, if it failed*/ + public String userName; + + /** If this is true then userName and hostType contain valid values. + Else errorCode contain the error code, and errorMessage contains + the corresponding message. + */ + public boolean successful; + /** Error code*/ + public int errorCode; + /** Identd on port 113 can't be contacted*/ + public static final int ERR_NO_CONNECT = 1; + /** Connection timed out*/ + public static final int ERR_TIMEOUT = 2; + /** Identd daemon responded with ERROR, in this case errorMessage + contains the string explanation, as send by the daemon. + */ + public static final int ERR_PROTOCOL = 3; + /** + When parsing server response protocol error happened. + */ + public static final int ERR_PROTOCOL_INCORRECT = 4; + + + /** Maximum amount of time we should wait before dropping the + connection to identd server.Setting it to 0 implies infinit + timeout. + */ + public static final int connectionTimeout = 10000; + + + /** + Constructor tries to connect to Identd daemon on the host of the + given socket, and retrieve user name of the owner of given socket + connection on remote machine. After constructor returns public + fields are initialised to whatever the server returned. + <p> + If user name was successfully retrieved successful is set to true, + and userName and hostType are set to whatever server returned. If + however for some reason user name was not obtained, successful is set + to false and errorCode contains the code explaining the reason of + failure, and errorMessage contains human readable explanation. + <p> + Constructor may block, for a while. + @param s Socket whose ownership on remote end should be obtained. + */ + public Ident(Socket s ){ + Socket sock = null; + successful = false; //We are pessimistic + + try{ + sock = new Socket(s.getInetAddress(),113); + sock.setSoTimeout(connectionTimeout); + byte[] request = (""+s.getPort()+" , "+ + s.getLocalPort()+"\r\n").getBytes(); + + sock.getOutputStream().write(request); + + BufferedReader in = new BufferedReader( + new InputStreamReader(sock.getInputStream())); + + parseResponse(in.readLine()); + + }catch(InterruptedIOException iioe){ + errorCode = ERR_TIMEOUT; + errorMessage = "Connection to identd timed out."; + }catch(ConnectException ce){ + errorCode = ERR_NO_CONNECT; + errorMessage = "Connection to identd server failed."; + + }catch(IOException ioe){ + errorCode = ERR_NO_CONNECT; + errorMessage = ""+ioe; + }finally{ + try{ if(sock!=null) sock.close();}catch(IOException ioe){}; + } + } + + private void parseResponse(String response){ + if(response == null){ + errorCode = ERR_PROTOCOL_INCORRECT; + errorMessage = "Identd server closed connection."; + return; + } + + StringTokenizer st = new StringTokenizer(response,":"); + if(st.countTokens() < 3){ + errorCode = ERR_PROTOCOL_INCORRECT; + errorMessage = "Can't parse server response."; + return; + } + + st.nextToken(); //Discard first token, it's basically what we have send + String command = st.nextToken().trim().toUpperCase(); + + if(command.equals("USERID") && st.countTokens() >= 2){ + successful = true; + hostType = st.nextToken().trim(); + userName = st.nextToken("").substring(1);//Get all that is left + }else if(command.equals("ERROR")){ + errorCode = ERR_PROTOCOL; + errorMessage = st.nextToken(); + }else{ + errorCode = ERR_PROTOCOL_INCORRECT; + System.out.println("Opa!"); + errorMessage = "Can't parse server response."; + } + + + } + +/////////////////////////////////////////////// +//USED for Testing +/* + public static void main(String[] args) throws IOException{ + + Socket s = null; + s = new Socket("gp101-16", 1391); + + Ident id = new Ident(s); + if(id.successful){ + System.out.println("User: "+id.userName); + System.out.println("HostType: "+id.hostType); + }else{ + System.out.println("ErrorCode: "+id.errorCode); + System.out.println("ErrorMessage: "+id.errorMessage); + + } + + if(s!= null) s.close(); + } +//*/ + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/server/IdentAuthenticator.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,150 @@ +package net.sourceforge.jsocks.server; +import net.sourceforge.jsocks.InetRange; +import net.sourceforge.jsocks.ProxyMessage; +import java.util.Hashtable; +import java.util.Vector; +import java.util.Enumeration; +import java.net.*; +import java.io.*; + +/** + An implementation of socks.ServerAuthentication which provides + simple authentication based on the host from which the connection + is made and the name of the user on the remote machine, as reported + by identd daemon on the remote machine. + <p> + It can also be used to provide authentication based only on the contacting + host address. +*/ + +public class IdentAuthenticator extends ServerAuthenticatorNone{ + /** Vector of InetRanges */ + Vector hosts; + + /** Vector of user hashes*/ + Vector users; + + String user; + + + /** + Constructs empty IdentAuthenticator. + */ + public IdentAuthenticator(){ + hosts = new Vector(); + users = new Vector(); + } + /** + Used to create instances returned from startSession. + @param in Input stream. + @param out OutputStream. + @param user Username associated with this connection,could be + null if name was not required. + */ + IdentAuthenticator(InputStream in,OutputStream out, String user){ + super(in,out); + this.user = user; + } + + /** + Adds range of addresses from which connection is allowed. Hashtable + users should contain user names as keys and anything as values + (value is not used and will be ignored). + @param hostRange Range of ip addresses from which connection is allowed. + @param users Hashtable of users for whom connection is allowed, or null + to indicate that anybody is allowed to connect from the hosts within given + range. + */ + public synchronized void add(InetRange hostRange,Hashtable users){ + this.hosts.addElement(hostRange); + this.users.addElement(users); + } + + /** + Grants permission only to those users, who connect from one of the + hosts registered with add(InetRange,Hashtable) and whose names, as + reported by identd daemon, are listed for the host the connection + came from. + */ + public ServerAuthenticator startSession(Socket s) + throws IOException{ + + int ind = getRangeIndex(s.getInetAddress()); + String user = null; + + //System.out.println("getRangeReturned:"+ind); + + if(ind < 0) return null; //Host is not on the list. + + ServerAuthenticatorNone auth = (ServerAuthenticatorNone) + super.startSession(s); + + //System.out.println("super.startSession() returned:"+auth); + if(auth == null) return null; + + //do the authentication + + Hashtable user_names = (Hashtable) users.elementAt(ind); + + if(user_names != null){ //If need to do authentication + Ident ident; + ident = new Ident(s); + //If can't obtain user name, fail + if(!ident.successful) return null; + //If user name is not listed for this address, fail + if(!user_names.containsKey(ident.userName)) return null; + user = ident.userName; + } + return new IdentAuthenticator(auth.in,auth.out,user); + + } + /** + For SOCKS5 requests allways returns true. For SOCKS4 requests + checks wether the user name supplied in the request corresponds + to the name obtained from the ident daemon. + */ + public boolean checkRequest(ProxyMessage msg,java.net.Socket s){ + //If it's version 5 request, or if anybody is permitted, return true; + if(msg.version == 5 || user == null) + return true; + + if(msg.version != 4) return false; //Who knows? + + return user.equals(msg.user); + } + + /** Get String representaion of the IdentAuthenticator.*/ + public String toString(){ + String s = ""; + + for(int i=0;i<hosts.size();++i) + s += "Range:"+hosts.elementAt(i)+"\nUsers:"+userNames(i)+"\n"; + return s; + } + +//Private Methods +////////////////// + private int getRangeIndex(InetAddress ip){ + int index = 0; + Enumeration eEnum = hosts.elements(); + while(eEnum.hasMoreElements()){ + InetRange ir = (InetRange) eEnum.nextElement(); + if(ir.contains(ip)) return index; + index++; + } + return -1; //Not found + } + + private String userNames(int i){ + if(users.elementAt(i) == null) return "Everybody is permitted."; + + Enumeration eEnum = ((Hashtable)users.elementAt(i)).keys(); + if(!eEnum.hasMoreElements()) return ""; + String s = eEnum.nextElement().toString(); + while(eEnum.hasMoreElements()) + s += "; "+eEnum.nextElement(); + + return s; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/server/ServerAuthenticator.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,119 @@ +package net.sourceforge.jsocks.server; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.net.DatagramPacket; +import net.sourceforge.jsocks.ProxyMessage; +import net.sourceforge.jsocks.UDPEncapsulation; + +/** + Classes implementing this interface should provide socks server with + authentication and authorization of users. +**/ +public interface ServerAuthenticator{ + + /** + This method is called when a new connection accepted by the server. + <p> + At this point no data have been extracted from the connection. It is + responsibility of this method to ensure that the next byte in the + stream after this method have been called is the first byte of the + socks request message. For SOCKSv4 there is no authentication data and + the first byte in the stream is part of the request. With SOCKSv5 however + there is an authentication data first. It is expected that implementaions + will process this authentication data. + <p> + If authentication was successful an instance of ServerAuthentication + should be returned, it later will be used by the server to perform + authorization and some other things. If authentication fails null should + be returned, or an exception may be thrown. + + @param s Accepted Socket. + @return An instance of ServerAuthenticator to be used for this connection + or null + */ + ServerAuthenticator startSession(Socket s) throws IOException; + + /** + This method should return input stream which should be used on the + accepted socket. + <p> + SOCKSv5 allows to have multiple authentication methods, and these methods + might require some kind of transformations being made on the data. + <p> + This method is called on the object returned from the startSession + function. + */ + InputStream getInputStream(); + /** + This method should return output stream to use to write to the accepted + socket. + <p> + SOCKSv5 allows to have multiple authentication methods, and these methods + might require some kind of transformations being made on the data. + <p> + This method is called on the object returned from the startSession + function. + */ + OutputStream getOutputStream(); + + /** + This method should return UDPEncapsulation, which should be used + on the datagrams being send in/out. + <p> + If no transformation should be done on the datagrams, this method + should return null. + <p> + This method is called on the object returned from the startSession + function. + */ + + UDPEncapsulation getUdpEncapsulation(); + + /** + This method is called when a request have been read. + <p> + Implementation should decide wether to grant request or not. Returning + true implies granting the request, false means request should be rejected. + <p> + This method is called on the object returned from the startSession + function. + @param msg Request message. + @return true to grant request, false to reject it. + */ + boolean checkRequest(ProxyMessage msg); + + /** + This method is called when datagram is received by the server. + <p> + Implementaions should decide wether it should be forwarded or dropped. + It is expecteed that implementation will use datagram address and port + information to make a decision, as well as anything else. Address and + port of the datagram are always correspond to remote machine. It is + either destination or source address. If out is true address is destination + address, else it is a source address, address of the machine from which + datagram have been received for the client. + <p> + Implementaions should return true if the datagram is to be forwarded, and + false if the datagram should be dropped. + <p> + This method is called on the object returned from the startSession + function. + + @param out If true the datagram is being send out(from the client), + otherwise it is an incoming datagram. + @return True to forward datagram false drop it silently. + */ + boolean checkRequest(DatagramPacket dp, boolean out); + + /** + This method is called when session is completed. Either due to normal + termination or due to any error condition. + <p> + This method is called on the object returned from the startSession + function. + */ + void endSession(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/server/ServerAuthenticatorNone.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,170 @@ +package net.sourceforge.jsocks.server; +import net.sourceforge.jsocks.ProxyMessage; +import net.sourceforge.jsocks.UDPEncapsulation; + +import java.io.IOException; +import java.io.InputStream; +import java.io.DataInputStream; +import java.io.OutputStream; +import java.io.PushbackInputStream; +import java.net.Socket; + +/** + An implementation of ServerAuthenticator, which does <b>not</b> do + any authentication. +<P> +<FONT size="+3" color ="FF0000"> Warning!!</font><br> Should not be +used on machines which are not behind the firewall. +<p> +It is only provided to make implementing other authentication schemes +easier.<br> +For Example: <tt><pre> + class MyAuth extends socks.server.ServerAuthenticator{ + ... + public ServerAuthenticator startSession(java.net.Socket s){ + if(!checkHost(s.getInetAddress()) return null; + return super.startSession(s); + } + + boolean checkHost(java.net.Inetaddress addr){ + boolean allow; + //Do it somehow + return allow; + } + } +</pre></tt> +*/ +public class ServerAuthenticatorNone implements ServerAuthenticator{ + + static final byte[] socks5response = {5,0}; + + InputStream in; + OutputStream out; + + /** + Creates new instance of the ServerAuthenticatorNone. + */ + public ServerAuthenticatorNone(){ + this.in = null; + this.out = null; + } + /** + Constructs new ServerAuthenticatorNone object suitable for returning + from the startSession function. + @param in Input stream to return from getInputStream method. + @param out Output stream to return from getOutputStream method. + */ + public ServerAuthenticatorNone(InputStream in, OutputStream out){ + this.in = in; + this.out = out; + } + /** + Grants access to everyone.Removes authentication related bytes from + the stream, when a SOCKS5 connection is being made, selects an + authentication NONE. + */ + public ServerAuthenticator startSession(Socket s) + throws IOException{ + + PushbackInputStream in = new PushbackInputStream(s.getInputStream()); + OutputStream out = s.getOutputStream(); + + int version = in.read(); + if(version == 5){ + if(!selectSocks5Authentication(in,out,0)) + return null; + }else if(version == 4){ + //Else it is the request message allready, version 4 + in.unread(version); + }else + return null; + + + return new ServerAuthenticatorNone(in,out); + } + + /** + Get input stream. + @return Input stream speciefied in the constructor. + */ + public InputStream getInputStream(){ + return in; + } + /** + Get output stream. + @return Output stream speciefied in the constructor. + */ + public OutputStream getOutputStream(){ + return out; + } + /** + Allways returns null. + @return null + */ + public UDPEncapsulation getUdpEncapsulation(){ + return null; + } + + /** + Allways returns true. + */ + public boolean checkRequest(ProxyMessage msg){ + return true; + } + + /** + Allways returns true. + */ + public boolean checkRequest(java.net.DatagramPacket dp, boolean out){ + return true; + } + + /** + Does nothing. + */ + public void endSession(){ + } + + /** + Convinience routine for selecting SOCKSv5 authentication. + <p> + This method reads in authentication methods that client supports, + checks wether it supports given method. If it does, the notification + method is written back to client, that this method have been chosen + for authentication. If given method was not found, authentication + failure message is send to client ([5,FF]). + @param in Input stream, version byte should be removed from the stream + before calling this method. + @param out Output stream. + @param methodId Method which should be selected. + @return true if methodId was found, false otherwise. + */ + static public boolean selectSocks5Authentication(InputStream in, + OutputStream out, + int methodId) + throws IOException{ + + int num_methods = in.read(); + if (num_methods <= 0) return false; + byte method_ids[] = new byte[num_methods]; + byte response[] = new byte[2]; + boolean found = false; + + response[0] = (byte) 5; //SOCKS version + response[1] = (byte) 0xFF; //Not found, we are pessimistic + + int bread = 0; //bytes read so far + while(bread < num_methods) + bread += in.read(method_ids,bread,num_methods-bread); + + for(int i=0;i<num_methods;++i) + if(method_ids[i] == methodId){ + found = true; + response[1] = (byte) methodId; + break; + } + + out.write(response); + return found; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/server/UserPasswordAuthenticator.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,73 @@ +package net.sourceforge.jsocks.server; + +import net.sourceforge.jsocks.ProxyMessage; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +/** + This class implements SOCKS5 User/Password authentication scheme as + defined in rfc1929,the server side of it. +*/ +public class UserPasswordAuthenticator extends ServerAuthenticatorNone{ + + static final int METHOD_ID = 2; + + UserValidation validator; + + /** + Construct a new UserPasswordAuthentication object, with given + UserVlaidation scheme. + + @param v UserValidation to use for validating users. + */ + public UserPasswordAuthenticator(UserValidation validator){ + this.validator = validator; + } + + public ServerAuthenticator startSession(Socket s) throws IOException{ + InputStream in = s.getInputStream(); + OutputStream out = s.getOutputStream(); + + if(in.read() != 5) return null; //Drop non version 5 messages. + + if(!selectSocks5Authentication(in,out,METHOD_ID)) + return null; + if(!doUserPasswordAuthentication(s,in,out)) + return null; + + return new ServerAuthenticatorNone(in,out); + } + + +//Private Methods +////////////////// + + private boolean doUserPasswordAuthentication(Socket s, + InputStream in, + OutputStream out) + throws IOException{ + int version = in.read(); + if(version != 1) return false; + int ulen = in.read(); + if(ulen < 0) return false; + byte[] user = new byte[ulen]; + in.read(user); + int plen = in.read(); + if(plen < 0) return false; + byte[] password = new byte[plen]; + in.read(password); + + if(validator.isUserValid(new String(user), new String(password),s)){ + //System.out.println("user valid"); + out.write(new byte[]{1,0}); + }else{ + //System.out.println("user invalid"); + out.write(new byte[]{1,1}); + return false; + } + + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/net/sourceforge/jsocks/server/UserValidation.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,21 @@ +package net.sourceforge.jsocks.server; + +/** + Interface which provides for user validation, based on user name + password and where it connects from. +*/ +public interface UserValidation{ + /** + Implementations of this interface are expected to use some or all + of the information provided plus any information they can extract + from other sources to decide wether given user should be allowed + access to SOCKS server, or whatever you use it for. + + @return true to indicate user is valid, false otherwise. + @param username User whom implementation should validate. + @param password Password this user provided. + @param connection Socket which user used to connect to the server. + */ + boolean isUserValid(String username,String password, + java.net.Socket connection); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/apache/harmony/niochar/charset/additional/IBM437.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,467 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.niochar.charset.additional; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; + +/* TODO: support direct byte buffers +import org.apache.harmony.nio.AddressUtil; +import org.apache.harmony.niochar.CharsetProviderImpl; +*/ + +public class IBM437 extends Charset { + + public IBM437(String csName, String[] aliases) { + super(csName, aliases); + } + + public boolean contains(Charset cs) { + return cs.name().equalsIgnoreCase("IBM367") || cs.name().equalsIgnoreCase("IBM437") || cs.name().equalsIgnoreCase("US-ASCII") ; + } + + public CharsetDecoder newDecoder() { + return new Decoder(this); + } + + public CharsetEncoder newEncoder() { + return new Encoder(this); + } + + private static final class Decoder extends CharsetDecoder { + private Decoder(Charset cs) { + super(cs, 1, 1); + } + + private native int nDecode(char[] array, int arrPosition, int remaining, long outAddr, int absolutePos); + + + protected CoderResult decodeLoop(ByteBuffer bb, CharBuffer cb) { + int cbRemaining = cb.remaining(); + + /* TODO: support direct byte buffers + if(CharsetProviderImpl.hasLoadedNatives() && bb.isDirect() && bb.hasRemaining() && cb.hasArray()){ + int toProceed = bb.remaining(); + int cbPos = cb.position(); + int bbPos = bb.position(); + boolean throwOverflow = false; + if( cbRemaining < toProceed ) { + toProceed = cbRemaining; + throwOverflow = true; + } + int res = nDecode(cb.array(), cb.arrayOffset()+cbPos, toProceed, AddressUtil.getDirectBufferAddress(bb), bbPos); + bb.position(bbPos+res); + cb.position(cbPos+res); + if(throwOverflow) return CoderResult.OVERFLOW; + }else{ + */ + if (bb.hasArray() && cb.hasArray()) { + int rem = bb.remaining(); + rem = cbRemaining >= rem ? rem : cbRemaining; + byte[] bArr = bb.array(); + char[] cArr = cb.array(); + int bStart = bb.position(); + int cStart = cb.position(); + int i; + + for (i = bStart; i < bStart + rem; i++) { + char in = (char)(bArr[i] & 0xFF); + + if (in >= 26) { + int index = (int)in - 26; + cArr[cStart++] = (char)arr[index]; + } + else { + cArr[cStart++] = (char)(in & 0xFF); + } + } + + bb.position(i); + cb.position(cStart); + + if (rem == cbRemaining && bb.hasRemaining()) return CoderResult.OVERFLOW; + } + else { + while (bb.hasRemaining()) { + if (cbRemaining == 0) return CoderResult.OVERFLOW; + + char in = (char)(bb.get() & 0xFF); + + if (in >= 26) { + int index = (int)in - 26; + cb.put(arr[index]); + } + else { + cb.put((char)(in & 0xFF)); + } + + cbRemaining--; + } + + /* + } + */ + } + + return CoderResult.UNDERFLOW; + } + + final static char[] arr = { + 0x001C, 0x001B, 0x007F, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x001A, + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x03BC, 0x03C4, + 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 + }; + } + + private static final class Encoder extends CharsetEncoder { + private Encoder(Charset cs) { + super(cs, 1, 1); + } + + private native void nEncode(long outAddr, int absolutePos, char[] array, int arrPosition, int[] res); + + protected CoderResult encodeLoop(CharBuffer cb, ByteBuffer bb) { + int bbRemaining = bb.remaining(); + + /* TODO: support direct byte buffers + if(CharsetProviderImpl.hasLoadedNatives() && bb.isDirect() && cb.hasRemaining() && cb.hasArray()){ + int toProceed = cb.remaining(); + int cbPos = cb.position(); + int bbPos = bb.position(); + boolean throwOverflow = false; + if( bbRemaining < toProceed ) { + toProceed = bbRemaining; + throwOverflow = true; + } + int[] res = {toProceed, 0}; + nEncode(AddressUtil.getDirectBufferAddress(bb), bbPos, cb.array(), cb.arrayOffset()+cbPos, res); + if( res[0] <= 0 ) { + bb.position(bbPos-res[0]); + cb.position(cbPos-res[0]); + if(res[1]!=0) { + if(res[1] < 0) + return CoderResult.malformedForLength(-res[1]); + else + return CoderResult.unmappableForLength(res[1]); + } + }else{ + bb.position(bbPos+res[0]); + cb.position(cbPos+res[0]); + if(throwOverflow) return CoderResult.OVERFLOW; + } + }else{ + */ + if (bb.hasArray() && cb.hasArray()) { + byte[] byteArr = bb.array(); + char[] charArr = cb.array(); + int rem = cb.remaining(); + int byteArrStart = bb.position(); + rem = bbRemaining <= rem ? bbRemaining : rem; + int x; + + for (x = cb.position(); x < cb.position() + rem; x++) { + char c = charArr[x]; + + if (c > (char)0x25A0) { + if (c >= 0xD800 && c <= 0xDFFF) { + if (x + 1 < cb.limit()) { + char c1 = charArr[x + 1]; + + if (c1 >= 0xD800 && c1 <= 0xDFFF) { + cb.position(x); bb.position(byteArrStart); + return CoderResult.unmappableForLength(2); + } + } + else { + cb.position(x); bb.position(byteArrStart); + return CoderResult.UNDERFLOW; + } + + cb.position(x); bb.position(byteArrStart); + return CoderResult.malformedForLength(1); + } + + cb.position(x); bb.position(byteArrStart); + return CoderResult.unmappableForLength(1); + } + else { + if (c < 0x1A) { + byteArr[byteArrStart++] = (byte)c; + } + else { + int index = (int)c >> 8; + index = encodeIndex[index]; + + if (index < 0) { + cb.position(x); bb.position(byteArrStart); + return CoderResult.unmappableForLength(1); + } + + index <<= 8; + index += (int)c & 0xFF; + + if ((byte)arr[index] != 0) { + byteArr[byteArrStart++] = (byte)arr[index]; + } + else { + cb.position(x); bb.position(byteArrStart); + return CoderResult.unmappableForLength(1); + } + } + } + } + + cb.position(x); + bb.position(byteArrStart); + + if (rem == bbRemaining && cb.hasRemaining()) { + return CoderResult.OVERFLOW; + } + } + else { + while (cb.hasRemaining()) { + if (bbRemaining == 0) return CoderResult.OVERFLOW; + + char c = cb.get(); + + if (c > (char)0x25A0) { + if (c >= 0xD800 && c <= 0xDFFF) { + if (cb.hasRemaining()) { + char c1 = cb.get(); + + if (c1 >= 0xD800 && c1 <= 0xDFFF) { + cb.position(cb.position() - 2); + return CoderResult.unmappableForLength(2); + } + else { + cb.position(cb.position() - 1); + } + } + else { + cb.position(cb.position() - 1); + return CoderResult.UNDERFLOW; + } + + cb.position(cb.position() - 1); + return CoderResult.malformedForLength(1); + } + + cb.position(cb.position() - 1); + return CoderResult.unmappableForLength(1); + } + else { + if (c < 0x1A) { + bb.put((byte)c); + } + else { + int index = (int)c >> 8; + index = encodeIndex[index]; + + if (index < 0) { + cb.position(cb.position() - 1); + return CoderResult.unmappableForLength(1); + } + + index <<= 8; + index += (int)c & 0xFF; + + if ((byte)arr[index] != 0) { + bb.put((byte)arr[index]); + } + else { + cb.position(cb.position() - 1); + return CoderResult.unmappableForLength(1); + } + } + + bbRemaining--; + } + } + + /* TODO: support direct byte buffers + } + */ + } + + return CoderResult.UNDERFLOW; + } + + final static char arr[] = { + + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x7F, 0x1B, 0x1A, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x1C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xAD, 0x9B, 0x9C, 0x00, 0x9D, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xAE, 0xAA, 0x00, 0x00, 0x00, + 0xF8, 0xF1, 0xFD, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0xA7, 0xAF, 0xAC, 0xAB, 0x00, 0xA8, + 0x00, 0x00, 0x00, 0x00, 0x8E, 0x8F, 0x92, 0x80, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0xE1, + 0x85, 0xA0, 0x83, 0x00, 0x84, 0x86, 0x91, 0x87, 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, + 0x00, 0xA4, 0x95, 0xA2, 0x93, 0x00, 0x94, 0xF6, 0x00, 0x97, 0xA3, 0x96, 0x81, 0x00, 0x00, 0x98, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0xE8, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0xEB, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, + 0xE3, 0x00, 0x00, 0xE5, 0xE7, 0x00, 0xED, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xFB, 0x00, 0x00, 0x00, 0xEC, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0xF3, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF4, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0xC4, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, + 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xCD, 0xBA, 0xD5, 0xD6, 0xC9, 0xB8, 0xB7, 0xBB, 0xD4, 0xD3, 0xC8, 0xBE, 0xBD, 0xBC, 0xC6, 0xC7, + 0xCC, 0xB5, 0xB6, 0xB9, 0xD1, 0xD2, 0xCB, 0xCF, 0xD0, 0xCA, 0xD8, 0xD7, 0xCE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xDF, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, + 0xDE, 0xB0, 0xB1, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + final static int[] encodeIndex = { + 0, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 3, -1, 4, 5, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/keyczar/jce/EcCore.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,678 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.keyczar.jce; + +import java.math.BigInteger; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; + +/** + * This class implements the basic EC operations such as point addition and + * doubling and point multiplication. Only NSA Suite B / NIST curves are + * supported. + * + * Todo: + * - Add (more) comments - Performance optimizations - Cleanup ASN.1 code, + * possibly replace with own impl - ... + * + * References: + * + * [1] Software Implementation of the NIST Elliptic Curves Over Prime Fields, M. + * Brown et al. [2] Efficient elliptic curve exponentiation using mixed + * coordinates, H. Cohen et al. [3] SEC 1: Elliptic Curve Cryptography. [4] + * Guide to Elliptic Curve Cryptography, D. Hankerson et al., Springer. + * + * @author martclau@gmail.com + * + */ +// BEGIN connectbot-changed +public final class EcCore { +// END connectbot-changed +// BEGIN connectbot-removed +// private static final long serialVersionUID = -1376116429660095993L; +// +// private static final String INFO = "Google Keyczar (EC key/parameter generation; EC signing)"; +// +// public static final String NAME = "GooKey"; +// +// @SuppressWarnings("unchecked") +// public EcCore() { +// super(NAME, 0.1, INFO); +// AccessController.doPrivileged(new PrivilegedAction<Object>() { +// @Override +// public Object run() { +// put("Signature.SHA1withECDSA", "org.keyczar.jce.EcSignatureImpl$SHA1"); +// put("Alg.Alias.Signature.ECDSA", "SHA1withDSA"); +// put("Signature.SHA256withECDSA", +// "org.keyczar.jce.EcSignatureImpl$SHA256"); +// put("Signature.SHA384withECDSA", +// "org.keyczar.jce.EcSignatureImpl$SHA384"); +// put("Signature.SHA512withECDSA", +// "org.keyczar.jce.EcSignatureImpl$SHA512"); +// put("KeyPairGenerator.EC", "org.keyczar.jce.EcKeyPairGeneratorImpl"); +// put("KeyFactory.EC", "org.keyczar.jce.EcKeyFactoryImpl"); +// put("Signature.SHA1withECDSA KeySize", "521"); +// put("Signature.SHA1withECDSA ImplementedIn", "Software"); +// put("Signature.SHA256withECDSA KeySize", "521"); +// put("Signature.SHA256withECDSA ImplementedIn", "Software"); +// put("Signature.SHA384withECDSA KeySize", "521"); +// put("Signature.SHA384withECDSA ImplementedIn", "Software"); +// put("Signature.SHA512withECDSA KeySize", "521"); +// put("Signature.SHA512withECDSA ImplementedIn", "Software"); +// put("KeyPairGenerator.EC ImplementedIn", "Software"); +// put("KeyFactory.EC ImplementedIn", "Software"); +// return null; +// } +// }); +// } +// +// private static final ECParameterSpec P192 = new ECParameterSpec( +// new EllipticCurve( +// new ECFieldFp(new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16)), +// new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", 16), +// new BigInteger("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", 16)), +// new ECPoint( +// new BigInteger("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", 16), +// new BigInteger("07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", 16)), +// new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 16), 1); +// +// private static final ECParameterSpec P224 = new ECParameterSpec( +// new EllipticCurve(new ECFieldFp(new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", 16)), +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", 16), +// new BigInteger( +// "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", 16)), +// new ECPoint(new BigInteger( +// "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", 16), +// new BigInteger( +// "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", 16)), +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 16), 1); +// +// private static final ECParameterSpec P256 = new ECParameterSpec( +// new EllipticCurve(new ECFieldFp(new BigInteger( +// "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", +// 16)), new BigInteger( +// "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", +// 16), new BigInteger( +// "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", +// 16)), new ECPoint(new BigInteger( +// "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", +// 16), new BigInteger( +// "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", +// 16)), new BigInteger( +// "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", +// 16), 1); +// +// private static final ECParameterSpec P384 = new ECParameterSpec( +// new EllipticCurve( +// new ECFieldFp( +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", +// 16)), +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", +// 16), +// new BigInteger( +// "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", +// 16)), +// new ECPoint( +// new BigInteger( +// "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", +// 16), +// new BigInteger( +// "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", +// 16)), +// new BigInteger( +// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", +// 16), 1); +// +// private static final ECParameterSpec P521 = new ECParameterSpec( +// new EllipticCurve( +// new ECFieldFp( +// new BigInteger( +// "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", +// 16)), +// new BigInteger( +// "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", +// 16), +// new BigInteger( +// "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", +// 16)), +// new ECPoint( +// new BigInteger( +// "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", +// 16), +// new BigInteger( +// "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", +// 16)), +// new BigInteger( +// "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", +// 16), 1); +// +// public static final String EC_PARAMS_P192_OID = "1.2.840.10045.3.1.1"; +// public static final String EC_PARAMS_P224_OID = "1.3.132.0.33"; +// public static final String EC_PARAMS_P256_OID = "1.2.840.10045.3.1.7"; +// public static final String EC_PARAMS_P384_OID = "1.3.132.0.34"; +// public static final String EC_PARAMS_P521_OID = "1.3.132.0.35"; +// +// private static Map<String, ECParameterSpec> oidMap = new HashMap<String, ECParameterSpec>(); +// private static Map<ECParameterSpec, String> paramsMap = new HashMap<ECParameterSpec, String>(); +// private static Map<ECParameterSpec, String> friendlyNameMap = new HashMap<ECParameterSpec, String>(); +// +// static { +// oidMap.put(EC_PARAMS_P192_OID, P192); +// oidMap.put(EC_PARAMS_P224_OID, P224); +// oidMap.put(EC_PARAMS_P256_OID, P256); +// oidMap.put(EC_PARAMS_P384_OID, P384); +// oidMap.put(EC_PARAMS_P521_OID, P521); +// paramsMap.put(P192, EC_PARAMS_P192_OID); +// paramsMap.put(P224, EC_PARAMS_P224_OID); +// paramsMap.put(P256, EC_PARAMS_P256_OID); +// paramsMap.put(P384, EC_PARAMS_P384_OID); +// paramsMap.put(P521, EC_PARAMS_P521_OID); +// friendlyNameMap.put(P192, "P-192"); +// friendlyNameMap.put(P224, "P-224"); +// friendlyNameMap.put(P256, "P-256"); +// friendlyNameMap.put(P384, "P-384"); +// friendlyNameMap.put(P521, "P-521"); +// } +// +// public static ECParameterSpec getParams(String oid) { +// ECParameterSpec params; +// if ((params = oidMap.get(oid)) != null) return params; +// throw new IllegalArgumentException("Unsupported EC parameters: " + oid); +// } +// +// public static String getOID(ECParameterSpec params) { +// String oid; +// if ((oid = paramsMap.get(params)) != null) return oid; +// throw new IllegalArgumentException("Unsupport EC parameters"); +// } +// +// public static String getFriendlyName(ECParameterSpec params) { +// String name; +// if ((name = friendlyNameMap.get(params)) != null) return name; +// throw new IllegalArgumentException("Unsupport EC parameters"); +// } +// +// private static final BigInteger ZERO = BigInteger.ZERO; +// private static final BigInteger ONE = BigInteger.ONE; +// private static final BigInteger TWO = BigInteger.valueOf(2); +// END connectbot-removed + private static final BigInteger THREE = BigInteger.valueOf(3); +// BEGIN connectbot-removed +// private static final BigInteger FOUR = BigInteger.valueOf(4); +// private static final BigInteger EIGHT = BigInteger.valueOf(8); +// END connectbot-removed + + private static BigInteger[] doublePointA(BigInteger[] P, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + final BigInteger a = params.getCurve().getA(); + + if (P[0] == null || P[1] == null) return P; + + BigInteger d = (P[0].pow(2).multiply(THREE).add(a)).multiply(P[1] + .shiftLeft(1).modInverse(p)); + BigInteger[] R = new BigInteger[2]; + R[0] = d.pow(2).subtract(P[0].shiftLeft(1)).mod(p); + R[1] = d.multiply(P[0].subtract(R[0])).subtract(P[1]).mod(p); + return R; + } + + private static BigInteger[] addPointsA(BigInteger[] P1, BigInteger[] P2, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + + if (P2[0] == null || P2[1] == null) return P1; + + if (P1[0] == null || P1[1] == null) return P2; + + BigInteger d = (P2[1].subtract(P1[1])).multiply((P2[0].subtract(P1[0])) + .modInverse(p)); + BigInteger[] R = new BigInteger[2]; + R[0] = d.pow(2).subtract(P1[0]).subtract(P2[0]).mod(p); + R[1] = d.multiply(P1[0].subtract(R[0])).subtract(P1[1]).mod(p); + return R; + } + + public static BigInteger[] multiplyPointA(BigInteger[] P, BigInteger k, + ECParameterSpec params) { + BigInteger[] Q = new BigInteger[] {null, null}; + + for (int i = k.bitLength() - 1; i >= 0; i--) { + Q = doublePointA(Q, params); + + if (k.testBit(i)) Q = addPointsA(Q, P, params); + } + + return Q; + } + +// BEGIN connectbot-removed +// private static BigInteger[] doublePointJ(BigInteger[] P, +// ECParameterSpec params) { +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// BigInteger A, B, C, D; +// +// if (P[2].signum() == 0) // point at inf +// return P; +// +// A = FOUR.multiply(P[0]).multiply(P[1].pow(2)).mod(p); +// B = EIGHT.multiply(P[1].pow(4)).mod(p); +// C = THREE.multiply(P[0].subtract(P[2].pow(2))).multiply( +// P[0].add(P[2].pow(2))).mod(p); +// D = C.pow(2).subtract(A.add(A)).mod(p); +// +// return new BigInteger[] { +// D, C.multiply(A.subtract(D)).subtract(B).mod(p), +// TWO.multiply(P[1]).multiply(P[2]).mod(p)}; +// } +// +// private static BigInteger[] addPointsJA(BigInteger[] P1, BigInteger[] P2, +// ECParameterSpec params) { +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// BigInteger A, B, C, D; +// BigInteger X3; +// +// if (P1[2].signum() == 0) // point at inf +// return new BigInteger[] {P2[0], P2[1], ONE}; +// +// A = P2[0].multiply(P1[2].pow(2)).mod(p); +// B = P2[1].multiply(P1[2].pow(3)).mod(p); +// C = A.subtract(P1[0]).mod(p); +// D = B.subtract(P1[1]).mod(p); +// +// X3 = D.pow(2) +// .subtract(C.pow(3).add(TWO.multiply(P1[0]).multiply(C.pow(2)))).mod(p); +// return new BigInteger[] { +// X3, +// D.multiply(P1[0].multiply(C.pow(2)).subtract(X3)).subtract( +// P1[1].multiply(C.pow(3))).mod(p), P1[2].multiply(C).mod(p)}; +// } +// +// // Binary NAF method for point multiplication +// public static BigInteger[] multiplyPoint(BigInteger[] P, BigInteger k, +// ECParameterSpec params) { +// BigInteger h = THREE.multiply(k); +// +// BigInteger[] Pneg = new BigInteger[] {P[0], P[1].negate()}; +// BigInteger[] R = new BigInteger[] {P[0], P[1], ONE}; +// +// int bitLen = h.bitLength(); +// for (int i = bitLen - 2; i > 0; --i) { +// R = doublePointJ(R, params); +// if (h.testBit(i)) R = addPointsJA(R, P, params); +// if (k.testBit(i)) R = addPointsJA(R, Pneg, params); +// } +// +// // // <DEBUG> +// // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; +// // toAffine(SS, params); +// // BigInteger[] RR = multiplyPointA(P, k, params); +// // if (!SS[0].equals(RR[0]) || !SS[1].equals(RR[1])) +// // throw new RuntimeException("Internal mult error"); +// // // </DEBUG> +// +// return R; +// } + +// // Simultaneous multiple point multiplication, also known as Shamir's trick +// static BigInteger[] multiplyPoints(BigInteger[] P, BigInteger k, +// BigInteger[] Q, BigInteger l, ECParameterSpec params) { +// BigInteger[] PQ = addPointsA(P, Q, params); +// BigInteger[] R = new BigInteger[] {null, null, ZERO}; +// +// int max = Math.max(k.bitLength(), l.bitLength()); +// for (int i = max - 1; i >= 0; --i) { +// R = doublePointJ(R, params); +// if (k.testBit(i)) { +// if (l.testBit(i)) +// R = addPointsJA(R, PQ, params); +// else +// R = addPointsJA(R, P, params); +// } else if (l.testBit(i)) R = addPointsJA(R, Q, params); +// } +// +// // // <DEBUG> +// // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; +// // toAffine(SS, params); +// // BigInteger[] AA = multiplyPointA(P, k, params); +// // BigInteger[] BB = multiplyPointA(Q, l, params); +// // BigInteger[] AB = addPointsA(AA, BB, params); +// // if (!SS[0].equals(AB[0]) || !SS[1].equals(AB[1])) +// // throw new RuntimeException("Internal mult error"); +// // // </DEBUG> +// +// return R; +// } +// +// // SEC 1, 2.3.5 +// static byte[] fieldElemToBytes(BigInteger a, ECParameterSpec params) { +// int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; +// byte[] bytes = a.toByteArray(); +// if (len < bytes.length) { +// byte[] tmp = new byte[len]; +// System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length); +// return tmp; +// } else if (len > bytes.length) { +// byte[] tmp = new byte[len]; +// System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length); +// return tmp; +// } +// return bytes; +// } +// +// static int fieldElemToBytes(BigInteger a, ECParameterSpec params, +// byte[] data, int off) { +// int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; +// byte[] bytes = a.toByteArray(); +// if (len < bytes.length) { +// System.arraycopy(bytes, bytes.length - len, data, off, len); +// return len; +// } else if (len > bytes.length) { +// System.arraycopy(bytes, 0, data, len - bytes.length + off, bytes.length); +// return len; +// } +// System.arraycopy(bytes, 0, data, off, bytes.length); +// return bytes.length; +// } +// +// // SEC 1, 2.3.3 +// static byte[] ecPointToBytes(ECPoint a, ECParameterSpec params) { +// byte[] fe1 = fieldElemToBytes(a.getAffineX(), params); +// byte[] fe2 = fieldElemToBytes(a.getAffineY(), params); +// byte[] bytes = new byte[1 + fe1.length + fe2.length]; +// bytes[0] = 0x04; +// System.arraycopy(fe1, 0, bytes, 1, fe1.length); +// System.arraycopy(fe2, 0, bytes, 1 + fe1.length, fe2.length); +// return bytes; +// } +// +// // SEC 1, 2.3.4 +// static ECPoint bytesToECPoint(byte[] bytes, ECParameterSpec params) { +// switch (bytes[0]) { +// case 0x00: // point at inf +// throw new IllegalArgumentException( +// "Point at infinity is not a valid argument"); +// case 0x02: // point compression +// case 0x03: +// throw new UnsupportedOperationException( +// "Point compression is not supported"); +// case 0x04: +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// byte[] fe = new byte[(p.bitLength() + 7) / 8]; +// System.arraycopy(bytes, 1, fe, 0, fe.length); +// BigInteger x = new BigInteger(1, fe); +// System.arraycopy(bytes, 1 + fe.length, fe, 0, fe.length); +// return new ECPoint(x, new BigInteger(1, fe)); +// default: +// throw new IllegalArgumentException("Invalid point encoding"); +// } +// } +// +// // Convert Jacobian point to affine +// static void toAffine(BigInteger[] P, ECParameterSpec params) { +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); +// P[1] = P[1].multiply(P[2].pow(3).modInverse(p)).mod(p); +// } +// +// static void toAffineX(BigInteger[] P, ECParameterSpec params) { +// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); +// P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); +// } +// +// static BigInteger[] internalPoint(ECPoint P) { +// return new BigInteger[] {P.getAffineX(), P.getAffineY()}; +// } +// +// // private static void printPerf(String msg, long start, long stop) { +// // String unit = "ms"; +// // long diff = stop - start; +// // if (diff > 1000) { +// // diff /= 1000; +// // unit = "s"; +// // } +// // System.out.printf("%s: %d %s\n", msg, diff, unit); +// // } +// +// public static void main(String[] args) throws Exception { +// +// Security.insertProviderAt(new EcCore(), 0); +// +// // ---- +// // Test primitives +// // ---- +// +// // GooKey EC private key, 256 bit +// // Private value: +// // a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2 +// // Parameters: P-256 (1.2.840.10045.3.1.7) +// // GooKey EC public key, 256 bit +// // Public value (x coordinate): +// // 86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c +// // Public value (y coordinate): +// // ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6 +// // Parameters: P-256 (1.2.840.10045.3.1.7) +// // GooKey EC private key, 256 bit +// // Private value: +// // b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022 +// // Parameters: P-256 (1.2.840.10045.3.1.7) +// // GooKey EC public key, 256 bit +// // Public value (x coordinate): +// // 61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1 +// // Public value (y coordinate): +// // 3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705 +// // Parameters: P-256 (1.2.840.10045.3.1.7) +// +// // P = kG +// BigInteger k = new BigInteger( +// "a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2", 16); +// BigInteger[] P = new BigInteger[] { +// new BigInteger( +// "86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c", +// 16), +// new BigInteger( +// "ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6", +// 16), ONE}; +// +// // Q = lG +// BigInteger l = new BigInteger( +// "b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022", 16); +// BigInteger[] Q = new BigInteger[] { +// new BigInteger( +// "61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1", +// 16), +// new BigInteger( +// "3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705", +// 16), ONE}; +// +// // Known answer for P+Q +// BigInteger[] kat1 = new BigInteger[] { +// new BigInteger( +// "bc7adb05bca2460bbfeb4e0f88b61c384ea88ed3fd56017938ac2582513d4220", +// 16), +// new BigInteger( +// "a640a43df2e9df39eec11445b7e3f7835b743ef1ac4a83cecb570a060b3f1c6c", +// 16)}; +// +// BigInteger[] R = addPointsA(P, Q, P256); +// if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) +// throw new RuntimeException("kat1 failed"); +// +// R = addPointsJA(P, Q, P256); +// toAffine(R, P256); +// if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) +// throw new RuntimeException("kat1 failed"); +// +// +// // Known answer for Q+Q +// BigInteger[] kat2 = new BigInteger[] { +// new BigInteger( +// "c79d7f9100c14a70f0bb9bdce59654abf99e10d1ac5afc1a0f1b6bc650d6429b", +// 16), +// new BigInteger( +// "6856814e47adce42bc0d7c3bef308c6c737c418ed093effb31e21f53c7735c97", +// 16)}; +// +// R = doublePointA(P, P256); +// if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) +// throw new RuntimeException("kat2 failed"); +// +// R = doublePointJ(P, P256); +// toAffine(R, P256); +// if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) +// throw new RuntimeException("kat2 failed"); +// +// // Known answer for kP +// BigInteger[] kat3 = new BigInteger[] { +// new BigInteger( +// "97a82a834b9e6b50660ae30d43dac9b200276e8bcd2ed6a6593048de09276d1a", +// 16), +// new BigInteger( +// "30a9590a01066d8ef54a910afcc8648dbc7400c01750af423ce95547f2154d56", +// 16)}; +// +// R = multiplyPointA(P, k, P256); +// if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) +// throw new RuntimeException("kat3 failed"); +// +// R = multiplyPoint(P, k, P256); +// toAffine(R, P256); +// if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) +// throw new RuntimeException("kat3 failed"); +// +// // Known answer for kP+lQ +// BigInteger[] kat4 = new BigInteger[] { +// new BigInteger( +// "6fd51be5cf3d6a6bcb62594bbe41ccf549b37d8fefff6e293a5bea0836efcfc6", +// 16), +// new BigInteger( +// "9bc21a930137aa3814908974c431e4545a05dce61321253c337f3883129c42ca", +// 16)}; +// +// BigInteger[] RR = multiplyPointA(Q, l, P256); +// R = addPointsA(R, RR, P256); +// if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) +// throw new RuntimeException("kat4 failed"); +// +// R = multiplyPoints(P, k, Q, l, P256); +// toAffine(R, P256); +// if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) +// throw new RuntimeException("kat4 failed"); +// +// // ---- +// // Test ECDSA in various combinations +// // ---- +// +// Provider gooProv = Security.getProvider("GooKey"); +// Provider nssProv = Security.getProvider("SunPKCS11-NSS"); +// +// // Number of iterations: trust me, this is a (stress) good test +// // and does provoke bugs in a fuzzing way. +// int iter = 50; +// +// // Iterate over all key lengths and signature schemes. +// int[] keyLengths = {192, 224, 256, 384, 521}; +// String[] ecdsas = { +// "SHA1withECDSA", "SHA256withECDSA", "SHA384withECDSA", +// "SHA512withECDSA"}; +// for (int s = 0; s < ecdsas.length; s++) { +// System.out.println("Signature scheme " + ecdsas[s]); +// for (int i = 0; i < keyLengths.length; i++) { +// System.out.print("Testing P-" + keyLengths[i] + ": "); +// for (int n = 0; n < iter; n++) { +// System.out.print("."); +// +// KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", gooProv); +// kpGen.initialize(keyLengths[i]); +// KeyPair ecKeyPair = kpGen.generateKeyPair(); +// +// ECPrivateKey ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); +// byte[] tmp = ecPrivKey.getEncoded(); +// KeyFactory keyFab = KeyFactory.getInstance("EC", gooProv); +// keyFab.generatePrivate(new PKCS8EncodedKeySpec(tmp)); +// ECPrivateKeySpec ecPrivSpec = new ECPrivateKeySpec(ecPrivKey.getS(), +// ecPrivKey.getParams()); +// keyFab.generatePrivate(ecPrivSpec); +// +// ECPublicKey ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); +// tmp = ecPubKey.getEncoded(); // dont modify tmp now - is used below +// keyFab.generatePublic(new X509EncodedKeySpec(tmp)); +// ECPublicKeySpec ecPubSpec = new ECPublicKeySpec(ecPubKey.getW(), +// ecPubKey.getParams()); +// keyFab.generatePublic(ecPubSpec); +// +// Signature ecdsa = Signature.getInstance(ecdsas[s], gooProv); +// ecdsa.initSign(ecPrivKey); +// ecdsa.update(tmp); +// byte[] sig = ecdsa.sign(); +// ecdsa.initVerify(ecPubKey); +// ecdsa.update(tmp); +// if (!ecdsa.verify(sig)) +// throw new RuntimeException("Signature not verified: " +// + keyLengths[i]); +// +// // Cross verify using NSS if present +// if (nssProv != null) { +// keyFab = KeyFactory.getInstance("EC", nssProv); +// +// // For some reason NSS doesnt seem to work for P-192 and P-224?! +// if (keyLengths[i] == 192 || keyLengths[i] == 224) continue; +// +// ECPrivateKey nssPrivKey = (ECPrivateKey) keyFab +// .generatePrivate(new PKCS8EncodedKeySpec(ecPrivKey.getEncoded())); +// ECPublicKey nssPubKey = (ECPublicKey) keyFab +// .generatePublic(new X509EncodedKeySpec(ecPubKey.getEncoded())); +// +// ecdsa = Signature.getInstance(ecdsas[s], nssProv); +// ecdsa.initVerify(nssPubKey); +// ecdsa.update(tmp); +// if (!ecdsa.verify(sig)) +// throw new RuntimeException("Signature not verified 2: " +// + keyLengths[i]); +// +// ecdsa.initSign(nssPrivKey); +// ecdsa.update(tmp); +// sig = ecdsa.sign(); +// ecdsa = Signature.getInstance(ecdsas[s], gooProv); +// ecdsa.initVerify(ecPubKey); +// ecdsa.update(tmp); +// if (!ecdsa.verify(sig)) +// throw new RuntimeException("Signature not verified 3: " +// + keyLengths[i]); +// } +// } +// System.out.println(" done"); +// } +// } +// +// // Test Keyczar integration +// // Signer ecdsaSigner = new Signer("c:\\temp\\eckeyset"); +// // String tbs = "Sign this"; +// // String sig = ecdsaSigner.sign(tbs); +// // if (ecdsaSigner.verify(sig, tbs)) +// // System.out.println("Keyczar EC OK"); +// // else +// // System.out.println("Keyczar EC not OK"); +// } +//END connectbot-removed +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/openintents/intents/FileManagerIntents.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2008 OpenIntents.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.intents; + +// Version Dec 9, 2008 + + +/** + * Provides OpenIntents actions, extras, and categories used by providers. + * <p>These specifiers extend the standard Android specifiers.</p> + */ +public final class FileManagerIntents { + + /** + * Activity Action: Pick a file through the file manager, or let user + * specify a custom file name. + * Data is the current file name or file name suggestion. + * Returns a new file name as file URI in data. + * + * <p>Constant Value: "org.openintents.action.PICK_FILE"</p> + */ + public static final String ACTION_PICK_FILE = "org.openintents.action.PICK_FILE"; + + /** + * Activity Action: Pick a directory through the file manager, or let user + * specify a custom file name. + * Data is the current directory name or directory name suggestion. + * Returns a new directory name as file URI in data. + * + * <p>Constant Value: "org.openintents.action.PICK_DIRECTORY"</p> + */ + public static final String ACTION_PICK_DIRECTORY = "org.openintents.action.PICK_DIRECTORY"; + + /** + * The title to display. + * + * <p>This is shown in the title bar of the file manager.</p> + * + * <p>Constant Value: "org.openintents.extra.TITLE"</p> + */ + public static final String EXTRA_TITLE = "org.openintents.extra.TITLE"; + + /** + * The text on the button to display. + * + * <p>Depending on the use, it makes sense to set this to "Open" or "Save".</p> + * + * <p>Constant Value: "org.openintents.extra.BUTTON_TEXT"</p> + */ + public static final String EXTRA_BUTTON_TEXT = "org.openintents.extra.BUTTON_TEXT"; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/TN5250jConstants.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,590 @@ +/* + * @(#)TN5250jConstants.java + * Copyright: Copyright (c) 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ + +package org.tn5250j; +import java.util.HashMap; + +public class TN5250jConstants { + + // Version information + public static final String tn5250jRelease = "0"; + public static final String tn5250jVersion = ".7"; + public static final String tn5250jSubVer = ".4"; + + public static final String VERSION_INFO = tn5250jRelease + tn5250jVersion + tn5250jSubVer; + + // STATE + static final int STATE_DISCONNECTED = 0; + static final int STATE_CONNECTED = 1; + static final int STATE_REMOVE = 2; + + // SESSION Level key value pairs + public static final String SESSION_HOST = "SESSION_HOST"; + public static final String SESSION_HOST_PORT = "SESSION_HOST_PORT"; + public static final String SESSION_CONFIG_RESOURCE = "SESSION_CONFIG_RESOURCE"; + public static final String SESSION_TYPE = "SESSION_HOST_TYPE"; + public static final String SESSION_TN_ENHANCED = "SESSION_TN_ENHANCED"; + public static final String SESSION_SCREEN_SIZE = "SESSION_SCREEN_SIZE"; + public static final String SESSION_CODE_PAGE = "SESSION_CODE_PAGE"; + public static final String SESSION_PROXY_HOST = "SESSION_PROXY_HOST"; + public static final String SESSION_PROXY_PORT = "SESSION_PROXY_PORT"; + public static final String SESSION_USE_GUI = "SESSION_USE_GUI"; + public static final String SESSION_DEVICE_NAME = "SESSION_DEVICE_NAME"; + public static final String SESSION_NAMES_REFS = "SESSION_NAMES_REFS"; + public static final String SESSION_LOCALE = "SESSION_LOCALE"; + public static final String SESSION_CONFIG_FILE = "SESSION_CONFIG_FILE"; + public static final String SESSION_TERM_NAME_SYSTEM = "SESSION_TERM_NAME_SYSTEM"; + public static final String SESSION_TERM_NAME = "SESSION_TERM_NAME"; + public static final String SESSION_IS_APPLET = "SESSION_IS_APPLET"; + public static final String SESSION_HEART_BEAT = "SESSION_KEEP_ALIVE_ENABLED"; + +// public static final String GUI_MDI_TYPE = "GUI_MDI_TYPE"; + public static final String GUI_FRAME_WIDTH = "GUI_FRAME_WIDTH"; + public static final String GUI_FRAME_HEIGHT = "GUI_FRAME_HEIGHT"; + public static final String GUI_NO_TAB = "GUI_NO_TAB"; + public static final String NO_CHECK_RUNNING = "NO_CHECK_RUNNING"; + public static final String START_MONITOR_THREAD = "START_MONITOR_THREAD"; + +// public static final String SSL_TYPE = "TN5250J_SSL_TYPE"; + public static final String SSL_TYPE = "-sslType"; + public static final String SSL_TYPE_NONE = "NONE"; + public static final String SSL_TYPE_SSLv2 = "SSLv2"; + public static final String SSL_TYPE_SSLv3 = "SSLv3"; + public static final String SSL_TYPE_TLS = "TLS"; + + public static final String[] SSL_TYPES = {SSL_TYPE_NONE, + SSL_TYPE_SSLv2, + SSL_TYPE_SSLv3, + SSL_TYPE_TLS + }; + + // Session JUMP Directions + static final int JUMP_PREVIOUS = 0; + static final int JUMP_NEXT = 1; + +// // OS_OHIO_SESSION_TYPE type of sessions +// public static final String OS_OHIO_SESSION_TYPE_5250_STR = "2"; + + // SCREEN_SIZE Size of screen string + public static final String SCREEN_SIZE_24X80_STR = "0"; + public static final String SCREEN_SIZE_27X132_STR = "1"; + + // SCREEN_SIZE Size of screen int + public static final int SCREEN_SIZE_24X80 = 0; + public static final int SCREEN_SIZE_27X132 = 1; + + public static final int NUM_PARMS = 20; + + // mnemonic value constants + public static final int BACK_SPACE = 1001; + public static final int BACK_TAB = 1002; + public static final int UP = 1003; + public static final int DOWN = 1004; + public static final int LEFT = 1005; + public static final int RIGHT = 1006; + public static final int DELETE = 1007; + public static final int TAB = 1008; + public static final int EOF = 1009; + public static final int ERASE_EOF = 1010; + public static final int ERASE_FIELD = 1011; + public static final int INSERT = 1012; + public static final int HOME = 1013; + public static final int KEYPAD_0 = 1014; + public static final int KEYPAD_1 = 1015; + public static final int KEYPAD_2 = 1016; + public static final int KEYPAD_3 = 1017; + public static final int KEYPAD_4 = 1018; + public static final int KEYPAD_5 = 1019; + public static final int KEYPAD_6 = 1020; + public static final int KEYPAD_7 = 1021; + public static final int KEYPAD_8 = 1022; + public static final int KEYPAD_9 = 1023; + public static final int KEYPAD_PERIOD = 1024; + public static final int KEYPAD_COMMA = 1025; + public static final int KEYPAD_MINUS = 1026; + public static final int FIELD_EXIT = 1027; + public static final int FIELD_PLUS = 1028; + public static final int FIELD_MINUS = 1029; + public static final int BOF = 1030; + public static final int SYSREQ = 1031; + public static final int RESET = 1032; + public static final int NEXTWORD = 1033; + public static final int PREVWORD = 1034; + public static final int COPY = 1035; + public static final int PASTE = 1036; + public static final int ATTN = 1037; + public static final int MARK_UP = 1038; + public static final int MARK_DOWN = 1039; + public static final int MARK_LEFT = 1040; + public static final int MARK_RIGHT = 1041; + public static final int DUP_FIELD = 1042; + public static final int NEW_LINE = 1043; + public static final int JUMP_NEXT_SESS = 5000; + public static final int JUMP_PREV_SESS = 5001; + public static final int OPEN_NEW = 5002; + public static final int TOGGLE_CONNECTION = 5003; + public static final int HOTSPOTS = 5004; + public static final int GUI = 5005; + public static final int DSP_MSGS = 5006; + public static final int DSP_ATTRIBUTES = 5007; + public static final int PRINT_SCREEN = 5008; + public static final int CURSOR = 5009; + public static final int DEBUG = 5010; + public static final int CLOSE = 5011; + public static final int TRANSFER = 5012; + public static final int E_MAIL = 5013; + public static final int RUN_SCRIPT = 5014; + public static final int SPOOL_FILE = 5015; + public static final int QUICK_MAIL = 5016; + public static final int OPEN_SAME = 5017; + public static final int FAST_CURSOR_DOWN = 5018; + public static final int FAST_CURSOR_UP = 5019; + public static final int FAST_CURSOR_RIGHT = 5020; + public static final int FAST_CURSOR_LEFT = 5021; + + // PF Keys + public static final int PF1 = 0x31; + public static final int PF2 = 0x32; + public static final int PF3 = 0x33; + public static final int PF4 = 0x34; + public static final int PF5 = 0x35; + public static final int PF6 = 0x36; + public static final int PF7 = 0x37; + public static final int PF8 = 0x38; + public static final int PF9 = 0x39; + public static final int PF10 = 0x3A; + public static final int PF11 = 0x3B; + public static final int PF12 = 0x3C; + public static final int PF13 = 0xB1; + public static final int PF14 = 0xB2; + public static final int PF15 = 0xB3; + public static final int PF16 = 0xB4; + public static final int PF17 = 0xB5; + public static final int PF18 = 0xB6; + public static final int PF19 = 0xB7; + public static final int PF20 = 0xB8; + public static final int PF21 = 0xB9; + public static final int PF22 = 0xBA; + public static final int PF23 = 0xBB; + public static final int PF24 = 0xBC; + + public static final HashMap<String, Integer> mnemonicMap = new HashMap<String, Integer>(); + static { + mnemonicMap.put("[backspace]", 1001); + mnemonicMap.put("[backtab]", 1002); + mnemonicMap.put("[up]", 1003); + mnemonicMap.put("[down]", 1004); + mnemonicMap.put("[left]", 1005); + mnemonicMap.put("[right]", 1006); + mnemonicMap.put("[delete]", 1007); + mnemonicMap.put("[tab]", 1008); + mnemonicMap.put("[eof]", 1009); + mnemonicMap.put("[eraseeof]", 1010); + mnemonicMap.put("[erasefld]", 1011); + mnemonicMap.put("[insert]", 1012); + mnemonicMap.put("[home]", 1013); + mnemonicMap.put("[keypad0]", 1014); + mnemonicMap.put("[keypad1]", 1015); + mnemonicMap.put("[keypad2]", 1016); + mnemonicMap.put("[keypad3]", 1017); + mnemonicMap.put("[keypad4]", 1018); + mnemonicMap.put("[keypad5]", 1019); + mnemonicMap.put("[keypad6]", 1020); + mnemonicMap.put("[keypad7]", 1021); + mnemonicMap.put("[keypad8]", 1022); + mnemonicMap.put("[keypad9]", 1023); + mnemonicMap.put("[keypad.]", 1024); + mnemonicMap.put("[keypad,]", 1025); + mnemonicMap.put("[keypad-]", 1026); + mnemonicMap.put("[fldext]", 1027); + mnemonicMap.put("[field+]", 1028); + mnemonicMap.put("[field-]", 1029); + mnemonicMap.put("[bof]", 1030); + mnemonicMap.put("[enter]", 0xF1); + mnemonicMap.put("[pf1]", 0x31); + mnemonicMap.put("[pf2]", 0x32); + mnemonicMap.put("[pf3]", 0x33); + mnemonicMap.put("[pf4]", 0x34); + mnemonicMap.put("[pf5]", 0x35); + mnemonicMap.put("[pf6]", 0x36); + mnemonicMap.put("[pf7]", 0x37); + mnemonicMap.put("[pf8]", 0x38); + mnemonicMap.put("[pf9]", 0x39); + mnemonicMap.put("[pf10]", 0x3A); + mnemonicMap.put("[pf11]", 0x3B); + mnemonicMap.put("[pf12]", 0x3C); + mnemonicMap.put("[pf13]", 0xB1); + mnemonicMap.put("[pf14]", 0xB2); + mnemonicMap.put("[pf15]", 0xB3); + mnemonicMap.put("[pf16]", 0xB4); + mnemonicMap.put("[pf17]", 0xB5); + mnemonicMap.put("[pf18]", 0xB6); + mnemonicMap.put("[pf19]", 0xB7); + mnemonicMap.put("[pf20]", 0xB8); + mnemonicMap.put("[pf21]", 0xB9); + mnemonicMap.put("[pf22]", 0xBA); + mnemonicMap.put("[pf23]", 0xBB); + mnemonicMap.put("[pf24]", 0xBC); + mnemonicMap.put("[clear]", 0xBD); + mnemonicMap.put("[help]", 0xF3); + mnemonicMap.put("[pgup]", 0xF4); + mnemonicMap.put("[pgdown]", 0xF5); + mnemonicMap.put("[rollleft]", 0xD9); + mnemonicMap.put("[rollright]", 0xDA); + mnemonicMap.put("[hostprint]", 0xF6); + mnemonicMap.put("[pa1]", 0x6C); + mnemonicMap.put("[pa2]", 0x6E); + mnemonicMap.put("[pa3]", 0x6B); + mnemonicMap.put("[sysreq]", 1031); + mnemonicMap.put("[reset]", 1032); + mnemonicMap.put("[nextword]", 1033); + mnemonicMap.put("[prevword]", 1034); + mnemonicMap.put("[copy]", 1035); + mnemonicMap.put("[paste]", 1036); + mnemonicMap.put("[attn]", 1037); + mnemonicMap.put("[markup]", 1038); + mnemonicMap.put("[markdown]", 1039); + mnemonicMap.put("[markleft]", 1040); + mnemonicMap.put("[markright]", 1041); + mnemonicMap.put("[dupfield]", 1042); + mnemonicMap.put("[newline]", 1043); + mnemonicMap.put("[jumpnext]", 5000); + mnemonicMap.put("[jumpprev]", 5001); + mnemonicMap.put("[opennew]", 5002); + mnemonicMap.put("[togcon]", 5003); + mnemonicMap.put("[hotspots]", 5004); + mnemonicMap.put("[gui]", 5005); + mnemonicMap.put("[dspmsgs]", 5006); + mnemonicMap.put("[dspattr]", 5007); + mnemonicMap.put("[print]", 5008); + mnemonicMap.put("[cursor]", 5009); + mnemonicMap.put("[debug]", 5010); + mnemonicMap.put("[close]", 5011); + mnemonicMap.put("[transfer]", 5012); + mnemonicMap.put("[e-mail]", 5013); + mnemonicMap.put("[runscript]", 5014); + mnemonicMap.put("[spoolfile]", 5015); + mnemonicMap.put("[quick-mail]", 5016); + mnemonicMap.put("[open-same]", 5017); + mnemonicMap.put("[fastcursordown]", 5018); + mnemonicMap.put("[fastcursorup]", 5019); + mnemonicMap.put("[fastcursorright]", 5020); + mnemonicMap.put("[fastcursorleft]", 5021); + }; + + public static final String MNEMONIC_CLEAR = "[clear]"; + public static final String MNEMONIC_ENTER = "[enter]"; + public static final String MNEMONIC_HELP = "[help]"; + public static final String MNEMONIC_PAGE_DOWN = "[pgdown]"; + public static final String MNEMONIC_PAGE_UP = "[pgup]"; + public static final String MNEMONIC_PRINT = "[hostprint]"; + public static final String MNEMONIC_PF1 = "[pf1]"; + public static final String MNEMONIC_PF2 = "[pf2]"; + public static final String MNEMONIC_PF3 = "[pf3]"; + public static final String MNEMONIC_PF4 = "[pf4]"; + public static final String MNEMONIC_PF5 = "[pf5]"; + public static final String MNEMONIC_PF6 = "[pf6]"; + public static final String MNEMONIC_PF7 = "[pf7]"; + public static final String MNEMONIC_PF8 = "[pf8]"; + public static final String MNEMONIC_PF9 = "[pf9]"; + public static final String MNEMONIC_PF10 = "[pf10]"; + public static final String MNEMONIC_PF11 = "[pf11]"; + public static final String MNEMONIC_PF12 = "[pf12]"; + public static final String MNEMONIC_PF13 = "[pf13]"; + public static final String MNEMONIC_PF14 = "[pf14]"; + public static final String MNEMONIC_PF15 = "[pf15]"; + public static final String MNEMONIC_PF16 = "[pf16]"; + public static final String MNEMONIC_PF17 = "[pf17]"; + public static final String MNEMONIC_PF18 = "[pf18]"; + public static final String MNEMONIC_PF19 = "[pf19]"; + public static final String MNEMONIC_PF20 = "[pf20]"; + public static final String MNEMONIC_PF21 = "[pf21]"; + public static final String MNEMONIC_PF22 = "[pf22]"; + public static final String MNEMONIC_PF23 = "[pf23]"; + public static final String MNEMONIC_PF24 = "[pf24]"; + public static final String MNEMONIC_BACK_SPACE = "[backspace]"; + public static final String MNEMONIC_BACK_TAB = "[backtab]"; + public static final String MNEMONIC_UP = "[up]"; + public static final String MNEMONIC_DOWN = "[down]"; + public static final String MNEMONIC_LEFT = "[left]"; + public static final String MNEMONIC_RIGHT = "[right]"; + public static final String MNEMONIC_DELETE = "[delete]"; + public static final String MNEMONIC_TAB = "[tab]"; + public static final String MNEMONIC_END_OF_FIELD = "[eof]"; + public static final String MNEMONIC_ERASE_EOF = "[eraseeof]"; + public static final String MNEMONIC_ERASE_FIELD = "[erasefld]"; + public static final String MNEMONIC_INSERT = "[insert]"; + public static final String MNEMONIC_HOME = "[home]"; + public static final String MNEMONIC_KEYPAD0 = "[keypad0]"; + public static final String MNEMONIC_KEYPAD1 = "[keypad1]"; + public static final String MNEMONIC_KEYPAD2 = "[keypad2]"; + public static final String MNEMONIC_KEYPAD3 = "[keypad3]"; + public static final String MNEMONIC_KEYPAD4 = "[keypad4]"; + public static final String MNEMONIC_KEYPAD5 = "[keypad5]"; + public static final String MNEMONIC_KEYPAD6 = "[keypad6]"; + public static final String MNEMONIC_KEYPAD7 = "[keypad7]"; + public static final String MNEMONIC_KEYPAD8 = "[keypad8]"; + public static final String MNEMONIC_KEYPAD9 = "[keypad9]"; + public static final String MNEMONIC_KEYPAD_PERIOD = "[keypad.]"; + public static final String MNEMONIC_KEYPAD_COMMA = "[keypad,]"; + public static final String MNEMONIC_KEYPAD_MINUS = "[keypad-]"; + public static final String MNEMONIC_FIELD_EXIT = "[fldext]"; + public static final String MNEMONIC_FIELD_PLUS = "[field+]"; + public static final String MNEMONIC_FIELD_MINUS = "[field-]"; + public static final String MNEMONIC_BEGIN_OF_FIELD = "[bof]"; + public static final String MNEMONIC_PA1 = "[pa1]"; + public static final String MNEMONIC_PA2 = "[pa2]"; + public static final String MNEMONIC_PA3 = "[pa3]"; + public static final String MNEMONIC_SYSREQ = "[sysreq]"; + public static final String MNEMONIC_RESET = "[reset]"; + public static final String MNEMONIC_NEXTWORD = "[nextword]"; + public static final String MNEMONIC_PREVWORD = "[prevword]"; + public static final String MNEMONIC_ATTN = "[attn]"; + public static final String MNEMONIC_MARK_LEFT = "[markleft]"; + public static final String MNEMONIC_MARK_RIGHT = "[markright]"; + public static final String MNEMONIC_MARK_UP = "[markup]"; + public static final String MNEMONIC_MARK_DOWN = "[markdown]"; + public static final String MNEMONIC_DUP_FIELD = "[dupfield]"; + public static final String MNEMONIC_NEW_LINE = "[newline]"; + public static final String MNEMONIC_JUMP_NEXT = "[jumpnext]"; + public static final String MNEMONIC_JUMP_PREV = "[jumpprev]"; + public static final String MNEMONIC_OPEN_NEW = "[opennew]"; + public static final String MNEMONIC_TOGGLE_CONNECTION = "[togcon]"; + public static final String MNEMONIC_HOTSPOTS = "[hotspots]"; + public static final String MNEMONIC_GUI = "[gui]"; + public static final String MNEMONIC_DISP_MESSAGES = "[dspmsgs]"; + public static final String MNEMONIC_DISP_ATTRIBUTES = "[dspattr]"; + public static final String MNEMONIC_PRINT_SCREEN = "[print]"; + public static final String MNEMONIC_CURSOR = "[cursor]"; + public static final String MNEMONIC_DEBUG = "[debug]"; + public static final String MNEMONIC_CLOSE = "[close]"; + public static final String MNEMONIC_E_MAIL = "[e-mail]"; + public static final String MNEMONIC_COPY = "[copy]"; + public static final String MNEMONIC_PASTE = "[paste]"; + public static final String MNEMONIC_FILE_TRANSFER = "[transfer]"; + public static final String MNEMONIC_RUN_SCRIPT = "[runscript]"; + public static final String MNEMONIC_SPOOL_FILE = "[spoolfile]"; + public static final String MNEMONIC_QUICK_MAIL = "[quick-mail]"; + public static final String MNEMONIC_OPEN_SAME = "[open-same]"; + public static final String MNEMONIC_FAST_CURSOR_DOWN = "[fastcursordown]"; + public static final String MNEMONIC_FAST_CURSOR_UP = "[fastcursorup]"; + public static final String MNEMONIC_FAST_CURSOR_RIGHT = "[fastcursorright]"; + public static final String MNEMONIC_FAST_CURSOR_LEFT = "[fastcursorleft]"; + + // AID-Generating Keys + public static final int AID_CLEAR = 0xBD; + public static final int AID_ENTER = 0xF1; + public static final int AID_HELP = 0xF3; + public static final int AID_ROLL_UP = 0xF4; + public static final int AID_ROLL_DOWN = 0xF5; + public static final int AID_ROLL_LEFT = 0xD9; + public static final int AID_ROLL_RIGHT = 0xDA; + public static final int AID_PRINT = 0xF6; + public static final int AID_PF1 = 0x31; + public static final int AID_PF2 = 0x32; + public static final int AID_PF3 = 0x33; + public static final int AID_PF4 = 0x34; + public static final int AID_PF5 = 0x35; + public static final int AID_PF6 = 0x36; + public static final int AID_PF7 = 0x37; + public static final int AID_PF8 = 0x38; + public static final int AID_PF9 = 0x39; + public static final int AID_PF10 = 0x3A; + public static final int AID_PF11 = 0x3B; + public static final int AID_PF12 = 0x3C; + public static final int AID_PF13 = 0xB1; + public static final int AID_PF14 = 0xB2; + public static final int AID_PF15 = 0xB3; + public static final int AID_PF16 = 0xB4; + public static final int AID_PF17 = 0xB5; + public static final int AID_PF18 = 0xB6; + public static final int AID_PF19 = 0xB7; + public static final int AID_PF20 = 0xB8; + public static final int AID_PF21 = 0xB9; + public static final int AID_PF22 = 0xBA; + public static final int AID_PF23 = 0xBB; + public static final int AID_PF24 = 0xBC; + + // negative response categories + public static final int NR_REQUEST_REJECT = 0x08; + public static final int NR_REQUEST_ERROR = 0x10; + public static final int NR_STATE_ERROR = 0x20; + public static final int NR_USAGE_ERROR = 0x40; + public static final int NR_PATH_ERROR = 0x80; + + // commands + public static final byte CMD_WRITE_TO_DISPLAY = 0x11; // 17 + public static final byte CMD_CLEAR_UNIT = 0x40; // 64 + public static final byte CMD_CLEAR_UNIT_ALTERNATE = 0x20; // 32 + public static final byte CMD_CLEAR_FORMAT_TABLE = 0x50; // 80 + public static final byte CMD_READ_INPUT_FIELDS = 0x42; // 66 + public static final byte CMD_READ_MDT_FIELDS = 0x52; // 82 + public static final byte CMD_READ_MDT_IMMEDIATE_ALT = (byte)0x83; // 131 +// public static final byte CMD_READ_MDT_FIELDS_ALT = (byte)0x82; // 130 +// public static final byte CMD_READ_IMMEDIATE = 0x72; // 114 + public static final byte CMD_READ_SCREEN_IMMEDIATE = 0x62; // 98 + public static final byte CMD_WRITE_STRUCTURED_FIELD = (byte)243; // (byte)0xF3 -13 + public static final byte CMD_SAVE_SCREEN = 0x02; // 02 + public static final byte CMD_RESTORE_SCREEN = 0x12; // 18 + public static final byte CMD_WRITE_ERROR_CODE = 0x21; // 33 + public static final byte CMD_WRITE_ERROR_CODE_TO_WINDOW = 0x22; // 34 + public static final byte CMD_ROLL = 0x23; // 35 + public static final byte CMD_READ_SCREEN_TO_PRINT = (byte)0x66; // 102 + + // PLANES + public static final int PLANE_TEXT = 1; + public static final int PLANE_COLOR = 2; + public static final int PLANE_FIELD = 3; + public static final int PLANE_EXTENDED = 4; + public static final int PLANE_EXTENDED_GRAPHIC = 5; + public static final int PLANE_EXTENDED_FIELD = 6; + public static final int PLANE_ATTR = 7; + public static final int PLANE_IS_ATTR_PLACE = 8; + + // COLOR_BG + public static final char COLOR_BG_BLACK = 0; + public static final char COLOR_BG_BLUE = 1; + public static final char COLOR_BG_GREEN = 2; + public static final char COLOR_BG_CYAN = 3; + public static final char COLOR_BG_RED = 4; + public static final char COLOR_BG_MAGENTA = 5; + public static final char COLOR_BG_YELLOW = 6; + public static final char COLOR_BG_WHITE = 7; + + // COLOR_FG + public static final char COLOR_FG_BLACK = 0; + public static final char COLOR_FG_BLUE = 1; + public static final char COLOR_FG_GREEN = 2; + public static final char COLOR_FG_CYAN = 3; + public static final char COLOR_FG_RED = 4; + public static final char COLOR_FG_MAGENTA = 5; + public static final char COLOR_FG_YELLOW = 6; + public static final char COLOR_FG_WHITE = 7; + public static final char COLOR_FG_GRAY = 8; + public static final char COLOR_FG_LIGHT_BLUE = 9; + public static final char COLOR_FG_LIGHT_GREEN = 0xA; + public static final char COLOR_FG_LIGHT_CYAN = 0xB; + public static final char COLOR_FG_LIGHT_RED = 0xC; + public static final char COLOR_FG_LIGHT_MAGENTA = 0xD; + public static final char COLOR_FG_BROWN = 0xE; + public static final char COLOR_FG_WHITE_HIGH = 0xF; + + public static final int EXTENDED_5250_REVERSE = 0x10; + public static final int EXTENDED_5250_UNDERLINE = 0x08; + public static final int EXTENDED_5250_BLINK = 0x04; + public static final int EXTENDED_5250_COL_SEP = 0x02; + public static final int EXTENDED_5250_NON_DSP = 0x01; + + public static final char ATTR_32 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_GREEN & 0xff); + public static final char ATTR_33 = (COLOR_BG_GREEN << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_34 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_WHITE & 0xff); + public static final char ATTR_35 = (COLOR_BG_WHITE << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_36 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_GREEN & 0xff); + public static final char ATTR_37 = (COLOR_BG_GREEN << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_38 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_WHITE & 0xff); + public static final char ATTR_40 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_RED & 0xff); + public static final char ATTR_41 = (COLOR_BG_RED << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_42 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_RED & 0xff); + public static final char ATTR_43 = (COLOR_BG_RED << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + + public static final char ATTR_44 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_RED & 0xff); + public static final char ATTR_45 = (COLOR_BG_RED << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_46 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_RED & 0xff); + + public static final char ATTR_48 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_CYAN & 0xff); + public static final char ATTR_49 = (COLOR_BG_CYAN << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_50 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_YELLOW & 0xff); + + public static final char ATTR_51 = (COLOR_BG_YELLOW << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_52 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_CYAN & 0xff); + public static final char ATTR_53 = (COLOR_BG_CYAN << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_54 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_YELLOW & 0xff); + public static final char ATTR_56 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_MAGENTA & 0xff); + public static final char ATTR_57 = (COLOR_BG_MAGENTA << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_58 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_BLUE & 0xff); + public static final char ATTR_59 = (COLOR_BG_BLUE << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_60 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_MAGENTA & 0xff); + public static final char ATTR_61 = (COLOR_BG_MAGENTA << 8 & 0xff00) | + (COLOR_FG_BLACK & 0xff); + public static final char ATTR_62 = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_BLUE & 0xff); + + public static final int NO_GUI = 0; + public static final int UPPER_LEFT = 1; + public static final int UPPER = 2; + public static final int UPPER_RIGHT = 3; + public static final int GUI_LEFT = 4; + public static final int GUI_RIGHT = 5; + public static final int LOWER_LEFT = 6; + public static final int BOTTOM = 7; + public static final int LOWER_RIGHT = 8; + public static final int FIELD_LEFT = 9; + public static final int FIELD_RIGHT = 10; + public static final int FIELD_MIDDLE = 11; + public static final int FIELD_ONE = 12; + public static final int BUTTON_LEFT = 13; + public static final int BUTTON_RIGHT = 14; + public static final int BUTTON_MIDDLE = 15; + public static final int BUTTON_ONE = 16; + public static final int BUTTON_LEFT_UP = 17; + public static final int BUTTON_RIGHT_UP = 18; + public static final int BUTTON_MIDDLE_UP = 19; + public static final int BUTTON_ONE_UP = 20; + public static final int BUTTON_LEFT_DN = 21; + public static final int BUTTON_RIGHT_DN = 22; + public static final int BUTTON_MIDDLE_DN = 23; + public static final int BUTTON_ONE_DN = 24; + public static final int BUTTON_LEFT_EB = 25; + public static final int BUTTON_RIGHT_EB = 26; + public static final int BUTTON_MIDDLE_EB = 27; + public static final int BUTTON_SB_UP = 28; + public static final int BUTTON_SB_DN = 29; + public static final int BUTTON_SB_GUIDE = 30; + public static final int BUTTON_SB_THUMB = 31; + public static final int BUTTON_LAST = 31; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/AbstractCodePage.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,45 @@ +/** + * Title: CodePage.java + * Copyright: Copyright (c) 2001, 2002, 2003 + * Company: + * @author Kenneth J. Pouncey + * rewritten by LDC, WVL, Luc + * @version 0.4 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding; + +/** + * + * This class controls the translation from EBCDIC to ASCII and ASCII to EBCDIC + * + */ +public abstract class AbstractCodePage implements ICodePage { + + protected AbstractCodePage(String encoding) { + this.encoding = encoding; + } + + public String getEncoding() { + return encoding; + } + + protected String encoding; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/BuiltInCodePageFactory.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,156 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2012 + * Company: + * @author: master_jaf + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +import org.tn5250j.encoding.builtin.CCSID1025; +import org.tn5250j.encoding.builtin.CCSID1026; +import org.tn5250j.encoding.builtin.CCSID1112; +import org.tn5250j.encoding.builtin.CCSID1140; +import org.tn5250j.encoding.builtin.CCSID1141; +import org.tn5250j.encoding.builtin.CCSID1147; +import org.tn5250j.encoding.builtin.CCSID1148; +import org.tn5250j.encoding.builtin.CCSID273; +import org.tn5250j.encoding.builtin.CCSID277; +import org.tn5250j.encoding.builtin.CCSID278; +import org.tn5250j.encoding.builtin.CCSID280; +import org.tn5250j.encoding.builtin.CCSID284; +import org.tn5250j.encoding.builtin.CCSID285; +import org.tn5250j.encoding.builtin.CCSID297; +import org.tn5250j.encoding.builtin.CCSID37; +import org.tn5250j.encoding.builtin.CCSID424; +import org.tn5250j.encoding.builtin.CCSID500; +import org.tn5250j.encoding.builtin.CCSID870; +import org.tn5250j.encoding.builtin.CCSID871; +import org.tn5250j.encoding.builtin.CCSID875; +import org.tn5250j.encoding.builtin.ICodepageConverter; +import android.util.Log; + + +/** + * Methods for built-in code page support. + */ +class BuiltInCodePageFactory { + private static final String TAG = "BuiltInCodePageFactory"; + private static BuiltInCodePageFactory singleton; + + private final List<Class<?>> clazzes = new ArrayList<Class<?>>(); + + + private BuiltInCodePageFactory() { + register(); + } + + public static synchronized final BuiltInCodePageFactory getInstance() { + if (singleton == null) { + singleton = new BuiltInCodePageFactory(); + } + + return singleton; + } + + private void register() { + clazzes.add(CCSID37.class); + clazzes.add(CCSID273.class); + clazzes.add(CCSID277.class); + clazzes.add(CCSID278.class); + clazzes.add(CCSID280.class); + clazzes.add(CCSID284.class); + clazzes.add(CCSID285.class); + clazzes.add(CCSID297.class); + clazzes.add(CCSID424.class); + clazzes.add(CCSID500.class); + clazzes.add(CCSID870.class); + clazzes.add(CCSID871.class); + clazzes.add(CCSID875.class); + clazzes.add(CCSID1025.class); + clazzes.add(CCSID1026.class); + clazzes.add(CCSID1112.class); + clazzes.add(CCSID1140.class); + clazzes.add(CCSID1141.class); + clazzes.add(CCSID1147.class); + clazzes.add(CCSID1148.class); + } + + /** + * @return unsorted list of available code pages + */ + public String[] getAvailableCodePages() { + HashSet<String> cpset = new HashSet<String>(); + + for (Class<?> clazz : clazzes) { + final ICodepageConverter converter = getConverterFromClassName(clazz); + + if (converter != null) { + cpset.add(converter.getName()); + } + } + + return cpset.toArray(new String[cpset.size()]); + } + + /** + * @param encoding + * @return an {@link ICodePage} object OR null, of not found + */ + public ICodePage getCodePage(String encoding) { + for (Class<?> clazz : clazzes) { + final ICodepageConverter converter = getConverterFromClassName(clazz); + + if (converter != null && converter.getName().equals(encoding)) { + return converter; + } + } + + return null; + } + + /** + * Lazy loading converters takes time, + * but doesn't happen so often and saves memory. + * + * @param clazz {@link ICodepageConverter} + * @return + */ + private ICodepageConverter getConverterFromClassName(Class<?> clazz) { + try { + final Constructor<?> constructor = clazz.getConstructor(new Class[0]); + final ICodepageConverter converter = (ICodepageConverter) constructor.newInstance(); + converter.init(); + return converter; + } + catch (Exception e) { + Log.e(TAG, "Couldn't load code page converter class:" + clazz.getCanonicalName(), e); + return null; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/CharMappings.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,91 @@ +/** + * Title: CharMappings.java + * Copyright: Copyright (c) 2001,2002,2003 + * Company: + * @author Kenneth J. Pouncey + * rewritten by LDC, WVL, Luc + * @version 0.4 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +/** + * Character Mappings for EBCDIC to ASCII and ASCII to EBCDIC translations + */ +public class CharMappings { + + public static final String DFT_ENC = "37"; + public static final int NATIVE_CP = 0; + public static final int TOOLBOX_CP = 1; + + private static final HashMap<String, ICodePage> map = new HashMap<String, ICodePage>(); + + public static String[] getAvailableCodePages() { + Set<String> cpset = new HashSet<String>(); // no double entries + + for (String cp : BuiltInCodePageFactory.getInstance().getAvailableCodePages()) { + cpset.add(cp); + } + + for (String cp : ToolboxCodePageFactory.getInstance().getAvailableCodePages()) { + cpset.add(cp); + } + + String[] cparray = cpset.toArray(new String[cpset.size()]); + Arrays.sort(cparray); + return cparray; + } + + public static ICodePage getCodePage(String encoding) { + if (map.containsKey(encoding)) { + return map.get(encoding); + } + + ICodePage cp = BuiltInCodePageFactory.getInstance().getCodePage(encoding); + + if (cp != null) { + map.put(encoding, cp); + return cp; + } + + cp = ToolboxCodePageFactory.getInstance().getCodePage(encoding); + + if (cp != null) { + map.put(encoding, cp); + return cp; + } + + cp = JavaCodePageFactory.getCodePage(encoding); + + if (cp != null) { + map.put(encoding, cp); + return cp; + } + + // unsupported codepage ==> return default + return BuiltInCodePageFactory.getInstance().getCodePage(DFT_ENC); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/ICodePage.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,22 @@ +package org.tn5250j.encoding; + +public interface ICodePage { + + /** + * Convert a single byte (or maybe more bytes which representing one character) to a Unicode character. + * + * @param index + * @return + */ + public abstract char ebcdic2uni(int index); + + /** + * Convert a Unicode character in it's byte representation. + * Therefore, only 8bit codepages are supported. + * + * @param index + * @return + */ + public abstract byte uni2ebcdic(char index); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/JavaCodePageFactory.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,98 @@ +/** + * Title: JavaCodePage + * Copyright: Copyright (c) 2001, 2002, 2003 + * Company: + * @author LDC, WVL, Luc, master_jaf + * @version 0.4 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; + +/* package */ class JavaCodePageFactory extends AbstractCodePage { + + private final CharsetEncoder encoder; + private final CharsetDecoder decoder; + + /* package */ JavaCodePageFactory(String encoding, CharsetEncoder encoder, CharsetDecoder decoder) { + super(encoding); + this.encoder = encoder; + this.decoder = decoder; + } + + /* (non-Javadoc) + * @see org.tn5250j.encoding.CodePage#ebcdic2uni(int) + */ + public char ebcdic2uni(int codepoint) { + try { + final ByteBuffer in = ByteBuffer.wrap(new byte[] { (byte) codepoint }); + final CharBuffer out = this.decoder.decode(in); + return out.get(0); + } + catch (Exception cce) { + return ' '; + } + } + + /* (non-Javadoc) + * @see org.tn5250j.encoding.CodePage#uni2ebcdic(char) + */ + public byte uni2ebcdic(char character) { + try { + final CharBuffer in = CharBuffer.wrap(new char[] {character}); + final ByteBuffer out = this.encoder.encode(in); + return out.get(0); + } + catch (Exception cce) { + return 0x0; + } + } + + /** + * @param encoding + * @return A new {@link CodePage} object OR null, if not available. + */ + /* package */ static ICodePage getCodePage(final String encoding) { + CharsetDecoder dec = null; + CharsetEncoder enc = null; + + try { + final Charset cs = java.nio.charset.Charset.forName(encoding); + dec = cs.newDecoder(); + enc = cs.newEncoder(); + } + catch (Exception e) { + enc = null; + dec = null; + } + + if ((enc != null) && (dec != null)) { + return new JavaCodePageFactory(encoding, enc, dec); + } + + return null; + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/ToolboxCodePageFactory.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,164 @@ +/** + * Title: ToolboxCodePage + * Copyright: Copyright (c) 2001, 2002, 2003 + * Company: + * @author Kenneth J. Pouncey + * rewritten by LDC, WVL, Luc + * @version 0.4 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import android.util.Log; + + +class ToolboxCodePageFactory { + private static final String TAG = "ToolboxCodePageFactory"; + private final static String[] CODEPAGES = { "Big5", "Cp037", "Cp273", "Cp277", "Cp278", + "Cp280", "Cp284", "Cp285", "Cp297", "Cp420", "Cp424", "Cp437", + "Cp500", "Cp737", "Cp775", "Cp838", "Cp850", "Cp852", "Cp855", + "Cp856", "Cp857", "Cp858", "Cp860", "Cp861", "Cp862", "Cp863", + "Cp864", "Cp865", "Cp866", "Cp868", "Cp869", "Cp870", + "Cp871", "Cp874", "Cp875", "Cp918", "Cp921", "Cp922", + "Cp923", // IBM Latin-9. + "Cp930", "Cp933", "Cp935", "Cp937", "Cp939", "Cp942", "Cp943", + "Cp948", "Cp949", "Cp950", "Cp964", "Cp970", "Cp1006", "Cp1025", + "Cp1026", "Cp1046", "Cp1097", "Cp1098", "Cp1112", "Cp1122", + "Cp1123", "Cp1124", "Cp1140", "Cp1141", "Cp1142", "Cp1143", + "Cp1144", "Cp1145", "Cp1146", "Cp1147", "Cp1148", "Cp1149", + "Cp1252", "Cp1250", "Cp1251", "Cp1253", "Cp1254", "Cp1255", + "Cp1256", "Cp1257", "Cp1258", "Cp1381", "Cp1383", "Cp33722" + }; + + private static final String CONVERTER_NAME = "com.ibm.as400.access.CharConverter"; + private static final String TOBYTES_NAME = "stringToByteArray"; + private static final String TOSTRING_NAME = "byteArrayToString"; + + private static ToolboxCodePageFactory singleton; + + + + private ToolboxCodePageFactory() { + /* private for singleton */ + } + + public static synchronized ToolboxCodePageFactory getInstance() { + if (singleton == null) { + singleton = new ToolboxCodePageFactory(); + } + + return singleton; + } + + /** + * @return + */ + public String[] getAvailableCodePages() { + try { + final ClassLoader loader = getClassLoader(); + Class.forName(CONVERTER_NAME, false, loader); + return CODEPAGES; + } + catch (Exception e) { + Log.i(TAG, "Couldn't locate JT400 Toolbox in classpath. Charset converters can't be used."); + return new String[0]; + } + } + + /** + * @param encoding + * @return + */ + public ICodePage getCodePage(String encoding) { + try { + ClassLoader loader = getClassLoader(); + Class<?> conv_class = Class.forName(CONVERTER_NAME, true, loader); + Constructor<?> conv_constructor = conv_class.getConstructor(new Class[] { String.class }); + Method toBytes_method = conv_class.getMethod(TOBYTES_NAME, new Class[] { String.class }); + Method toString_method = conv_class.getMethod(TOSTRING_NAME, new Class[] { byte[].class }); + Object convobj = conv_constructor.newInstance(new Object[] { encoding }); + return new ToolboxConverterProxy(convobj, toBytes_method, toString_method); + } + catch (Exception e) { + Log.w(TAG, "Can't load charset converter from JT400 Toolbox for code page " + encoding, e); + return null; + } + } + + private static final ClassLoader getClassLoader() { + ClassLoader loader = ToolboxCodePageFactory.class.getClassLoader(); + + if (loader == null) { + loader = ClassLoader.getSystemClassLoader(); + } + + return loader; + } + + private static class ToolboxConverterProxy implements ICodePage { + + private final Object converter; + private final Method tobytesMethod; + private final Method tostringMethod; + + private ToolboxConverterProxy(Object converterObject, Method tobytesMethod, Method tostringMethod) { + super(); + this.converter = converterObject; + this.tobytesMethod = tobytesMethod; + this.tostringMethod = tostringMethod; + } + + public char ebcdic2uni(int index) { + Object result; + + try { + result = tostringMethod.invoke(converter, new Object[] { new byte[] { (byte)(index & 0xFF) } }); + } + catch (Throwable t) { + result = null; + } + + if (result == null) + return 0x00; + + return ((String) result).charAt(0); + } + + public byte uni2ebcdic(char index) { + Object result; + + try { + result = tobytesMethod.invoke(converter, new Object[] { new String(new char[] { index }) }); + } + catch (Throwable t) { + result = null; + } + + if (result == null) + return 0x00; + + return ((byte[]) result)[0]; + } + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID1025.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 1025<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1025.jsp + */ +public final class CCSID1025 extends CodepageConverterAdapter { + + public final static String NAME = "1025"; + public final static String DESCR = "Cyrillic Multilingual"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u0452', + '\u0453', '\u0451', '\u0454', '\u0455', '\u0456', '\u0457', + '\u0458', '[', '.', '<', '(', '+', '!', '&', '\u0459', '\u045A', + '\u045B', '\u045C', '\u045E', '\u045F', '\u042A', '\u2116', + '\u0402', ']', '$', '*', ')', ';', '^', '-', '/', '\u0403', + '\u0401', '\u0404', '\u0405', '\u0406', '\u0407', '\u0408', + '\u0409', '|', ',', '%', '_', '>', '?', '\u040A', '\u040B', + '\u040C', '\u00AD', '\u040E', '\u040F', '\u044E', '\u0430', + '\u0431', '`', ':', '#', '@', '\'', '=', '"', '\u0446', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u0434', '\u0435', '\u0444', + '\u0433', '\u0445', '\u0438', '\u0439', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', '\u043A', '\u043B', '\u043C', '\u043D', + '\u043E', '\u043F', '\u044F', '~', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '\u0440', '\u0441', '\u0442', '\u0443', '\u0436', + '\u0432', '\u044C', '\u044B', '\u0437', '\u0448', '\u044D', + '\u0449', '\u0447', '\u044A', '\u042E', '\u0410', '\u0411', + '\u0426', '\u0414', '\u0415', '\u0424', '\u0413', '{', 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u0425', '\u0418', '\u0419', + '\u041A', '\u041B', '\u041C', '}', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', '\u041D', '\u041E', '\u041F', '\u042F', '\u0420', + '\u0421', '\\', '\u00A7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '\u0422', '\u0423', '\u0416', '\u0412', '\u042C', '\u042B', '0', + '1', '2', '3', '4', '5', '6', '7', '8', '9', '\u0417', '\u0428', + '\u042D', '\u0429', '\u0427', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID1026.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 1026<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1026.jsp + */ +public final class CCSID1026 extends CodepageConverterAdapter { + + public final static String NAME = "1026"; + public final static String DESCR = "Turkey Latin 5"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '{', '\u00F1', + '\u00C7', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', + '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', + '\u00DF', '\u011E', '\u0130', '*', ')', ';', '^', '-', '/', + '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', '[', + '\u00D1', '\u015F', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', + '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', + '\u00CC', '\u0131', ':', '\u00D6', '\u015E', '\'', '=', '\u00DC', + '\u00D8', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', + '\u00BB', '}', '`', '\u00A6', '\u00B1', '\u00B0', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', + '\u00B8', '\u00C6', '\u00A4', '\u00B5', '\u00F6', 's', 't', 'u', + 'v', 'w', 'x', 'y', 'z', '\u00A1', '\u00BF', ']', '$', '@', + '\u00AE', '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', + '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', + '\u00AF', '\u00A8', '\u00B4', '\u00D7', '\u00E7', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '~', '\u00F2', + '\u00F3', '\u00F5', '\u011F', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', '\u00B9', '\u00FB', '\\', '\u00F9', '\u00FA', '\u00FF', + '\u00FC', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '\u00B2', '\u00D4', '#', '\u00D2', '\u00D3', '\u00D5', '0', '1', + '2', '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '"', + '\u00D9', '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID1112.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 1112<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1112.jsp + */ +public final class CCSID1112 extends CodepageConverterAdapter { + + public final static String NAME = "1112"; + public final static String DESCR = "Baltic, Multilingual"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u0161', + '\u00E4', '\u0105', '\u012F', '\u016B', '\u00E5', '\u0113', + '\u017E', '\u00A2', '.', '<', '(', '+', '|', '&', '\u00E9', + '\u0119', '\u0117', '\u010D', '\u0173', '\u201E', '\u201C', + '\u0123', '\u00DF', '!', '$', '*', ')', ';', '\u00AC', '-', '/', + '\u0160', '\u00C4', '\u0104', '\u012E', '\u016A', '\u00C5', + '\u0112', '\u017D', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', + '\u00C9', '\u0118', '\u0116', '\u010C', '\u0172', '\u012A', + '\u013B', '\u0122', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', + '\u0101', '\u017C', '\u0144', '\u00B1', '\u00B0', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', '\u0156', '\u0157', '\u00E6', + '\u0137', '\u00C6', '\u00A4', '\u00B5', '~', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '\u201D', '\u017A', '\u0100', '\u017B', + '\u0143', '\u00AE', '^', '\u00A3', '\u012B', '\u00B7', '\u00A9', + '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '[', ']', + '\u0179', '\u0136', '\u013C', '\u00D7', '{', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u014D', '\u00F6', '\u0146', + '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', '\u00B9', '\u0107', '\u00FC', '\u0142', '\u015B', '\u2019', + '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u014C', '\u00D6', '\u0145', '\u00D3', '\u00D5', '0', '1', '2', + '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u0106', '\u00DC', + '\u0141', '\u015A', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID1140.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 1140<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1140.jsp + */ +public final class CCSID1140 extends CodepageConverterAdapter { + + public final static String NAME = "1140"; + public final static String DESCR = "ECECP: USA, Canada, Netherlands, Portugal, Brazil, Australia, New Zealand"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', + '\u00F1', '\u00A2', '.', '<', '(', '+', '|', '&', '\u00E9', + '\u00EA', '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', + '\u00EC', '\u00DF', '!', '$', '*', ')', ';', '\u00AC', '-', '/', + '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', + '\u00C7', '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', + '\u00C9', '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', + '\u00CF', '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', + '\u00F0', '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', + '\u00B8', '\u00C6', '\u20AC', '\u00B5', '~', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', + '\u00DE', '\u00AE', '^', '\u00A3', '\u00A5', '\u00B7', '\u00A9', + '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '[', ']', + '\u00AF', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', + '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', + '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', + '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', + '\u00D9', '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID1141.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 1141<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1141.jsp + */ +public final class CCSID1141 extends CodepageConverterAdapter { + + public final static String NAME = "1141"; + public final static String DESCR = "ECECP: Austria, Germany"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '{', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', '\u00F1', + '\u00C4', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', + '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '~', + '\u00DC', '$', '*', ')', ';', '^', '-', '/', '\u00C2', '[', + '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', + '\u00F6', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', + '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '`', + ':', '#', '\u00A7', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', + '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', + '\u20AC', '\u00B5', '\u00DF', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', + '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '@', '\u00B6', + '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', + '\u00B4', '\u00D7', '\u00E4', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', '\u00AD', '\u00F4', '\u00A6', '\u00F2', '\u00F3', + '\u00F5', '\u00FC', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + '\u00B9', '\u00FB', '}', '\u00F9', '\u00FA', '\u00FF', '\u00D6', + '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '\\', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', ']', '\u00D9', + '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID1147.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 1147<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1147.jsp + */ +public final class CCSID1147 extends CodepageConverterAdapter { + + public final static String NAME = "1147"; + public final static String DESCR = "ECECP: France"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '@', '\u00E1', '\u00E3', '\u00E5', '\\', '\u00F1', + '\u00B0', '.', '<', '(', '+', '!', '&', '{', '\u00EA', '\u00EB', + '}', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '\u00DF', '\u00A7', + '$', '*', ')', ';', '^', '-', '/', '\u00C2', '\u00C4', '\u00C0', + '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', '\u00F9', ',', + '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', '\u00CB', + '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00B5', ':', + '\u00A3', '\u00E0', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', + '\u00FE', '\u00B1', '[', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', '\u20AC', + '`', '\u00A8', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\u00A1', + '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', '\u00A2', '#', + '\u00A5', '\u00B7', '\u00A9', ']', '\u00B6', '\u00BC', '\u00BD', + '\u00BE', '\u00AC', '|', '\u00AF', '~', '\u00B4', '\u00D7', + '\u00E9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', + '\u00F4', '\u00F6', '\u00F2', '\u00F3', '\u00F5', '\u00E8', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', '\u00B9', '\u00FB', + '\u00FC', '\u00A6', '\u00FA', '\u00FF', '\u00E7', '\u00F7', 'S', + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', '\u00D4', '\u00D6', + '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', '\u00D9', '\u00DA', + '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID1148.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 1148<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1148.jsp + */ +public final class CCSID1148 extends CodepageConverterAdapter { + + public final static String NAME = "1148"; + public final static String DESCR = "ECECP: International 1"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', + '\u00F1', '[', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', + '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', + '\u00DF', ']', '$', '*', ')', ';', '^', '-', '/', '\u00C2', + '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', + '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', + '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', + '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', + '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', + '\u00C6', '\u20AC', '\u00B5', '~', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', + '\u00AE', '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', + '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', + '\u00AF', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', + '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', + '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', + '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', + '\u00D9', '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID273.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,98 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 273<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid273.jsp + */ +public final class CCSID273 extends CodepageConverterAdapter { + + public final static String NAME = "273"; + public final static String DESCR = "CECP: Austria, Germany"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '{', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', '\u00F1', + '\u00C4', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', + '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '~', + '\u00DC', '$', '*', ')', ';', '^', '-', '/', '\u00C2', '[', + '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', + '\u00F6', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', + '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '`', + ':', '#', '\u00A7', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', + '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', + '\u00A4', '\u00B5', '\u00DF', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', + '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '@', '\u00B6', + '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', + '\u00B4', '\u00D7', '\u00E4', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', '\u00AD', '\u00F4', '\u00A6', '\u00F2', '\u00F3', + '\u00F5', '\u00FC', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + '\u00B9', '\u00FB', '}', '\u00F9', '\u00FA', '\u00FF', '\u00D6', + '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '\\', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', ']', '\u00D9', + '\u00DA', '\u009F', + }; + + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID277.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 277<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid277.jsp + */ +public final class CCSID277 extends CodepageConverterAdapter { + + public final static String NAME = "277"; + public final static String DESCR = "CECP: Denmark, Norway"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u00E0', '\u00E1', '\u00E3', '}', '\u00E7', '\u00F1', + '#', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', '\u00EB', + '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '\u00DF', + '\u00A4', '\u00C5', '*', ')', ';', '^', '-', '/', '\u00C2', + '\u00C4', '\u00C0', '\u00C1', '\u00C3', '$', '\u00C7', '\u00D1', + '\u00F8', ',', '%', '_', '>', '?', '\u00A6', '\u00C9', '\u00CA', + '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '`', + ':', '\u00C6', '\u00D8', '\'', '=', '"', '@', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', + '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', '\u00AA', '\u00BA', '{', '\u00B8', '[', ']', '\u00B5', + '\u00FC', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\u00A1', + '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', '\u00A2', + '\u00A3', '\u00A5', '\u00B7', '\u00A9', '\u00A7', '\u00B6', + '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', + '\u00B4', '\u00D7', '\u00E6', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', '\u00F3', + '\u00F5', '\u00E5', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + '\u00B9', '\u00FB', '~', '\u00F9', '\u00FA', '\u00FF', '\\', + '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', + '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', + '\u00D9', '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID278.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 278<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid278.jsp + */ +public final class CCSID278 extends CodepageConverterAdapter { + + public final static String NAME = "278"; + public final static String DESCR = "CECP: Finland, Sweden"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '{', '\u00E0', '\u00E1', '\u00E3', '}', '\u00E7', '\u00F1', + '\u00A7', '.', '<', '(', '+', '!', '&', '`', '\u00EA', '\u00EB', + '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '\u00DF', + '\u00A4', '\u00C5', '*', ')', ';', '^', '-', '/', '\u00C2', '#', + '\u00C0', '\u00C1', '\u00C3', '$', '\u00C7', '\u00D1', '\u00F6', + ',', '%', '_', '>', '?', '\u00F8', '\\', '\u00CA', '\u00CB', + '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00E9', ':', + '\u00C4', '\u00D6', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', + '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', ']', + '\u00B5', '\u00FC', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', + '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '[', '\u00B6', + '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', + '\u00B4', '\u00D7', '\u00E4', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', '\u00AD', '\u00F4', '\u00A6', '\u00F2', '\u00F3', + '\u00F5', '\u00E5', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + '\u00B9', '\u00FB', '~', '\u00F9', '\u00FA', '\u00FF', '\u00C9', + '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '@', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', + '\u00D9', '\u00DA', '\u009F' + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID280.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 280<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid280.jsp + */ +public final class CCSID280 extends CodepageConverterAdapter { + + public final static String NAME = "280"; + public final static String DESCR = "CECP: Italy"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '{', '\u00E1', '\u00E3', '\u00E5', '\\', '\u00F1', + '\u00B0', '.', '<', '(', '+', '!', '&', ']', '\u00EA', '\u00EB', + '}', '\u00ED', '\u00EE', '\u00EF', '~', '\u00DF', '\u00E9', '$', + '*', ')', ';', '^', '-', '/', '\u00C2', '\u00C4', '\u00C0', + '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', '\u00F2', ',', + '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', '\u00CB', + '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00F9', ':', + '\u00A3', '\u00A7', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', + '\u00FE', '\u00B1', '[', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', '\u00A4', + '\u00B5', '\u00EC', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', + '\u00A2', '#', '\u00A5', '\u00B7', '\u00A9', '@', '\u00B6', + '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', + '\u00B4', '\u00D7', '\u00E0', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00A6', '\u00F3', + '\u00F5', '\u00E8', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + '\u00B9', '\u00FB', '\u00FC', '`', '\u00FA', '\u00FF', '\u00E7', + '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', + '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', + '\u00D9', '\u00DA', '\u009F' + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID284.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 284<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid284.jsp + */ +public final class CCSID284 extends CodepageConverterAdapter { + + public final static String NAME = "284"; + public final static String DESCR = "CECP: Spain, Latin America (Spanish)"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', + '\u00A6', '[', '.', '<', '(', '+', '|', '&', '\u00E9', '\u00EA', + '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', + '\u00DF', ']', '$', '*', ')', ';', '\u00AC', '-', '/', '\u00C2', + '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', '#', + '\u00F1', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', + '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '`', + ':', '\u00D1', '@', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', + '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', + '\u00A4', '\u00B5', '\u00A8', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', + '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '\u00A7', + '\u00B6', '\u00BC', '\u00BD', '\u00BE', '^', '!', '\u00AF', '~', + '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', '\u00F3', '\u00F5', + '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', '\u00B9', + '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', '\\', '\u00F7', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', '\u00D4', + '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', '4', + '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', '\u00D9', + '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID285.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 285<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid285.jsp + */ +public final class CCSID285 extends CodepageConverterAdapter { + + public final static String NAME = "285"; + public final static String DESCR = "CECP: United Kingdom"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', + '\u00F1', '$', '.', '<', '(', '+', '|', '&', '\u00E9', '\u00EA', + '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', + '\u00DF', '!', '\u00A3', '*', ')', ';', '\u00AC', '-', '/', + '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', + '\u00C7', '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', + '\u00C9', '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', + '\u00CF', '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', + '\u00F0', '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', + '\u00B8', '\u00C6', '\u00A4', '\u00B5', '\u00AF', 's', 't', 'u', + 'v', 'w', 'x', 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', + '\u00DE', '\u00AE', '\u00A2', '[', '\u00A5', '\u00B7', '\u00A9', + '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '^', ']', '~', + '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', '\u00F3', + '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', '\\', + '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', + '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', + '\u00D9', '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID297.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 297<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid297.jsp + */ +public final class CCSID297 extends CodepageConverterAdapter { + + public final static String NAME = "297"; + public final static String DESCR = "CECP: France"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '@', '\u00E1', '\u00E3', '\u00E5', '\\', '\u00F1', + '\u00B0', '.', '<', '(', '+', '!', '&', '{', '\u00EA', '\u00EB', + '}', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '\u00DF', '\u00A7', + '$', '*', ')', ';', '^', '-', '/', '\u00C2', '\u00C4', '\u00C0', + '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', '\u00F9', ',', + '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', '\u00CB', + '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00B5', ':', + '\u00A3', '\u00E0', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', + '\u00FE', '\u00B1', '[', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', '\u00A4', + '`', '\u00A8', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\u00A1', + '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', '\u00A2', '#', + '\u00A5', '\u00B7', '\u00A9', ']', '\u00B6', '\u00BC', '\u00BD', + '\u00BE', '\u00AC', '|', '\u00AF', '~', '\u00B4', '\u00D7', + '\u00E9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', + '\u00F4', '\u00F6', '\u00F2', '\u00F3', '\u00F5', '\u00E8', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', '\u00B9', '\u00FB', + '\u00FC', '\u00A6', '\u00FA', '\u00FF', '\u00E7', '\u00F7', 'S', + 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', '\u00D4', '\u00D6', + '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', '\u00D9', '\u00DA', + '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID37.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,99 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 37<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid37.jsp + */ +public final class CCSID37 extends CodepageConverterAdapter { + + public final static String NAME = "37"; + public final static String DESCR = "CECP: USA, Canada (ESA*), Netherlands, Portugal, Brazil, Australia, New Zealand"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', + '\u00F1', '\u00A2', '.', '<', '(', '+', '|', '&', '\u00E9', + '\u00EA', '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', + '\u00EC', '\u00DF', '!', '$', '*', ')', ';', '\u00AC', '-', '/', + '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', + '\u00C7', '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', + '\u00C9', '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', + '\u00CF', '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', + '\u00F0', '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', + '\u00B8', '\u00C6', '\u00A4', '\u00B5', '~', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', + '\u00DE', '\u00AE', '^', '\u00A3', '\u00A5', '\u00B7', '\u00A9', + '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '[', ']', + '\u00AF', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', + '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', + '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', + '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', + '\u00D9', '\u00DA', '\u009F', + }; + + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID424.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 424<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid424.jsp + */ +public final class CCSID424 extends CodepageConverterAdapter { + + public final static String NAME = "424"; + public final static String DESCR = "Hebrew"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u05D0', '\u05D1', + '\u05D2', '\u05D3', '\u05D4', '\u05D5', '\u05D6', '\u05D7', + '\u05D8', '\u00A2', '.', '<', '(', '+', '|', '&', '\u05D9', + '\u05DA', '\u05DB', '\u05DC', '\u05DD', '\u05DE', '\u05DF', + '\u05E0', '\u05E1', '!', '$', '*', ')', ';', '\u00AC', '-', '/', + '\u05E2', '\u05E3', '\u05E4', '\u05E5', '\u05E6', '\u05E7', + '\u05E8', '\u05E9', '\u00A6', ',', '%', '_', '>', '?', '\u001A', + '\u05EA', '\u001A', '\u001A', '\u00A0', '\u001A', '\u001A', + '\u001A', '\u2017', '`', ':', '#', '@', '\'', '=', '"', '\u001A', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', + '\u001A', '\u001A', '\u001A', '\u00B1', '\u00B0', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', '\u001A', '\u001A', '\u20AC', + '\u00B8', '\u20AA', '\u00A4', '\u00B5', '~', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '\u001A', '\u001A', '\u001A', '\u001A', + '\u001A', '\u00AE', '^', '\u00A3', '\u00A5', '\u2022', '\u00A9', + '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '[', ']', + '\u203E', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u001A', '\u001A', '\u001A', + '\u001A', '\u001A', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', '\u00B9', '\u202D', '\u202E', '\u202C', '\u001A', '\u001A', + '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u001A', '\u001A', '\u001A', '\u001A', '\u001A', '0', '1', '2', + '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u202A', '\u202B', + '\u200E', '\u200F', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID500.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 500<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid500.jsp + */ +public final class CCSID500 extends CodepageConverterAdapter { + + public final static String NAME = "500"; + public final static String DESCR = "CECP: Belgium, Canada (AS/400*), Switzerland, International Latin-1"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', + '\u00F1', '[', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', + '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', + '\u00DF', ']', '$', '*', ')', ';', '^', '-', '/', '\u00C2', + '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', + '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', + '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', + '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', + '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', + '\u00C6', '\u00A4', '\u00B5', '~', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', + '\u00AE', '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', + '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', + '\u00AF', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', + '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', + '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', + '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', + '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', + '\u00D9', '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID870.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 870<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid870.jsp + */ +public final class CCSID870 extends CodepageConverterAdapter { + + public final static String NAME = "870"; + public final static String DESCR = "Latin 2 - EBCDIC Multilingual"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u0163', '\u00E1', '\u0103', '\u010D', '\u00E7', + '\u0107', '[', '.', '<', '(', '+', '!', '&', '\u00E9', '\u0119', + '\u00EB', '\u016F', '\u00ED', '\u00EE', '\u013E', '\u013A', + '\u00DF', ']', '$', '*', ')', ';', '^', '-', '/', '\u00C2', + '\u00C4', '\u02DD', '\u00C1', '\u0102', '\u010C', '\u00C7', + '\u0106', '|', ',', '%', '_', '>', '?', '\u02C7', '\u00C9', + '\u0118', '\u00CB', '\u016E', '\u00CD', '\u00CE', '\u013D', + '\u0139', '`', ':', '#', '@', '\'', '=', '"', '\u02D8', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u015B', '\u0148', '\u0111', + '\u00FD', '\u0159', '\u015F', '\u00B0', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', '\u0142', '\u0144', '\u0161', '\u00B8', + '\u02DB', '\u00A4', '\u0105', '~', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '\u015A', '\u0147', '\u0110', '\u00DD', '\u0158', + '\u015E', '\u02D9', '\u0104', '\u017C', '\u0162', '\u017B', + '\u00A7', '\u017E', '\u017A', '\u017D', '\u0179', '\u0141', + '\u0143', '\u0160', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', + '\u0155', '\u00F3', '\u0151', '}', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', '\u011A', '\u0171', '\u00FC', '\u0165', '\u00FA', + '\u011B', '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '\u010F', '\u00D4', '\u00D6', '\u0154', '\u00D3', '\u0150', '0', + '1', '2', '3', '4', '5', '6', '7', '8', '9', '\u010E', '\u0170', + '\u00DC', '\u0164', '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID871.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 871<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid871.jsp + */ +public final class CCSID871 extends CodepageConverterAdapter { + + public final static String NAME = "871"; + public final static String DESCR = "CECP: Iceland"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', + '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', + '\u00F1', '\u00DE', '.', '<', '(', '+', '!', '&', '\u00E9', + '\u00EA', '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', + '\u00EC', '\u00DF', '\u00C6', '$', '*', ')', ';', '\u00D6', '-', + '/', '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', + '\u00C7', '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', + '\u00C9', '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', + '\u00CF', '\u00CC', '\u00F0', ':', '#', '\u00D0', '\'', '=', '"', + '\u00D8', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', + '\u00BB', '`', '\u00FD', '{', '\u00B1', '\u00B0', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '}', '\u00B8', + ']', '\u00A4', '\u00B5', '\u00F6', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '\u00A1', '\u00BF', '@', '\u00DD', '[', '\u00AE', + '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '\u00A7', + '\u00B6', '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', + '\u00A8', '\\', '\u00D7', '\u00FE', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', '\u00AD', '\u00F4', '~', '\u00F2', '\u00F3', + '\u00F5', '\u00E6', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', + '\u00B4', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '\u00B2', '\u00D4', '^', '\u00D2', '\u00D3', '\u00D5', '0', '1', + '2', '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', + '\u00DC', '\u00D9', '\u00DA', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CCSID875.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,96 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * Alternative (extended) implementation of a codepage converter CCSID 875<->Unicode. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +/** + * @author master_jaf + * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid875.jsp + */ +public final class CCSID875 extends CodepageConverterAdapter { + + public final static String NAME = "875"; + public final static String DESCR = "Greek"; + + /* + * Char maps manually extracted from JTOpen v6.4. Because char maps can't be + * covered by any license, this should legal. + */ + private static final char[] codepage = { '\u0000', '\u0001', '\u0002', + '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', + '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', + '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', + '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', + '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', + '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', + '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', + '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', + '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', + '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u0391', '\u0392', + '\u0393', '\u0394', '\u0395', '\u0396', '\u0397', '\u0398', + '\u0399', '[', '.', '<', '(', '+', '!', '&', '\u039A', '\u039B', + '\u039C', '\u039D', '\u039E', '\u039F', '\u03A0', '\u03A1', + '\u03A3', ']', '$', '*', ')', ';', '^', '-', '/', '\u03A4', + '\u03A5', '\u03A6', '\u03A7', '\u03A8', '\u03A9', '\u03AA', + '\u03AB', '|', ',', '%', '_', '>', '?', '\u00A8', '\u0386', + '\u0388', '\u0389', '\u00A0', '\u038A', '\u038C', '\u038E', + '\u038F', '`', ':', '#', '@', '\'', '=', '"', '\u0385', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u03B1', '\u03B2', '\u03B3', + '\u03B4', '\u03B5', '\u03B6', '\u00B0', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', '\u03B7', '\u03B8', '\u03B9', '\u03BA', + '\u03BB', '\u03BC', '\u00B4', '~', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '\u03BD', '\u03BE', '\u03BF', '\u03C0', '\u03C1', + '\u03C3', '\u00A3', '\u03AC', '\u03AD', '\u03AE', '\u03CA', + '\u03AF', '\u03CC', '\u03CD', '\u03CB', '\u03CE', '\u03C2', + '\u03C4', '\u03C5', '\u03C6', '\u03C7', '\u03C8', '{', 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u03C9', '\u0390', + '\u03B0', '\u2018', '\u2015', '}', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', '\u00B1', '\u00BD', '\u001A', '\u0387', '\u2019', + '\u00A6', '\\', '\u001A', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '\u00B2', '\u00A7', '\u001A', '\u001A', '\u00AB', '\u00AC', '0', + '1', '2', '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00A9', + '\u001A', '\u001A', '\u00BB', '\u009F', + }; + + public String getName() { + return NAME; + } + + public String getDescription() { + return DESCR; + } + + public String getEncoding() { + return NAME; + } + + @Override + protected char[] getCodePage() { + return codepage; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/CodepageConverterAdapter.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,85 @@ +/** + * $Id$ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.encoding.builtin; + +import java.util.Arrays; + +/** + * Adapter class for converters using 8bit codepages. + * + * @author master_jaf + */ +public abstract class CodepageConverterAdapter implements ICodepageConverter { + + private char[] codepage = null; + private int[] reverse_codepage = null; + + /* (non-Javadoc) + * @see org.tn5250j.cp.ICodepageConverter#init() + */ + public ICodepageConverter init() { + codepage = getCodePage(); + int size = 0; + + for (int i = 0; i < codepage.length; i++) { + size = Math.max(size, codepage[i]); + } + + assert(size + 1) < 1024 * 1024; // some kind of maximum size limiter. + reverse_codepage = new int[size + 1]; + Arrays.fill(reverse_codepage, '?'); + + for (int i = 0; i < codepage.length; i++) { + reverse_codepage[codepage[i]] = i; + } + + return this; + } + + /* (non-Javadoc) + * @see org.tn5250j.cp.ICodepageConverter#uni2ebcdic(char) + */ + public byte uni2ebcdic(char index) { + assert index < reverse_codepage.length; + return (byte)reverse_codepage[index]; + } + + /* (non-Javadoc) + * @see org.tn5250j.cp.ICodepageConverter#ebcdic2uni(int) + */ + public char ebcdic2uni(int index) { + index = index & 0xFF; + assert index < 256; + return codepage[index]; + } + + /** + * @return The oringal 8bit codepage. + */ + protected abstract char[] getCodePage(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/encoding/builtin/ICodepageConverter.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,34 @@ +package org.tn5250j.encoding.builtin; + +import org.tn5250j.encoding.ICodePage; + +/** + * Interface for classes which do the translation from + * EBCDIC bytes to Unicode characters and vice versa. + * + */ +public interface ICodepageConverter extends ICodePage { + + /** + * Returns an name/ID for this converter. + * Example '273' or 'CP1252'. This name should be unique, + * cause it's used in user settungs and so on. + * + * @return + */ + public abstract String getName(); + + /** + * Returns a short description for this converter. + * For Example '273 - German, EBCDIC' + * + * @return + */ + public abstract String getDescription(); + + /** + * Does special initialization stuff for this converter. + */ + public abstract ICodepageConverter init(); + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/event/ScreenOIAListener.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,45 @@ +/** + * + * <p>Title: ScreenOIAListener</p> + * <p>Description: Main interface to draw the graphical image of the screen</p> + * <p>Copyright: Copyright (c) 2000 - 2002</p> + * <p> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * </p> + * @author Kenneth J. Pouncey + * @version 0.5 + */ + +package org.tn5250j.event; + +import org.tn5250j.framework.tn5250.ScreenOIA; + +public interface ScreenOIAListener { + + public static final int OIA_CHANGED_INSERT_MODE = 0; + public static final int OIA_CHANGED_KEYS_BUFFERED = 1; + public static final int OIA_CHANGED_KEYBOARD_LOCKED = 2; + public static final int OIA_CHANGED_MESSAGELIGHT = 3; + public static final int OIA_CHANGED_SCRIPT = 4; + public static final int OIA_CHANGED_BELL = 5; + public static final int OIA_CHANGED_CLEAR_SCREEN = 6; + public static final int OIA_CHANGED_INPUTINHIBITED = 7; + public static final int OIA_CHANGED_CURSOR = 8; + + + public void onOIAChanged(ScreenOIA oia, int change); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/DataStreamProducer.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,372 @@ +package org.tn5250j.framework.tn5250; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.SocketException; +import java.util.concurrent.BlockingQueue; +import java.util.Timer; +import java.util.TimerTask; + +import org.tn5250j.encoding.ICodePage; + +import android.util.Log; + + +public class DataStreamProducer implements Runnable { + private static final String TAG = "DataStreamProducer"; + private tnvt vt; + private BufferedInputStream bin; + private ByteArrayOutputStream baosin; + private Thread me; + private byte[] saveStream; + private final BlockingQueue<Object> dsq; + private byte[] abyte2; + private FileOutputStream fw; + private BufferedOutputStream dw; + private boolean dumpBytes = false; + private ICodePage codePage; + + + + public DataStreamProducer(tnvt vt, BufferedInputStream bin, BlockingQueue<Object> queue, byte[] init) { + this.bin = bin; + this.vt = vt; + baosin = new ByteArrayOutputStream(); + dsq = queue; + abyte2 = init; + } + + public void setInputStream(ByteArrayOutputStream is) { + baosin = is; + } + + public final void run() { + boolean done = false; + me = Thread.currentThread(); + // load the first response screen + loadStream(abyte2, 0); + + while (!done) { + try { + byte[] abyte0 = readIncoming(); + + // WVL - LDC : 17/05/2004 : Device name negotiations send TIMING MARK + // Restructured to the readIncoming() method to return null + // on TIMING MARK. Don't process in that case (abyte0 == null)! + if (abyte0 != null) { + // WVL - LDC : 16/07/2003 : TR.000345 + // When the socket has been closed, the reading returns + // no bytes (an empty byte arrray). + // But the loadStream fails on this, so we check it here! + if (abyte0.length > 0) { + loadStream(abyte0, 0); + } + // WVL - LDC : 16/07/2003 : TR.000345 + // Returning no bytes means the input buffer has + // reached end-of-stream, so we do a disconnect! + else { + done = true; + vt.disconnect(); + } + } + } + catch (SocketException se) { + Log.w(TAG, " DataStreamProducer thread interrupted and stopping " + se.getMessage()); + done = true; + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + + if (me.isInterrupted()) + done = true; + } + catch (Exception ex) { + Log.w(TAG, ex.getMessage()); + + if (me.isInterrupted()) + done = true; + } + } + } + + private final void loadStream(byte abyte0[], int i) { + int j = 0; + int size = 0; + + if (saveStream == null) { + j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff; + size = abyte0.length; + } + else { + size = saveStream.length + abyte0.length; + byte[] inter = new byte[size]; + System.arraycopy(saveStream, 0, inter, 0, saveStream.length); + System.arraycopy(abyte0, 0, inter, saveStream.length, abyte0.length); + abyte0 = new byte[size]; + System.arraycopy(inter, 0, abyte0, 0, size); + saveStream = null; + inter = null; + j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff; + Log.d(TAG, "partial stream found"); + } + + if (j > size) { + saveStream = new byte[abyte0.length]; + System.arraycopy(abyte0, 0, saveStream, 0, abyte0.length); + Log.d(TAG, "partial stream saved"); + } + else { + byte abyte1[]; + + try { + abyte1 = new byte[j + 2]; + System.arraycopy(abyte0, i, abyte1, 0, j + 2); + dsq.put(abyte1); + + if (abyte0.length > abyte1.length + i) + loadStream(abyte0, i + j + 2); + } + catch (Exception ex) { + Log.w(TAG, "load stream error " + ex.getMessage()); + // ex.printStackTrace(); + // dump(abyte0); + } + } + } + + public final byte[] readIncoming() + throws IOException { + boolean done = false; + boolean negotiate = false; + baosin.reset(); + int j = -1; + int i = 0; + Timer timer = new Timer("data.stream", true); + TimerTask task = null; + + while (!done) { + if (bin.available() == 0) { + task = new TimerTask() { + public void run() { + try { + dsq.put(new Integer(0)); // trigger buffer.testChanged() + } + catch (Exception ex) { + Log.w(TAG, "readIncoming error " + ex.getMessage()); + } + } + }; + timer.schedule(task, 10); // 10 ms delay + } + + i = bin.read(); + + if (task != null) { + task.cancel(); + task = null; + } + + // WVL - LDC : 16/07/2003 : TR.000345 + // The inStream return -1 when end-of-stream is reached. This + // happens e.g. when the connection is closed from the AS/400. + // So we stop in this case! + // ==> an empty byte array is returned from this method. + if (i == -1) { // nothing read! + done = true; + vt.disconnect(); + continue; + } + + // We use the values instead of the static values IAC and EOR + // because they are defined as bytes. + // + // The > if(i != 255 || j != 255) < is a hack for the double FF FF's + // that are being returned. I do not know why this is like this and + // can not find any documentation for it. It is also being returned + // on my Client Access tcp dump as well so they are handling it. + // + // my5250 + // 0000: 00 50 DA 44 C8 45 42 00 00 00 00 24 08 00 45 00 .P.D.EB....$..E. + // 0010: 04 2A BC F9 00 00 40 06 D0 27 C1 A8 33 04 C1 A8 .*....@..'..3... + // 0020: 33 58 00 17 04 18 6F A2 83 CB 00 1E D1 BA 50 18 3X....o.......P. + // 0030: 20 00 8A 9A 00 00 03 FF FF 12 A0 00 00 04 00 00 ............... + // --------------------------- || || ------------------------------------- + // 0040: 03 04 40 04 11 00 20 01 07 00 00 00 18 00 00 10 ..@... ......... + + if (j == 255 && i == 255) { + j = -1; + continue; + } + + baosin.write(i); + + // check for end of record EOR and IAC - FFEF + if (j == 255 && i == 239) + done = true; + + // This is to check for the TELNET TIMING MARK OPTION + // rfc860 explains this in more detail. When we receive it + // we will negotiate with the server by sending a WONT'T TIMING-MARK + // This will let the server know that we processed the information + // and are just waiting for the user to enter some data so keep the + // socket alive. This is more or less a AYT (ARE YOU THERE) or not. + if (i == 253 && j == 255) { + done = true; + negotiate = true; + } + + j = i; + } + + // after the initial negotiation we might get other options such as + // timing marks ?????????????? do we ???????????? look at telnet spec + // yes we do. rfc860 explains about timing marks. + // WVL - LDC : 17/05/2004 : Device name negotiations send TIMING MARK + // to existing device! + // Handled incorrectly: we cannot continue processing the TIMING MARK DO + // after we have handled it in the vt.negotiate() + // We should not return the bytes; + // ==> restructured to return null after negotiation! + // Impacts the run method! Added the null check. + byte[] rBytes = baosin.toByteArray(); + + if (dumpBytes) { + dump(rBytes); + } + + if (negotiate) { + if (bin.available() == 0) { + task = new TimerTask() { + public void run() { + try { + dsq.put(new Integer(0)); // trigger buffer.testChanged() + } + catch (Exception ex) { + Log.w(TAG, "readIncoming error " + ex.getMessage()); + } + } + }; + timer.schedule(task, 10); // 10 ms delay + } + + // get the negotiation option + baosin.write(bin.read()); + + if (task != null) { + task.cancel(); + task = null; + } + + vt.negotiate(rBytes); + return null; + } + + return rBytes; + } + + protected final void toggleDebug(ICodePage cp) { + if (codePage == null) + codePage = cp; + + dumpBytes = !dumpBytes; + + if (dumpBytes) { + try { + if (fw == null) { + fw = new FileOutputStream("log.txt"); + dw = new BufferedOutputStream(fw); + } + } + catch (FileNotFoundException fnfe) { + Log.w(TAG, fnfe.getMessage()); + } + } + else { + try { + if (dw != null) + dw.close(); + + if (fw != null) + fw.close(); + + dw = null; + fw = null; + codePage = null; + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + } + } + + Log.i(TAG, "Data Stream output is now " + dumpBytes); + } + + public void dump(byte[] abyte0) { + try { + Log.i(TAG, "\n Buffer Dump of data from AS400: "); + dw.write("\r\n Buffer Dump of data from AS400: ".getBytes()); + StringBuffer h = new StringBuffer(); + + for (int x = 0; x < abyte0.length; x++) { + if (x % 16 == 0) { + System.out.println(" " + h.toString()); + dw.write((" " + h.toString() + "\r\n").getBytes()); + h.setLength(0); + h.append("+0000"); + h.setLength(5 - Integer.toHexString(x).length()); + h.append(Integer.toHexString(x).toUpperCase()); + System.out.print(h.toString()); + dw.write(h.toString().getBytes()); + h.setLength(0); + } + + char ac = codePage.ebcdic2uni(abyte0[x]); + + if (ac < ' ') + h.append('.'); + else + h.append(ac); + + if (x % 4 == 0) { + System.out.print(" "); + dw.write((" ").getBytes()); + } + + if (Integer.toHexString(abyte0[x] & 0xff).length() == 1) { + System.out.print("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()); + dw.write(("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes()); + } + else { + System.out.print(Integer.toHexString(abyte0[x] & 0xff).toUpperCase()); + dw.write((Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes()); + } + } + + System.out.println(); + dw.write("\r\n".getBytes()); + dw.flush(); + } + catch (EOFException _ex) { } + catch (Exception _ex) { + Log.w(TAG, "Cannot dump from host\n\r"); + } + } + +// public void dumpBytes() { +// byte shit[] = bk.buffer; +// for (int i = 0;i < shit.length;i++) +// System.out.println(i + ">" + shit[i] + "< - ascii - >" + getASCIIChar(shit[i]) + "<"); +// } +// +// public void dumpHexBytes(byte[] abyte) { +// byte shit[] = abyte; +// for (int i = 0;i < shit.length;i++) +// System.out.println(i + ">" + shit[i] + "< hex >" + Integer.toHexString((shit[i] & 0xff))); +// } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/KbdTypesCodePages.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,112 @@ +package org.tn5250j.framework.tn5250; + +/** + * IBM i 7.1 Information Center > Programmierung > i5/OS globalization > Globalization reference information > Keyboard reference information + * + * @see <a href="http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=/nls/rbagsnatlangkeybrdtype.htm">National language keyboard types and SBCS code pages</a> + */ +public enum KbdTypesCodePages { + + ALI("Albanian", "ALI", "697", "500", "500"), + CLB("Arabic", "CLB", "235", "420", "420"), + AGB("Austrian/ German", "AGB", "697", "273", "273"), + AGE("Austrian/ German", "AGB", "695", "1141", "1141"), + AGI("Austrian/German (MNCS)", "AGI", "697", "500", "500"), + BLI("Belgian MNCS", "BLI", "697", "500", "500"), + BRB("Brazilian Portuguese", "BRB", "697", "37", "37"), + BGB("Bulgarian", "BGB", "1150", "1025", "1025"), + CAB("Canadian French", "CAB", "341", "260", "65535"), + CAI("Canadian French MNCS", "CAI", "697", "500", "500"), +// YGI("Croatian","YGI","959","870","870"), + CYB("Cyrillic", "CYB", "960", "880", "880"), + CSB("Czech", "CSB", "959", "870", "870"), + DMB("Danish", "DMB", "697", "277", "277"), + DMI("Danish MNCS", "DMI", "697", "500", "500"), + FNB("Finnish/Swedish", "FNB", "697", "278", "278"), + FNI("Finnish/Swedish MNCS", "FNI", "697", "500", "500"), + FAB("French (Azerty)", "FAB", "697", "297", "297"), + FAI("French (Azerty) MNCS", "FAI", "697", "500", "500"), + FQB("French (Qwerty)", "FQB", "697", "297", "297"), + FQI("French (Qwerty) MNCS", "FQI", "697", "500", "500"), + GNB("Greek (See note 2.)", "GNB", "925", "875", "875"), + NCB("Hebrew", "NCB", "941", "424", "424"), + HNB("Hungarian", "HNB", "959", "870", "870"), + ICB("Icelandic", "ICB", "697", "871", "871"), + ICI("Icelandic MNCS", "ICI", "697", "500", "500"), + INB("International", "INB", "697", "500", "500"), + INBX("International-X", "INB", "697", "500", "500-ch"), +// INB("International MNCS","INB","697","500","500"), + IRB("Farsi (Iran)", "IRB", "1219", "1097", "1097"), + ITB("Italian", "ITB", "697", "280", "280"), + ITI("Italian MNCS", "ITI", "697", "500", "500"), + JEB("Japanese-English", "JEB", "697", "281", "65535"), + JEI("Japanese- English MNCS", "JEI", "697", "500", "500"), + JKB("Japanese Kanji and Katakana", "JKB", "1172", "290", "5026"), +// JUB("Japanese Kanji and US English","JUB","697","37","See note 3."), + KAB("Japanese Katakana", "KAB", "332", "290", "290"), + JPB("Japanese Latin Extended", "JPB", "1172", "1027", "1027"), + KOB("Korean", "KOB", "1173", "833", "833"), + ROB("Latin 2", "ROB", "959", "870", "870"), + MKB("Macedonian", "MKB", "1150", "1025", "1025"), + NEB("Dutch (Netherlands)", "NEB", "697", "37", "37"), + NEI("Dutch (Netherlands) MNCS", "NEI", "697", "500", "500"), + NWB("Norwegian", "NWB", "697", "277", "277"), + NWI("Norwegian MNCS", "NWI", "697", "500", "500"), + PLB("Polish", "PLB", "959", "870", "870"), + PLBX("Polish 870-pl", "PLB", "959", "870", "870-pl"), // Workaround, to catch up Java codepage '870-pl' + PRB("Portuguese", "PRB", "697", "37", "37"), + PRI("Portuguese MNCS", "PRI", "697", "500", "500"), + RMB("Romanian", "RMB", "959", "870", "870"), + RUB("Russian", "RUB", "1150", "1025", "1025"), + SQB("Serbian, Cyrillic", "SQB", "1150", "1025", "1025"), + YGI("Serbian, Latin", "YGI", "959", "870", "870"), + RCB("Simplified Chinese", "RCB", "1174", "836", "836"), + SKB("Slovakian", "SKB", "959", "870", "870"), + SKBX("Slovakian 870-sk", "SKB", "959", "870", "870-sk"), // Workaround, to catch up Java codepage '870-sk' +// YGI("Slovenian","YGI","959","870","870"), + SPB("Spanish", "SPB", "697", "284", "284"), + SPI("Spanish MNCS", "SPI", "697", "500", "500"), + SSB("Spanish Speaking", "SSB", "697", "284", "284"), + SSI("Spanish Speaking MNCS", "SSI", "697", "500", "500"), + SWB("Swedish", "SWB", "697", "278", "278"), + SWI("Swedish MNCS", "SWI", "697", "500", "500"), + SFI("French (Switzerland) MNCS", "SFI", "697", "500", "500"), + SGI("German (Switzerland) MNCS", "SGI", "697", "500", "500"), + THB("Thai", "THB", "1176", "838", "838"), + TAB("Traditional Chinese", "TAB", "1175", "37", "937"), + TKB("Turkish (Qwerty)", "TKB", "1152", "1026", "1026"), + TRB("Turkish (F)", "TRB", "1152", "1026", "1026"), + UKB("English (United Kingdom)", "UKB", "697", "285", "285"), + UKI("English (United Kingdom) MNCS", "UKI", "697", "500", "500"), + USB("English (United States and Canada)", "USB", "697", "37", "37"), + USI("English (United States and Canada) MNCS", "USI", "697", "500", "500"); + + public final String description; + public final String kbdType; + public final String charset; + public final String codepage; + public final String ccsid; + + /** + * @param description + * @param kbdType + * @param charset + * @param codepage + * @param ccsid + */ + private KbdTypesCodePages(String description, String kbdType, String charset, String codepage, String ccsid) { + this.description = description; + this.kbdType = kbdType; + this.charset = charset; + this.codepage = codepage; + this.ccsid = ccsid; + } + + @Override + public String toString() { + return "[description=" + description + ", kbdType=" + kbdType + + ", charset=" + charset + ", codepage=" + codepage + + ", ccsid=" + ccsid + "]"; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/KeyStrokenizer.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,160 @@ +/* + * @(#)KeyStrokenizer.java + * Copyright: Copyright (c) 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ + +package org.tn5250j.framework.tn5250; + +import android.util.Log; + + + +public class KeyStrokenizer { + private static final String TAG = "KeyStrokenizer"; + private StringBuffer keyStrokes; + private StringBuffer sb; + private int index; + private int length; + + + + public KeyStrokenizer() { + sb = new StringBuffer(); + setKeyStrokes(null); + } + + public void setKeyStrokes(String strokes) { + if (strokes != null) { + keyStrokes.setLength(0); + Log.d(TAG, "set " + strokes); + length = strokes.length(); + } + else { + keyStrokes = new StringBuffer(); + length = 0; + } + + keyStrokes.append(strokes); + index = 0; + } + + public boolean hasMoreKeyStrokes() { + return length > index; + } + + public String nextKeyStroke() { + String s = ""; + boolean gotOne = false; + + if (length > index) { + sb.setLength(0); + char c = keyStrokes.charAt(index); + + switch (c) { + case '[': + sb.append(c); + index++; + + // we need to throw an error here + if (index >= length) { + Log.w(TAG, " mnemonic key was incomplete :1 " + + "at position " + index + " len " + length); + } + else { + c = keyStrokes.charAt(index); + + if (c == '[') + index++; + else { + while (!gotOne) { + if (c == ']') { // did we find an ending + sb.append(c); + index++; + gotOne = true; + } + else { + sb.append(c); + index++; + + // we need to throw an error here because we did not + // find an ending for the potential mnemonic + if (index >= length) { + Log.w(TAG, + " mnemonic key was incomplete ending not found :2 " + + "at position " + index); + } + + c = keyStrokes.charAt(index); + } + } + } + } + + break; + + case ']': + index++; + + if (index >= length) { + Log.w(TAG, + " mnemonic key was incomplete ending not found :3 " + + "at position " + index); + sb.append(c); + index++; + } + else { + c = keyStrokes.charAt(index); + + if (c == ']') { + sb.append(c); + index++; + } + else { + Log.w(TAG, + " mnemonic key was incomplete beginning not found :4 " + + "at position " + index); + } + } + + break; + + default: + sb.append(c); + index++; + break; + } + + if (sb != null) { + s = new String(sb); + } + } + + Log.d(TAG, "next " + keyStrokes); + return s; + } + + public String getUnprocessedKeyStroked() { + if (index >= length) { + return null; + } + + return keyStrokes.substring(index); + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/Rect.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,61 @@ +/** + * $Id: Rect.java 1092 2011-01-16 20:27:56Z master_jaf $ + * + * Title: tn5250J + * Copyright: Copyright (c) 2001,2009 + * Company: + * @author: master_jaf + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.framework.tn5250; + + +/** + * Simplified rectangle class. Very much similar like java.awt.Rectangle, + * but we want to decouple the packages ... + */ +public class Rect { + + /* default */ int x; + /* default */ int y; + /* default */ int height; + /* default */ int width; + + /** + * @param rect + */ + public void setBounds(Rect rect) { + setBounds(rect.x, rect.y, rect.width, rect.height); + } + + /** + * @param x the new X coordinate for the upper-left corner of this rectangle + * @param y the new Y coordinate for the upper-left corner of this rectangle + * @param width the new width for this rectangle + * @param height the new height for this rectangle + */ + public void setBounds(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/Screen5250.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,3738 @@ +/* + * Title: Screen5250.java + * Copyright: Copyright (c) 2001 - 2004 + * Company: + * @author Kenneth J. Pouncey + * @version 0.5 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.framework.tn5250; + +import static org.tn5250j.TN5250jConstants.*; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Vector; + +import org.tn5250j.TN5250jConstants; + +import android.util.Log; +import de.mud.terminal.VDUBuffer; +import de.mud.terminal.vt320; +import com.five_ten_sg.connectbot.service.FontSizeChangedListener; + + +public class Screen5250 implements FontSizeChangedListener { + private static final String TAG = "Screen5250"; + private ScreenFields screenFields; + private int lastAttr; + private int lastPos; + private int lenScreen; + private KeyStrokenizer strokenizer; + private tnvt sessionVT; + private vt320 buffer; // used to draw the screen + private int numRows = 0; + private int numCols = 0; + protected static final int initAttr = 32; + protected static final char initChar = 0; + public boolean cursorActive = false; + public boolean cursorShown = false; + protected boolean insertMode = false; + private boolean keyProcessed = false; + private Rect dirtyScreen = new Rect(); + + public int homePos = 0; + public int saveHomePos = 0; + private String bufferedKeys; + public boolean pendingInsert = false; + + public final static byte STATUS_SYSTEM = 1; + public final static byte STATUS_ERROR_CODE = 2; + public final static byte STATUS_VALUE_ON = 1; + public final static byte STATUS_VALUE_OFF = 2; + + private StringBuffer hsMore = new StringBuffer("More..."); + private StringBuffer hsBottom = new StringBuffer("Bottom"); + + // error codes to be sent to the host on an error + private final static int ERR_CURSOR_PROTECTED = 0x05; + private final static int ERR_INVALID_SIGN = 0x11; + private final static int ERR_NO_ROOM_INSERT = 0x12; + private final static int ERR_NUMERIC_ONLY = 0x09; + private final static int ERR_DUP_KEY_NOT_ALLOWED = 0x19; + private final static int ERR_NUMERIC_09 = 0x10; + private final static int ERR_FIELD_MINUS = 0x16; + private final static int ERR_FIELD_EXIT_INVALID = 0x18; + private final static int ERR_ENTER_NO_ALLOWED = 0x20; + private final static int ERR_MANDATORY_ENTER = 0x21; + + private boolean guiInterface = false; + private boolean resetRequired = false; + private boolean backspaceError = true; + private boolean feError; + + // Operator Information Area + private ScreenOIA oia; + + // screen planes + protected ScreenPlanes planes; + + + + public Screen5250() { + try { + jbInit(); + } + catch (Exception ex) { + Log.w(TAG, "In constructor: ", ex); + } + } + + void jbInit() throws Exception { + lastAttr = 32; + // default number of rows and columns + numRows = 24; + numCols = 80; + setCursor(1, 1); // set initial cursor position + oia = new ScreenOIA(this); + oia.setKeyBoardLocked(true); + lenScreen = numRows * numCols; + planes = new ScreenPlanes(this, numRows); + screenFields = new ScreenFields(this); + strokenizer = new KeyStrokenizer(); + } + + protected ScreenPlanes getPlanes() { + return planes; + } + + public final ScreenOIA getOIA() { + return oia; + } + + protected final void setRowsCols(int rows, int cols) { + int oldRows = numRows; + int oldCols = numCols; + // default number of rows and columns + numRows = rows; + numCols = cols; + lenScreen = numRows * numCols; + planes.setSize(rows); + + // If they are not the same then we need to inform the listeners that + // the size changed. + if (oldRows != numRows || oldCols != numCols) + fireScreenSizeChanged(); + } + + + public boolean isCursorActive() { + return cursorActive; + } + + public boolean isCursorShown() { + return cursorShown; + } + + public void setUseGUIInterface(boolean gui) { + guiInterface = gui; + } + + public void toggleGUIInterface() { + guiInterface = !guiInterface; + } + + public void setResetRequired(boolean reset) { + resetRequired = reset; + } + + public void setBackspaceError(boolean onError) { + backspaceError = onError; + } + + /** + * Copy & Paste support + * + * @see {@link #pasteText(String, boolean)} + * @see {@link #copyTextField(int)} + */ + public final String copyText(Rect area) { + StringBuilder sb = new StringBuilder(); + Rect workR = new Rect(); + workR.setBounds(area); + Log.d(TAG, "Copying " + workR); + // loop through all the screen characters to send them to the clip board + int m = workR.x; + int i = 0; + int t = 0; + + while (workR.height-- > 0) { + t = workR.width; + i = workR.y; + + while (t-- > 0) { + // only copy printable characters (in this case >= ' ') + char c = planes.getChar(getPos(m - 1, i - 1)); + + if (c >= ' ' && (planes.screenExtended[getPos(m - 1, i - 1)] & EXTENDED_5250_NON_DSP) + == 0) + sb.append(c); + else + sb.append(' '); + + i++; + } + + sb.append('\n'); + m++; + } + + return sb.toString(); + } + + /** + * Copy & Paste support + * + * @param content + * @see {@link #copyText(Rectangle)} + */ + public final void pasteText(String content, boolean special) { + Log.d(TAG, "Pasting, special:" + special); + setCursorActive(false); + StringBuilder sb = new StringBuilder(content); + StringBuilder pd = new StringBuilder(); + // character counters within the string to be pasted. + int nextChar = 0; + int nChars = sb.length(); + int lr = getRow(lastPos); + int lc = getCol(lastPos); + resetDirty(lastPos); + int cpos = lastPos; + int length = getScreenLength(); + char c = 0; + boolean setIt; + // save our current place within the FFT. + screenFields.saveCurrentField(); + + for (int x = nextChar; x < nChars; x++) { + c = sb.charAt(x); + + if ((c == '\n') || (c == '\r')) { + Log.i(TAG, "pasted cr-lf>" + pd + "<"); + pd.setLength(0); + // if we read in a cr lf in the data stream we need to go + // to the starting column of the next row and start from there + cpos = getPos(getRow(cpos) + 1, lc); + + // If we go paste the end of the screen then let's start over from + // the beginning of the screen space. + if (cpos > length) + cpos = 0; + } + else { + // we will default to set the character always. + setIt = true; + + // If we are in a special paste scenario then we check for valid + // characters to paste. + if (special && (!Character.isLetter(c) && !Character.isDigit(c))) + setIt = false; + + // we will only push a character to the screen space if we are in + // a field + if (isInField(cpos) && setIt) { + planes.setChar(cpos, c); + setDirty(cpos); + screenFields.setCurrentFieldMDT(); + } + + // If we placed a character then we go to the next position. + if (setIt) + cpos++; + + // we will append the information to our debug buffer. + pd.append(c); + } + } + + // if we have anything else not logged then log it out. + if (pd.length() > 0) + Log.i(TAG, "pasted >" + pd + "<"); + + // restore out position within the FFT. + screenFields.restoreCurrentField(); + updateDirty(); + // restore our cursor position. + setCursor(lr + 1, lc + 1); + setCursorActive(true); + } + + /** + * Copy & Paste support + * + * @param position + * @return + * @see {@link #copyText(int)} + */ + public final String copyTextField(int position) { + screenFields.saveCurrentField(); + isInField(position); + String result = screenFields.getCurrentFieldText(); + screenFields.restoreCurrentField(); + return result; + } + + /** + * + * Copy & Paste end code + * + */ + + /** + * Sum them + * + * @param which + * formatting option to use + * @return vector string of numberic values + */ + public final Vector<Double> sumThem(boolean which, Rect area) { + StringBuilder sb = new StringBuilder(); + Rect workR = new Rect(); + workR.setBounds(area); + // gui.rubberband.reset(); + // gui.repaint(); + Log.d(TAG, "Summing"); + // obtain the decimal format for parsing + DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); + DecimalFormatSymbols dfs = df.getDecimalFormatSymbols(); + + if (which) { + dfs.setDecimalSeparator('.'); + dfs.setGroupingSeparator(','); + } + else { + dfs.setDecimalSeparator(','); + dfs.setGroupingSeparator('.'); + } + + df.setDecimalFormatSymbols(dfs); + Vector<Double> sumVector = new Vector<Double>(); + // loop through all the screen characters to send them to the clip board + int m = workR.x; + int i = 0; + int t = 0; + double sum = 0.0; + + while (workR.height-- > 0) { + t = workR.width; + i = workR.y; + + while (t-- > 0) { + // only copy printable numeric characters (in this case >= ' ') + // char c = screen[getPos(m - 1, i - 1)].getChar(); + char c = planes.getChar(getPos(m - 1, i - 1)); + // if (((c >= '0' && c <= '9') || c == '.' || c == ',' || c == '-') + // && !screen[getPos(m - 1, i - 1)].nonDisplay) { + + // TODO: update me here to implement the nonDisplay check as well + if (((c >= '0' && c <= '9') || c == '.' || c == ',' || c == '-')) { + sb.append(c); + } + + i++; + } + + if (sb.length() > 0) { + if (sb.charAt(sb.length() - 1) == '-') { + sb.insert(0, '-'); + sb.deleteCharAt(sb.length() - 1); + } + + try { + Number n = df.parse(sb.toString()); + // System.out.println(s + " " + n.doubleValue()); + sumVector.add(new Double(n.doubleValue())); + sum += n.doubleValue(); + } + catch (ParseException pe) { + Log.w(TAG, pe.getMessage() + " at " + + pe.getErrorOffset()); + } + } + + sb.setLength(0); + m++; + } + + Log.d(TAG, "" + sum); + return sumVector; + } + + public void setVT(tnvt v) { + sessionVT = v; + } + + public void setBuffer(vt320 buffer) { + this.buffer = buffer; + } + + /** + * converts mnemonic string values into aid integers + * + * @see #sendKeys + * @param mnem string mnemonic value + * @return key value of Mnemonic + */ + private int getMnemonicValue(String mnem) { + if (mnemonicMap.containsKey(mnem)) return mnemonicMap.get(mnem); + + return 0; + } + + protected void setPrehelpState(boolean setErrorCode, boolean lockKeyboard, + boolean unlockIfLocked) { + if (oia.isKeyBoardLocked() && unlockIfLocked) + oia.setKeyBoardLocked(false); + else + oia.setKeyBoardLocked(lockKeyboard); + + bufferedKeys = null; + oia.setKeysBuffered(false); + } + + /** + * Activate the cursor on screen + * + * @param activate + */ + public void setCursorActive(boolean activate) { + // System.out.println("cursor active " + updateCursorLoc + " " + + // cursorActive + " " + activate); + if (cursorActive && !activate) { + setCursorOff(); + cursorActive = activate; + } + else { + if (!cursorActive && activate) { + cursorActive = activate; + setCursorOn(); + } + } + } + + /** + * Set the cursor on + */ + public void setCursorOn() { + cursorShown = true; + updateCursorLoc(); + } + + /** + * Set the cursor off + */ + public void setCursorOff() { + cursorShown = false; + updateCursorLoc(); + // System.out.println("cursor off " + updateCursorLoc + " " + + // cursorActive); + } + + /** + * + */ + private void updateCursorLoc() { + if (cursorActive) { + fireCursorChanged(); + } + } + + /** + * The sendKeys method sends a string of keys to the virtual screen. This + * method acts as if keystrokes were being typed from the keyboard. The + * keystrokes will be sent to the location given. The string being passed + * can also contain mnemonic values such as [enter] enter key,[tab] tab key, + * [pf1] pf1 etc... + * + * These will be processed as if you had pressed these keys from the + * keyboard. All the valid special key values are contained in the MNEMONIC + * enumeration: + * + * <table BORDER COLS=2 WIDTH="50%" > + * + * <tr> + * <td>MNEMONIC_CLEAR</td> + * <td>[clear]</td> + * </tr> + * <tr> + * <td>MNEMONIC_ENTER</td> + * <td>[enter]</td> + * </tr> + * <tr> + * <td>MNEMONIC_HELP</td> + * <td>[help]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PAGE_DOWN</td> + * <td>[pgdown]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PAGE_UP</td> + * <td>[pgup]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PRINT</td> + * <td>[print]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF1</td> + * <td>[pf1]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF2</td> + * <td>[pf2]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF3</td> + * <td>[pf3]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF4</td> + * <td>[pf4]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF5</td> + * <td>[pf5]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF6</td> + * <td>[pf6]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF7</td> + * <td>[pf7]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF8</td> + * <td>[pf8]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF9</td> + * <td>[pf9]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF10</td> + * <td>[pf10]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF11</td> + * <td>[pf11]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF12</td> + * <td>[pf12]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF13</td> + * <td>[pf13]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF14</td> + * <td>[pf14]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF15</td> + * <td>[pf15]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF16</td> + * <td>[pf16]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF17</td> + * <td>[pf17]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF18</td> + * <td>[pf18]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF19</td> + * <td>[pf19]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF20</td> + * <td>[pf20]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF21</td> + * <td>[pf21]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF22</td> + * <td>[pf22]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF23</td> + * <td>[pf23]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PF24</td> + * <td>[pf24]</td> + * </tr> + * <tr> + * <td>MNEMONIC_BACK_SPACE</td> + * <td>[backspace]</td> + * </tr> + * <tr> + * <td>MNEMONIC_BACK_TAB</td> + * <td>[backtab]</td> + * </tr> + * <tr> + * <td>MNEMONIC_UP</td> + * <td>[up]</td> + * </tr> + * <tr> + * <td>MNEMONIC_DOWN</td> + * <td>[down]</td> + * </tr> + * <tr> + * <td>MNEMONIC_LEFT</td> + * <td>[left]</td> + * </tr> + * <tr> + * <td>MNEMONIC_RIGHT</td> + * <td>[right]</td> + * </tr> + * <tr> + * <td>MNEMONIC_DELETE</td> + * <td>[delete]</td> + * </tr> + * <tr> + * <td>MNEMONIC_TAB</td> + * <td>"[tab]</td> + * </tr> + * <tr> + * <td>MNEMONIC_END_OF_FIELD</td> + * <td>[eof]</td> + * </tr> + * <tr> + * <td>MNEMONIC_ERASE_EOF</td> + * <td>[eraseeof]</td> + * </tr> + * <tr> + * <td>MNEMONIC_ERASE_FIELD</td> + * <td>[erasefld]</td> + * </tr> + * <tr> + * <td>MNEMONIC_INSERT</td> + * <td>[insert]</td> + * </tr> + * <tr> + * <td>MNEMONIC_HOME</td> + * <td>[home]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD0</td> + * <td>[keypad0]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD1</td> + * <td>[keypad1]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD2</td> + * <td>[keypad2]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD3</td> + * <td>[keypad3]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD4</td> + * <td>[keypad4]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD5</td> + * <td>[keypad5]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD6</td> + * <td>[keypad6]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD7</td> + * <td>[keypad7]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD8</td> + * <td>[keypad8]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD9</td> + * <td>[keypad9]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD_PERIOD</td> + * <td>[keypad.]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD_COMMA</td> + * <td>[keypad,]</td> + * </tr> + * <tr> + * <td>MNEMONIC_KEYPAD_MINUS</td> + * <td>[keypad-]</td> + * </tr> + * <tr> + * <td>MNEMONIC_FIELD_EXIT</td> + * <td>[fldext]</td> + * </tr> + * <tr> + * <td>MNEMONIC_FIELD_PLUS</td> + * <td>[field+]</td> + * </tr> + * <tr> + * <td>MNEMONIC_FIELD_MINUS</td> + * <td>[field-]</td> + * </tr> + * <tr> + * <td>MNEMONIC_BEGIN_OF_FIELD</td> + * <td>[bof]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PA1</td> + * <td>[pa1]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PA2</td> + * <td>[pa2]</td> + * </tr> + * <tr> + * <td>MNEMONIC_PA3</td> + * <td>[pa3]</td> + * </tr> + * <tr> + * <td>MNEMONIC_SYSREQ</td> + * <td>[sysreq]</td> + * </tr> + * <tr> + * <td>MNEMONIC_RESET</td> + * <td>[reset]</td> + * </tr> + * <tr> + * <td>MNEMONIC_ATTN</td> + * <td>[attn]</td> + * </tr> + * <tr> + * <td>MNEMONIC_MARK_LEFT</td> + * <td>[markleft]</td> + * </tr> + * <tr> + * <td>MNEMONIC_MARK_RIGHT</td> + * <td>[markright]</td> + * </tr> + * <tr> + * <td>MNEMONIC_MARK_UP</td> + * <td>[markup]</td> + * </tr> + * <tr> + * <td>MNEMONIC_MARK_DOWN</td> + * <td>[markdown]</td> + * </tr> + * + * </table> + * + * @param text + * The string of characters to be sent + * + * @see #sendAid + * + */ + + public synchronized void sendKeys(String text) { + if (isStatusErrorCode() && !resetRequired) { + setCursorActive(false); + simulateMnemonic(getMnemonicValue("[reset]")); + setCursorActive(true); + } + + if (oia.isKeyBoardLocked()) { + if (text.equals("[reset]") || text.equals("[sysreq]") + || text.equals("[attn]")) { + setCursorActive(false); + simulateMnemonic(getMnemonicValue(text)); + setCursorActive(true); + } + else { + if (isStatusErrorCode()) { + sessionVT.signalBell(); + return; + } + + oia.setKeysBuffered(true); + + if (bufferedKeys == null) bufferedKeys = text; + else bufferedKeys += text; + + return; + } + } + else { + if (oia.isKeysBuffered()) { + if (bufferedKeys != null) { + text = bufferedKeys + text; + } + + oia.setKeysBuffered(false); + bufferedKeys = null; + } + + isInField(); + + if (text.length() == 1 && !text.equals("[") && !text.equals("]")) { + setCursorActive(false); + simulateKeyStroke(text.charAt(0)); + setCursorActive(true); + } + else { + strokenizer.setKeyStrokes(text); + String s; + boolean done = false; + // setCursorOff2(); + setCursorActive(false); + + while (!done) { + if (strokenizer.hasMoreKeyStrokes()) { + isInField(); + s = strokenizer.nextKeyStroke(); + + if (s.length() == 1) { + simulateKeyStroke(s.charAt(0)); + } + else { + simulateMnemonic(getMnemonicValue(s)); + } + + if (oia.isKeyBoardLocked()) { + bufferedKeys = strokenizer + .getUnprocessedKeyStroked(); + + if (bufferedKeys != null) { + oia.setKeysBuffered(true); + } + + done = true; + } + } + else { + done = true; + } + } + + setCursorActive(true); + } + } + } + + /** + * The sendAid method sends an "aid" keystroke to the virtual screen. These + * aid keys can be thought of as special keystrokes, like the Enter key, + * PF1-24 keys or the Page Up key. All the valid special key values are + * contained in the AID_ enumeration: + * + * @param aidKey + * The aid key to be sent to the host + * + * @see #sendKeys + * @see TN5250jConstants#AID_CLEAR + * @see #AID_ENTER + * @see #AID_HELP + * @see #AID_ROLL_UP + * @see #AID_ROLL_DOWN + * @see #AID_ROLL_LEFT + * @see #AID_ROLL_RIGHT + * @see #AID_PRINT + * @see #AID_PF1 + * @see #AID_PF2 + * @see #AID_PF3 + * @see #AID_PF4 + * @see #AID_PF5 + * @see #AID_PF6 + * @see #AID_PF7 + * @see #AID_PF8 + * @see #AID_PF9 + * @see #AID_PF10 + * @see #AID_PF11 + * @see #AID_PF12 + * @see #AID_PF13 + * @see #AID_PF14 + * @see #AID_PF15 + * @see #AID_PF16 + * @see #AID_PF17 + * @see #AID_PF18 + * @see #AID_PF19 + * @see #AID_PF20 + * @see #AID_PF21 + * @see #AID_PF22 + * @see #AID_PF23 + * @see #AID_PF24 + */ + public void sendAid(int aidKey) { + sessionVT.sendAidKey(aidKey); + } + + /** + * Restores the error line and sets the error mode off. + * + */ + protected void resetError() { + restoreErrorLine(); + setStatus(STATUS_ERROR_CODE, STATUS_VALUE_OFF, ""); + } + + protected boolean simulateMnemonic(int mnem) { + boolean simulated = false; + + switch (mnem) { + case AID_CLEAR: + case AID_ENTER: + case AID_PF1: + case AID_PF2: + case AID_PF3: + case AID_PF4: + case AID_PF5: + case AID_PF6: + case AID_PF7: + case AID_PF8: + case AID_PF9: + case AID_PF10: + case AID_PF11: + case AID_PF12: + case AID_PF13: + case AID_PF14: + case AID_PF15: + case AID_PF16: + case AID_PF17: + case AID_PF18: + case AID_PF19: + case AID_PF20: + case AID_PF21: + case AID_PF22: + case AID_PF23: + case AID_PF24: + case AID_ROLL_DOWN: + case AID_ROLL_UP: + case AID_ROLL_LEFT: + case AID_ROLL_RIGHT: + if (!screenFields.isCanSendAid()) { + displayError(ERR_ENTER_NO_ALLOWED); + } + else + sendAid(mnem); + + simulated = true; + break; + + case AID_HELP: + sessionVT.sendHelpRequest(); + simulated = true; + break; + + case AID_PRINT: + sessionVT.hostPrint(1); + simulated = true; + break; + + case BACK_SPACE: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + if (screenFields.getCurrentField().startPos() == lastPos) { + if (backspaceError) + displayError(ERR_CURSOR_PROTECTED); + else { + gotoFieldPrev(); + goto_XY(screenFields.getCurrentField().endPos()); + updateDirty(); + } + } + else { + screenFields.getCurrentField().getKeyPos(lastPos); + screenFields.getCurrentField().changePos(-1); + resetDirty(screenFields.getCurrentField().getCurrentPos()); + shiftLeft(screenFields.getCurrentField().getCurrentPos()); + updateDirty(); + screenFields.setCurrentFieldMDT(); + simulated = true; + } + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + break; + + case BACK_TAB: + if (screenFields.getCurrentField() != null + && screenFields.isCurrentFieldHighlightedEntry()) { + resetDirty(screenFields.getCurrentField().startPos); + gotoFieldPrev(); + updateDirty(); + } + else + gotoFieldPrev(); + + if (screenFields.isCurrentFieldContinued()) { + do { + gotoFieldPrev(); + } + while (screenFields.isCurrentFieldContinuedMiddle() + || screenFields.isCurrentFieldContinuedLast()); + } + + isInField(); + simulated = true; + break; + + case UP: + case MARK_UP: + process_XY(lastPos - numCols); + simulated = true; + break; + + case DOWN: + case MARK_DOWN: + process_XY(lastPos + numCols); + simulated = true; + break; + + case LEFT: + case MARK_LEFT: + process_XY(lastPos - 1); + simulated = true; + break; + + case RIGHT: + case MARK_RIGHT: + process_XY(lastPos + 1); + simulated = true; + break; + + case NEXTWORD: + gotoNextWord(); + simulated = true; + break; + + case PREVWORD: + gotoPrevWord(); + simulated = true; + break; + + case DELETE: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + resetDirty(lastPos); + screenFields.getCurrentField().getKeyPos(lastPos); + shiftLeft(screenFields.getCurrentFieldPos()); + screenFields.setCurrentFieldMDT(); + updateDirty(); + simulated = true; + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + break; + + case TAB: + if (screenFields.getCurrentField() != null + && !screenFields.isCurrentFieldContinued()) { + if (screenFields.isCurrentFieldHighlightedEntry()) { + resetDirty(screenFields.getCurrentField().startPos); + gotoFieldNext(); + updateDirty(); + } + else + gotoFieldNext(); + } + else { + do { + gotoFieldNext(); + } + while (screenFields.getCurrentField() != null + && (screenFields.isCurrentFieldContinuedMiddle() || screenFields + .isCurrentFieldContinuedLast())); + } + + isInField(); + simulated = true; + break; + + case EOF: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + int where = endOfField(screenFields.getCurrentField() + .startPos(), true); + + if (where > 0) { + setCursor((where / numCols) + 1, (where % numCols) + 1); + } + + simulated = true; + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + resetDirty(lastPos); + break; + + case ERASE_EOF: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + int where = lastPos; + resetDirty(lastPos); + + if (fieldExit()) { + screenFields.setCurrentFieldMDT(); + + if (!screenFields.isCurrentFieldContinued()) { + gotoFieldNext(); + } + else { + do { + gotoFieldNext(); + + if (screenFields.isCurrentFieldContinued()) + fieldExit(); + } + while (screenFields.isCurrentFieldContinuedMiddle() + || screenFields.isCurrentFieldContinuedLast()); + } + } + + updateDirty(); + goto_XY(where); + simulated = true; + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + break; + + case ERASE_FIELD: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + int where = lastPos; + lastPos = screenFields.getCurrentField().startPos(); + resetDirty(lastPos); + + if (fieldExit()) { + screenFields.setCurrentFieldMDT(); + + if (!screenFields.isCurrentFieldContinued()) { + gotoFieldNext(); + } + else { + do { + gotoFieldNext(); + + if (screenFields.isCurrentFieldContinued()) + fieldExit(); + } + while (screenFields.isCurrentFieldContinuedMiddle() + || screenFields.isCurrentFieldContinuedLast()); + } + } + + updateDirty(); + goto_XY(where); + simulated = true; + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + break; + + case INSERT: + // we toggle it + oia.setInsertMode(oia.isInsertMode() ? false : true); + break; + + case HOME: + + // position to the home position set + if (lastPos + numCols + 1 != homePos) { + goto_XY(homePos - numCols - 1); + isInField(); + } + else + gotoField(1); + + break; + + case KEYPAD_0: + simulated = simulateKeyStroke('0'); + break; + + case KEYPAD_1: + simulated = simulateKeyStroke('1'); + break; + + case KEYPAD_2: + simulated = simulateKeyStroke('2'); + break; + + case KEYPAD_3: + simulated = simulateKeyStroke('3'); + break; + + case KEYPAD_4: + simulated = simulateKeyStroke('4'); + break; + + case KEYPAD_5: + simulated = simulateKeyStroke('5'); + break; + + case KEYPAD_6: + simulated = simulateKeyStroke('6'); + break; + + case KEYPAD_7: + simulated = simulateKeyStroke('7'); + break; + + case KEYPAD_8: + simulated = simulateKeyStroke('8'); + break; + + case KEYPAD_9: + simulated = simulateKeyStroke('9'); + break; + + case KEYPAD_PERIOD: + simulated = simulateKeyStroke('.'); + break; + + case KEYPAD_COMMA: + simulated = simulateKeyStroke(','); + break; + + case KEYPAD_MINUS: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + int s = screenFields.getCurrentField().getFieldShift(); + + if (s == 3 || s == 5 || s == 7) { + planes.setChar(lastPos, '-'); + resetDirty(lastPos); + advancePos(); + + if (fieldExit()) { + screenFields.setCurrentFieldMDT(); + + if (!screenFields.isCurrentFieldContinued()) { + gotoFieldNext(); + } + else { + do { + gotoFieldNext(); + } + while (screenFields + .isCurrentFieldContinuedMiddle() + || screenFields + .isCurrentFieldContinuedLast()); + } + + simulated = true; + updateDirty(); + + if (screenFields.isCurrentFieldAutoEnter()) + sendAid(AID_ENTER); + } + } + else { + displayError(ERR_FIELD_MINUS); + } + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + break; + + case FIELD_EXIT: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + resetDirty(lastPos); + boolean autoFE = screenFields.isCurrentFieldAutoEnter(); + + if (fieldExit()) { + screenFields.setCurrentFieldMDT(); + + if (!screenFields.isCurrentFieldContinued() && + !screenFields.isCurrentFieldAutoEnter()) { + gotoFieldNext(); + } + else { + do { + gotoFieldNext(); + + if (screenFields.isCurrentFieldContinued()) + fieldExit(); + } + while (screenFields.isCurrentFieldContinuedMiddle() + || screenFields.isCurrentFieldContinuedLast()); + } + } + + updateDirty(); + simulated = true; + + if (autoFE) + sendAid(AID_ENTER); + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + break; + + case FIELD_PLUS: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + resetDirty(lastPos); + boolean autoFE = screenFields.isCurrentFieldAutoEnter(); + + if (fieldExit()) { + screenFields.setCurrentFieldMDT(); + + if (!screenFields.isCurrentFieldContinued() && + !screenFields.isCurrentFieldAutoEnter()) { + gotoFieldNext(); + } + else { + do { + gotoFieldNext(); + } + while (screenFields.isCurrentFieldContinuedMiddle() + || screenFields.isCurrentFieldContinuedLast()); + } + } + + updateDirty(); + simulated = true; + + if (autoFE) + sendAid(AID_ENTER); + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + break; + + case FIELD_MINUS: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + int s = screenFields.getCurrentField().getFieldShift(); + + if (s == 3 || s == 5 || s == 7) { + planes.setChar(lastPos, '-'); + resetDirty(lastPos); + advancePos(); + boolean autoFE = screenFields.isCurrentFieldAutoEnter(); + + if (fieldExit()) { + screenFields.setCurrentFieldMDT(); + + if (!screenFields.isCurrentFieldContinued() + && !screenFields.isCurrentFieldAutoEnter()) { + gotoFieldNext(); + } + else { + do { + gotoFieldNext(); + } + while (screenFields.isCurrentFieldContinuedMiddle() + || screenFields.isCurrentFieldContinuedLast()); + } + } + + updateDirty(); + simulated = true; + + if (autoFE) + sendAid(AID_ENTER); + } + else { + displayError(ERR_FIELD_MINUS); + } + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + break; + + case BOF: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + int where = screenFields.getCurrentField().startPos(); + + if (where > 0) { + goto_XY(where); + } + + simulated = true; + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + resetDirty(lastPos); + break; + + case SYSREQ: + sessionVT.systemRequest(); + simulated = true; + break; + + case RESET: + if (isStatusErrorCode()) { + resetError(); + isInField(); + updateDirty(); + } + else { + setPrehelpState(false, oia.isKeyBoardLocked(), false); + } + + simulated = true; + break; + + case ATTN: + sessionVT.sendAttentionKey(); + simulated = true; + break; + + case DUP_FIELD: + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + if (screenFields.isCurrentFieldDupEnabled()) { + resetDirty(lastPos); + screenFields.getCurrentField().setFieldChar(lastPos, + (char) 0x1C); + screenFields.setCurrentFieldMDT(); + gotoFieldNext(); + updateDirty(); + simulated = true; + } + else { + displayError(ERR_DUP_KEY_NOT_ALLOWED); + } + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + + break; + + case NEW_LINE: + if (screenFields.getSize() > 0) { + int startRow = getRow(lastPos) + 1; + int startPos = lastPos; + + if (startRow == getRows()) + startRow = 0; + + setCursor(++startRow, 1); + + if (!isInField() && screenFields.getCurrentField() != null + && !screenFields.isCurrentFieldBypassField()) { + while (!isInField() + && screenFields.getCurrentField() != null + && !screenFields.isCurrentFieldBypassField()) { + // lets keep going + advancePos(); + + // Have we looped the screen? + if (lastPos == startPos) { + // if so then go back to starting point + goto_XY(startPos); + break; + } + } + } + } + + simulated = true; + break; + + case FAST_CURSOR_DOWN: + int rowNow = (getCurrentRow() - 1) + 3; + + if (rowNow > getRows() - 1) + rowNow = rowNow - getRows(); + + this.goto_XY(getPos(rowNow, getCurrentCol() - 1)); + simulated = true; + break; + + case FAST_CURSOR_UP: + rowNow = (getCurrentRow() - 1) - 3; + + if (rowNow < 0) + rowNow = (getRows()) + rowNow; + + this.goto_XY(getPos(rowNow, getCurrentCol() - 1)); + simulated = true; + break; + + case FAST_CURSOR_LEFT: + int colNow = (getCurrentCol() - 1) - 3; + rowNow = getCurrentRow() - 1; + + if (colNow <= 0) { + colNow = getColumns() + colNow; + rowNow--; + } + + if (rowNow < 0) + rowNow = getRows() - 1; + + process_XY(getPos(rowNow, colNow)); + simulated = true; + break; + + case FAST_CURSOR_RIGHT: + colNow = (getCurrentCol() - 1) + 3; + rowNow = getCurrentRow() - 1; + + if (colNow >= getColumns()) { + colNow = colNow - getColumns(); + rowNow++; + } + + if (rowNow > getRows() - 1) + rowNow = getRows() - rowNow; + + process_XY(getPos(rowNow, colNow)); + simulated = true; + break; + + default: + Log.i(TAG, " Mnemonic not supported " + mnem); + break; + } + + return simulated; + } + + protected boolean simulateKeyStroke(char c) { + if (isStatusErrorCode() && !Character.isISOControl(c) && !keyProcessed) { + if (resetRequired) return false; + + resetError(); + } + + boolean updateField = false; + boolean numericError = false; + boolean updatePos = false; + boolean autoEnter = false; + + if (!Character.isISOControl(c)) { + if (screenFields.getCurrentField() != null + && screenFields.withinCurrentField(lastPos) + && !screenFields.isCurrentFieldBypassField()) { + if (screenFields.isCurrentFieldFER() + && !screenFields.withinCurrentField(screenFields + .getCurrentFieldPos()) + && lastPos == screenFields.getCurrentField().endPos() + && screenFields.getCurrentFieldPos() > screenFields + .getCurrentField().endPos()) { + displayError(ERR_FIELD_EXIT_INVALID); + feError = true; + return false; + } + + switch (screenFields.getCurrentFieldShift()) { + case 0: // Alpha shift + case 2: // Numeric Shift + case 4: // Kakana Shift + updateField = true; + break; + + case 1: // Alpha Only + if (Character.isLetter(c) || c == ',' || c == '-' + || c == '.' || c == ' ') + updateField = true; + + break; + + case 3: // Numeric only + if (Character.isDigit(c) || c == '+' || c == ',' + || c == '-' || c == '.' || c == ' ') + updateField = true; + else + numericError = true; + + break; + + case 5: // Digits only + if (Character.isDigit(c)) + updateField = true; + else + displayError(ERR_NUMERIC_09); + + break; + + case 7: // Signed numeric + if (Character.isDigit(c) || c == '+' || c == '-') + if (lastPos == screenFields.getCurrentField().endPos() + && (c != '+' && c != '-')) + displayError(ERR_INVALID_SIGN); + else + updateField = true; + else + displayError(ERR_NUMERIC_09); + + break; + } + + if (updateField) { + if (screenFields.isCurrentFieldToUpper()) + c = Character.toUpperCase(c); + + updatePos = true; + resetDirty(lastPos); + + if (oia.isInsertMode()) { + if (endOfField(false) != screenFields.getCurrentField() + .endPos()) + shiftRight(lastPos); + else { + displayError(ERR_NO_ROOM_INSERT); + updatePos = false; + } + } + + if (updatePos) { + screenFields.getCurrentField().getKeyPos( + getRow(lastPos), getCol(lastPos)); + screenFields.getCurrentField().changePos(1); + planes.setChar(lastPos, c); + screenFields.setCurrentFieldMDT(); + + // if we have gone passed the end of the field then goto + // the next field + if (!screenFields.withinCurrentField(screenFields + .getCurrentFieldPos())) { + if (screenFields.isCurrentFieldAutoEnter()) { + autoEnter = true; + } + else if (!screenFields.isCurrentFieldFER()) + gotoFieldNext(); + else { + // screenFields.getCurrentField().changePos(1); + // + // if (screenFields. + // cursorPos == endPos) + // System.out.println("end of field"); + // + // feError != feError; + // if (feError) + // displayError(ERR_FIELD_EXIT_INVALID); + } + } + else + setCursor(screenFields.getCurrentField() + .getCursorRow() + 1, screenFields + .getCurrentField().getCursorCol() + 1); + } + + fireScreenChanged(); + + if (autoEnter) + sendAid(AID_ENTER); + } + else { + if (numericError) { + displayError(ERR_NUMERIC_ONLY); + } + } + } + else { + displayError(ERR_CURSOR_PROTECTED); + } + } + + return updatePos; + } + + /** + * Method: endOfField + * <p> + * + * convenience method that call endOfField with lastRow lastCol and passes + * the posSpace to that method + * + * @param posSpace + * value of type boolean - specifying to return the position of + * the the last space or not + * @return a value of type int - the screen postion (row * columns) + col + * + */ + private int endOfField(boolean posSpace) { + return endOfField(lastPos, posSpace); + } + + /** + * Method: endOfField + * <p> + * + * gets the position of the last character of the current field posSpace + * parameter tells the routine whether to return the position of the last + * space ( <= ' ') or the last non space posSpace == true last occurrence of + * char <= ' ' posSpace == false last occurrence of char > ' ' + * + * @param pos + * value of type int - position to start from + * @param posSpace + * value of type boolean - specifying to return the position of + * the the last space or not + * @return a value of type int - the screen postion (row * columns) + col + * + */ + private int endOfField(int pos, boolean posSpace) { + int endPos = screenFields.getCurrentField().endPos(); + int fePos = endPos; + // get the number of characters to the right + int count = endPos - pos; + + // first lets get the real ending point without spaces and the such + while (planes.getChar(endPos) <= ' ' && count-- > 0) { + endPos--; + } + + if (endPos == fePos) { + return endPos; + } + + screenFields.getCurrentField().getKeyPos(endPos); + + if (posSpace) screenFields.getCurrentField().changePos(+1); + + return screenFields.getCurrentFieldPos(); + } + + private boolean fieldExit() { + int pos = lastPos; + boolean mdt = false; + int end = endOfField(false); // get the ending position of the first + // non blank character in field + ScreenField sf = screenFields.getCurrentField(); + + if (sf.isMandatoryEnter() && end == sf.startPos()) { + displayError(ERR_MANDATORY_ENTER); + return false; + } + + // save off the current pos of the field for checking field exit required + // positioning. the getKeyPos resets this information so it is useless + // for comparing if we are positioned passed the end of field. + // Maybe this should be changed to not update the current cursor position + // of the field. + int currentPos = sf.getCurrentPos(); + // get the number of characters to the right + int count = (end - sf.startPos()) - sf.getKeyPos(pos); + + if (count == 0 && sf.isFER()) { + if (currentPos > sf.endPos()) { + mdt = true; + return mdt; + } + } + + for (; count >= 0; count--) { + planes.setChar(pos, initChar); + setDirty(pos); + pos++; + mdt = true; + } + + // This checks for a field minus because a field minus places + // a negative sign and then advances a position. If it is the + // end of the field where the minus is placed then this offset will + // place the count as -1. + if (count == -1) { + int s = sf.getFieldShift(); + + if (s == 3 || s == 5 || s == 7) { + mdt = true; + } + } + + int adj = sf.getAdjustment(); + + if (adj != 0) { + switch (adj) { + case 5: + rightAdjustField('0'); + sf.setRightAdjusted(); + break; + + case 6: + rightAdjustField(' '); + sf.setRightAdjusted(); + break; + + case 7: + sf.setMandatoryEntered(); + break; + } + } + else { + // we need to right adjust signed numeric fields as well. + if (sf.isSignedNumeric()) { + rightAdjustField(' '); + } + } + + return mdt; + } + + private void rightAdjustField(char fill) { + int end = endOfField(false); // get the ending position of the first + // non blank character in field + // get the number of characters to the right + int count = screenFields.getCurrentField().endPos() - end; + + // subtract 1 from count for signed numeric - note for later + if (screenFields.getCurrentField().isSignedNumeric()) { + if (planes.getChar(end - 1) != '-') + count--; + } + + int pos = screenFields.getCurrentField().startPos(); + + while (count-- >= 0) { + shiftRight(pos); + planes.setChar(pos, fill); + setDirty(pos); + } + } + + private void shiftLeft(int sPos) { + int endPos = 0; + int pos = sPos; + int pPos = sPos; + ScreenField sf = screenFields.getCurrentField(); + int end; + int count; + + do { + end = endOfField(pPos, false); // get the ending position of the + // first + // non blank character in field + count = (end - screenFields.getCurrentField().startPos()) + - screenFields.getCurrentField().getKeyPos(pPos); + + // now we loop through and shift the remaining characters to the + // left + while (count-- > 0) { + pos++; + planes.setChar(pPos, planes.getChar(pos)); + setDirty(pPos); + pPos = pos; + } + + if (screenFields.isCurrentFieldContinued()) { + gotoFieldNext(); + + if (screenFields.getCurrentField().isContinuedFirst()) + break; + + pos = screenFields.getCurrentField().startPos(); + planes.setChar(pPos, planes.getChar(pos)); + setDirty(pPos); + pPos = pos; + } + } + while (screenFields.isCurrentFieldContinued() + && !screenFields.getCurrentField().isContinuedFirst()); + + if (end >= 0 && count >= -1) { + endPos = end; + } + else { + endPos = sPos; + } + + screenFields.setCurrentField(sf); + planes.setChar(endPos, initChar); + setDirty(endPos); + goto_XY(screenFields.getCurrentFieldPos()); + sf = null; + } + + private void shiftRight(int sPos) { + int end = endOfField(true); // get the ending position of the first + // non blank character in field + int pos = end; + int pPos = end; + int count = end - sPos; + + // now we loop through and shift the remaining characters to the right + while (count-- > 0) { + pos--; + planes.setChar(pPos, planes.getChar(pos)); + setDirty(pPos); + pPos = pos; + } + } + + public int getRow(int pos) { + // if (pos == 0) + // return 1; + int row = pos / numCols; + + if (row < 0) { + row = lastPos / numCols; + } + + if (row > (lenScreen / numCols) - 1) + row = (lenScreen / numCols) - 1; + + return row; + } + + public int getCol(int pos) { + int col = pos % (getColumns()); + + if (col > 0) return col; + + return 0; + } + + /** + * This routine is 0 based offset. So to get row 20,1 then pass row 19,0 + * + * @param row + * @param col + * @return + */ + public int getPos(int row, int col) { + return (row * numCols) + col; + } + + /** + * Current position is based on offsets of 1,1 not 0,0 of the current + * position of the screen + * + * @return int + */ + public int getCurrentPos() { + // return lastPos + numCols + 1; + return lastPos + 1; + } + + /** + * I got this information from a tcp trace of each error. I could not find + * any documenation for this. Maybe there is but I could not find it. If + * anybody finds this documention could you please send me a copy. Please + * note that I did not look that hard either. + * <p> + * 0000: 00 50 73 1D 89 81 00 50 DA 44 C8 45 08 00 45 00 .Ps....P.D.E..E. + * </p> + * <p> + * 0010: 00 36 E9 1C 40 00 80 06 9B F9 C1 A8 33 58 C0 A8 .6..@...k....3X.. + * </p> + * <p> + * 0020: C0 02 06 0E 00 17 00 52 6E 88 73 40 DE CB 50 18 .......Rn.s@..P. + * </p> + * <p> + * 0030: 20 12 3C 53 00 00 00 0C 12 A0 00 00 04 01 00 00 . <S............ + * </p> + * <p> + * 0040: 00 05 FF EF .... ----------|| The 00 XX is the code to be sent. I + * found the following <table BORDER COLS=2 WIDTH="50%" > + * <tr> + * <td>ERR_CURSOR_PROTECTED</td> + * <td>0x05</td> + * </tr> + * <tr> + * <td>ERR_INVALID_SIGN</td> + * <td>0x11</td> + * </tr> + * <tr> + * <td>ERR_NO_ROOM_INSERT</td> + * <td>0x12</td> + * </tr> + * <tr> + * <td>ERR_NUMERIC_ONLY</td> + * <td>0x09</td> + * </tr> + * <tr> + * <td>ERR_NUMERIC_09</td> + * <td>0x10</td> + * </tr> + * <tr> + * <td>ERR_FIELD_MINUS</td> + * <td>0x16</td> + * </tr> + * <tr> + * <td>ERR_ENTER_NOT_ALLOWED</td> + * <td>0x20</td> + * </tr> + * <tr> + * <td>ERR_MANDATORY_ENTER</td> + * <td>0x21</td> + * </tr> + * <tr> + * <td>ERR_ENTER_NOT_ALLOWED</td> + * <td>0x20</td> + * </tr> + * </table> I am tired of typing and they should be self explanitory. Finding + * them in the first place was the pain. + * </p> + * + * @param ec error code + */ + private void displayError(int ec) { + saveHomePos = homePos; + homePos = lastPos + numCols + 1; + pendingInsert = true; + sessionVT.sendNegResponse2(ec); + } + + private void process_XY(int pos) { + if (pos < 0) + pos = lenScreen + pos; + + if (pos > lenScreen - 1) + pos = pos - lenScreen; + + // if there was a field exit error then we need to treat the movement + // of the cursor in a special way that equals that of Client Access. + // If the cursor is moved from the field then we need to reset the + // position within the field so that the last character can be typed + // over again instead of sending the field exit error again. + // We also need to reset the field exit error flag. + // + // How we know we have a field exit error is when the field position is + // set beyond the end of the field and a character is then typed we can + // not position that character. To reset this we need to set the next + // position of the field to not be beyond the end of field but to the + // last character. + // + // Now to make it work like Client Access if the cursor is a back space + // then do not move the cursor but place it on the last field. All + // other keys will reset the field position so that entering over the + // last character will not cause an error but replace that character or + // just plain move the cursor if the key was to do that. + ScreenField sf = screenFields.getCurrentField(); + + if (feError) { + feError = false; + sf.changePos(-1); + } + else { + if (sf != null && sf.isFER()) { + if ((sf.getCurrentPos() + > sf.endPos())) { + if (sf.withinField(pos)) { + sf.getKeyPos(pos); + return; + } + + sf.getKeyPos(sf.endPos()); + } + } + + goto_XY(pos); + } + } + + public boolean isUsingGuiInterface() { + return guiInterface; + } + + /** + * Convinience class to return if the cursor is in a field or not. + * + * @return true or false + */ + + protected boolean isInField() { + return isInField(lastPos, true); + } + + /** + * + * Convinience class to return if the position that is passed is in a field + * or not. If it is then the chgToField parameter will change the current + * field to this field where the position indicates + * + * @param pos + * @param chgToField + * @return true or false + */ + public boolean isInField(int pos, boolean chgToField) { + return screenFields.isInField(pos, chgToField); + } + + /** + * + * Convinience class to return if the position that is passed is in a field + * or not. If it is then the field at this position becomes the current + * working field + * + * @param pos + * @return true or false + */ + public boolean isInField(int pos) { + return screenFields.isInField(pos, true); + } + + /** + * Convinience class to return if the position at row and column that is + * passed is in a field or not. If it is then the field at this position + * becomes the current working field. + * + * @param row + * @param col + * @return true or false + */ + public boolean isInField(int row, int col) { + return isInField(row, col, true); + } + + /** + * + * Convinience class to return if the position at row and column that is + * passed is in a field or not. If it is then the chgToField parameter will + * change the current field to this field where the row and column + * indicates. + * + * @param row + * @param col + * @param chgToField + * @return true or false + */ + public boolean isInField(int row, int col, boolean chgToField) { + return screenFields.isInField((row * numCols) + col, chgToField); + } + + /** + * Gets the length of the screen - number of rows times number of columns + * + * @return int value of screen length + */ + public int getScreenLength() { + return lenScreen; + } + + /** + * Get the number or rows available. + * + * @return number of rows + */ + public int getRows() { + return numRows; + } + + /** + * Get the number of columns available. + * + * @return number of columns + */ + public int getColumns() { + return numCols; + } + + /** + * Get the current row where the cursor is + * + * @return the cursor current row position 1,1 based + */ + public int getCurrentRow() { + return (lastPos / numCols) + 1; + } + + /** + * Get the current column where the cursor is + * + * @return the cursor current column position 1,1 based + */ + public int getCurrentCol() { + return (lastPos % numCols) + 1; + } + + /** + * The last position of the cursor on the screen - Note - position is based + * 0,0 + * + * @return last position + */ + protected int getLastPos() { + return lastPos; + } + + /** + * Hotspot More... string + * + * @return string literal of More... + */ + public StringBuffer getHSMore() { + return hsMore; + } + + /** + * Hotspot Bottom string + * + * @return string literal of Bottom + */ + public StringBuffer getHSBottom() { + return hsBottom; + } + + /** + * + * Return the screen represented as a character array + * + * @return character array containing the text + */ + public char[] getScreenAsChars() { + char[] sac = new char[lenScreen]; + char c; + + for (int x = 0; x < lenScreen; x++) { + c = planes.getChar(x); + + // only draw printable characters (in this case >= ' ') + if ((c >= ' ') && (!planes.isAttributePlace(x))) { + sac[x] = c; + // TODO: implement the underline check here + // if (screen[x].underLine && c <= ' ') + // sac[x] = '_'; + } + else + sac[x] = ' '; + } + + return sac; + } + + public char[] getData(int startRow, int startCol, int endRow, int endCol, int plane) { + try { + int from = getPos(startRow, startCol); + int to = getPos(endRow, endCol); + + if (from > to) { + int f = from; + to = f; + from = f; + } + + return planes.getPlaneData(from, to, plane); + } + catch (Exception oe) { + return null; + } + } + + /** + * <p> + * GetScreen retrieves the various planes associated with the presentation + * space. The data is returned as a linear array of character values in the + * array provided. The array is not terminated by a null character except + * when data is retrieved from the text plane, in which case a single null + * character is appended. + * </p> + * <p> + * The application must supply a buffer for the returned data and the length + * of the buffer. Data is returned starting from the beginning of the + * presentation space and continuing until the buffer is full or the entire + * plane has been copied. For text plane data, the buffer must include one + * extra position for the terminating null character. + * <p> + * + * @param buffer + * @param bufferLength + * @param plane + * @return The number of characters copied to the buffer + * @throws OhioException + */ + + public synchronized int GetScreen(char buffer[], int bufferLength, int plane) + // throws OhioException { + { + return GetScreen(buffer, bufferLength, 0, lenScreen, plane); + } + + /** + * <p> + * GetScreen retrieves the various planes associated with the presentation + * space. The data is returned as a linear array of character values in the + * array provided. The array is not terminated by a null character except + * when data is retrieved from the text plane, in which case a single null + * character is appended. + * </p> + * <p> + * The application must supply a buffer for the returned data and the length + * of the buffer. Data is returned starting from the given position and + * continuing until the specified number of characters have been copied, the + * buffer is full or the entire plane has been copied. For text plane data, + * the buffer must include one extra position for the terminating null character. + * </p> + * + * @param buffer + * @param bufferLength + * @param from + * @param length + * @param plane + * @return The number of characters copied to the buffer + * @throws OhioException + */ + + public synchronized int GetScreen(char buffer[], int bufferLength, int from, + int length, int plane) + // throws OhioException { + { + return planes.GetScreen(buffer, bufferLength, from, length, plane); + } + + /** + * <p> + * GetScreen retrieves the various planes associated with the presentation + * space. The data is returned as a linear array of character values in the + * array provided. The array is not terminated by a null character except + * when data is retrieved from the text plane, in which case a single null + * character is appended. + * </p> + * <p> + * The application must supply a buffer for the returned data and the length + * of the buffer. Data is returned starting from the given coordinates and + * continuing until the specified number of characters have been copied, + * the buffer is full, or the entire plane has been copied. For text plane + * data, the buffer must include one extra position for the terminating null + * character. + * </p> + * + * @param buffer + * @param bufferLength + * @param row + * @param col + * @param length + * @param plane + * @return The number of characters copied to the buffer. + * @throws OhioException + */ + + public synchronized int GetScreen(char buffer[], int bufferLength, int row, + int col, int length, int plane) + // throws OhioException { + { + // Call GetScreen function after converting row and column to + // a position. + return planes.GetScreen(buffer, bufferLength, row, col, length, plane); + } + + /** + * <p> + * GetScreenRect retrieves data from the various planes associated with the + * presentation space. The data is returned as a linear array of character + * values in the buffer provided. + * </p> + * + * <p> + * The application supplies two positions that represent opposing corners of + * a rectangle within the presentation space. The starting and ending + * positions can have any spatial relationship to each other. The data + * returned starts from the row containing the upper-most point to the row + * containing the lower-most point, and from the left-most column to the + * right-most column. + * </p> + * <p> + * The specified buffer must be at least large enough to contain the number + * of characters in the rectangle. If the buffer is too small, no data is + * copied and zero is returned by the method. Otherwise, the method returns + * the number of characters copied. + * </p> + * + * @param buffer + * @param bufferLength + * @param startPos + * @param endPos + * @param plane + * @return The number of characters copied to the buffer + * @throws OhioException + */ + + public synchronized int GetScreenRect(char buffer[], int bufferLength, + int startPos, int endPos, int plane) + // throws OhioException { + { + return planes.GetScreenRect(buffer, bufferLength, startPos, endPos, plane); + } + + /** + * <p> + * GetScreenRect retrieves data from the various planes associated with the + * presentation space. The data is returned as a linear array of character + * values in the buffer provided. The buffer is not terminated by a null + * character. + * </p> + * <p> + * The application supplies two coordinates that represent opposing corners + * of a rectangle within the presentation space. The starting and ending + * coordinates can have any spatial relationship to each other. The data + * returned starts from the row containing the upper-most point to the row + * containing the lower-most point, and from the left-most column to the + * right-most column. + * </p> + * <p> + * The specified buffer must be at least large enough to contain the number + * of characters in the rectangle. If the buffer is too small, no data is + * copied and zero is returned by the method. Otherwise, the method returns + * the number of characters copied. + * </p> + * + * @param buffer + * @param bufferLength + * @param startRow + * @param startCol + * @param endRow + * @param endCol + * @param plane + * @return The number characters copied to the buffer + * @throws OhioException + */ + + public synchronized int GetScreenRect(char buffer[], int bufferLength, + int startRow, int startCol, + int endRow, int endCol, int plane) + // throws OhioException { + { + return planes.GetScreenRect(buffer, bufferLength, startRow, startCol, endRow, + endCol, plane); + } + + public synchronized boolean[] getActiveAidKeys() { + return sessionVT.getActiveAidKeys(); + } + + protected synchronized void setScreenData(String text, int location) { + // throws OhioException { + if (location < 0 || location > lenScreen) { + return; + // throw new OhioException(sessionVT.getSessionConfiguration(), + // OhioScreen5250.class.getName(), "osohio.screen.ohio00300", 1); + } + + int pos = location; + int l = text.length(); + boolean updated = false; + boolean flag = false; + int x = 0; + + for (; x < l; x++) { + if (isInField(pos + x, true)) { + if (!screenFields.getCurrentField().isBypassField()) { + if (!flag) { + screenFields.getCurrentField().setMDT(); + updated = true; + resetDirty(pos + x); + screenFields.setMasterMDT(); + flag = true; + } + + planes.screen[pos + x] = text.charAt(x); + setDirty(pos + x); + } + } + } + + lastPos = pos + x; + + if (updated) { + fireScreenChanged(); + } + } + + /** + * This routine is based on offset 1,1 not 0,0 it will translate to offset + * 0,0 and call the goto_XY(int pos) it is mostly used from external classes + * that use the 1,1 offset + * + * @param row + * @param col + */ + public void setCursor(int row, int col) { + goto_XY(((row - 1) * numCols) + (col - 1)); + } + + // this routine is based on offset 0,0 not 1,1 + protected void goto_XY(int pos) { + lastPos = pos; + updateCursorLoc(); + } + + /* + * set the content of the field at (l,c) to data + * if l == -1, set the current field contents to data + */ + public void setField(int l, int c, char [] data) { + ScreenField cf; + + if (l >= 0) { + lastPos = l * numCols + c; + + while (!isInField()) advancePos(); + + setDirty(lastPos); + fireCursorChanged(); + } + + if ((data != null) && (data.length > 0)) { + cf = screenFields.getCurrentField(); + cf.setString(new String(data)); + lastPos = cf.getStartPos(); + setDirty(lastPos); + setDirty(lastPos + cf.getLength()); + lastPos += data.length; + + if (!isInField()) { + gotoFieldNext(); + isInField(); + cf = screenFields.getCurrentField(); + lastPos = cf.getStartPos(); + } + + setDirty(lastPos); + fireCursorChanged(); + } + + updateDirty(); + } + + /** + * Set the current working field to the field number specified. + * + * @param f - + * numeric field number on the screen + * @return true or false whether it was sucessful + */ + public boolean gotoField(int f) { + int sizeFields = screenFields.getSize(); + + if (f > sizeFields || f <= 0) + return false; + + screenFields.setCurrentField(screenFields.getField(f - 1)); + + while (screenFields.isCurrentFieldBypassField() && f < sizeFields) { + screenFields.setCurrentField(screenFields.getField(f++)); + } + + return gotoField(screenFields.getCurrentField()); + } + + /** + * Convenience method to set the field object passed as the currect working + * screen field + * + * @param f + * @return true or false whether it was sucessful + * @see org.tn5250j.ScreenField + */ + protected boolean gotoField(ScreenField f) { + if (f != null) { + goto_XY(f.startPos()); + return true; + } + + return false; + } + + /** + * Convenience class to position the cursor to the next word on the screen + * + */ + private void gotoNextWord() { + int pos = lastPos; + + if (planes.getChar(lastPos) > ' ') { + advancePos(); + + // get the next space character + while (planes.getChar(lastPos) > ' ' && pos != lastPos) { + advancePos(); + } + } + else + advancePos(); + + // now that we are positioned on the next space character get the + // next none space character + while (planes.getChar(lastPos) <= ' ' && pos != lastPos) { + advancePos(); + } + } + + /** + * Convenience class to position the cursor to the previous word on the + * screen + * + */ + private void gotoPrevWord() { + int pos = lastPos; + changePos(-1); + + // position previous white space character + while (planes.getChar(lastPos) <= ' ') { + changePos(-1); + + if (pos == lastPos) + break; + } + + changePos(-1); + + // get the previous space character + while (planes.getChar(lastPos) > ' ' && pos != lastPos) { + changePos(-1); + } + + // and position one position more should give us the beginning of word + advancePos(); + } + + /** + * Convinience class to position to the next field on the screen. + * + * @see org.tn5250j.ScreenFields + */ + private void gotoFieldNext() { + if (screenFields.isCurrentFieldHighlightedEntry()) + unsetFieldHighlighted(screenFields.getCurrentField()); + + screenFields.gotoFieldNext(); + + if (screenFields.isCurrentFieldHighlightedEntry()) + setFieldHighlighted(screenFields.getCurrentField()); + } + + /** + * Convinience class to position to the previous field on the screen. + * + * @see org.tn5250j.ScreenFields + */ + private void gotoFieldPrev() { + if (screenFields.isCurrentFieldHighlightedEntry()) + unsetFieldHighlighted(screenFields.getCurrentField()); + + screenFields.gotoFieldPrev(); + + if (screenFields.isCurrentFieldHighlightedEntry()) + setFieldHighlighted(screenFields.getCurrentField()); + } + + /* *** NEVER USED LOCALLY ************************************************** */ + // /** + // * Used to restrict the cursor to a particular position on the screen. Used + // * in combination with windows to restrict the cursor to the active window + // * show on the screen. + // * + // * Not supported yet. Please implement me :-( + // * + // * @param depth + // * @param width + // */ + // protected void setRestrictCursor(int depth, int width) { + // + // restrictCursor = true; + // // restriction + // + // } + + /** + * Creates a window on the screen + * + * @param depth + * @param width + * @param type + * @param gui + * @param monoAttr + * @param colorAttr + * @param ul + * @param upper + * @param ur + * @param left + * @param right + * @param ll + * @param bottom + * @param lr + */ + protected void createWindow(int depth, int width, int type, boolean gui, + int monoAttr, int colorAttr, int ul, int upper, int ur, int left, + int right, int ll, int bottom, int lr) { + int c = getCol(lastPos); + int w = 0; + width++; + w = width; + // set leading attribute byte + // screen[lastPos].setCharAndAttr(initChar, initAttr, true); + planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); + setDirty(lastPos); + advancePos(); + // set upper left + // screen[lastPos].setCharAndAttr((char) ul, colorAttr, false); + planes.setScreenCharAndAttr(lastPos, (char) ul, colorAttr, false); + + if (gui) { + // screen[lastPos].setUseGUI(UPPER_LEFT); + planes.setUseGUI(lastPos, UPPER_LEFT); + } + + setDirty(lastPos); + advancePos(); + + // draw top row + + while (w-- >= 0) { + // screen[lastPos].setCharAndAttr((char) upper, colorAttr, false); + planes.setScreenCharAndAttr(lastPos, (char) upper, colorAttr, false); + + if (gui) { + // screen[lastPos].setUseGUI(UPPER); + planes.setUseGUI(lastPos, UPPER); + } + + setDirty(lastPos); + advancePos(); + } + + // set upper right + // screen[lastPos].setCharAndAttr((char) ur, colorAttr, false); + planes.setScreenCharAndAttr(lastPos, (char) ur, colorAttr, false); + + if (gui) { + // screen[lastPos].setUseGUI(UPPER_RIGHT); + planes.setUseGUI(lastPos, UPPER_RIGHT); + } + + setDirty(lastPos); + advancePos(); + // set ending attribute byte + planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); + setDirty(lastPos); + lastPos = ((getRow(lastPos) + 1) * numCols) + c; + + // now handle body of window + while (depth-- > 0) { + // set leading attribute byte + planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); + setDirty(lastPos); + advancePos(); + // set left + planes.setScreenCharAndAttr(lastPos, (char) left, colorAttr, false); + + if (gui) { + planes.setUseGUI(lastPos, GUI_LEFT); + } + + setDirty(lastPos); + advancePos(); + w = width; + + // fill it in + while (w-- >= 0) { + // screen[lastPos].setCharAndAttr(initChar, initAttr, true); + planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); + // screen[lastPos].setUseGUI(NO_GUI); + planes.setUseGUI(lastPos, NO_GUI); + setDirty(lastPos); + advancePos(); + } + + // set right + // screen[lastPos].setCharAndAttr((char) right, colorAttr, false); + planes.setScreenCharAndAttr(lastPos, (char) right, colorAttr, false); + + if (gui) { + // screen[lastPos].setUseGUI(RIGHT); + planes.setUseGUI(lastPos, GUI_RIGHT); + } + + setDirty(lastPos); + advancePos(); + // set ending attribute byte + // screen[lastPos].setCharAndAttr(initChar, initAttr, true); + planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); + setDirty(lastPos); + lastPos = ((getRow(lastPos) + 1) * numCols) + c; + } + + // set leading attribute byte + // screen[lastPos].setCharAndAttr(initChar, initAttr, true); + planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); + setDirty(lastPos); + advancePos(); + // set lower left + // screen[lastPos].setCharAndAttr((char) ll, colorAttr, false); + planes.setScreenCharAndAttr(lastPos, (char) ll, colorAttr, false); + + if (gui) { + // screen[lastPos].setUseGUI(LOWER_LEFT); + planes.setUseGUI(lastPos, LOWER_LEFT); + } + + setDirty(lastPos); + advancePos(); + w = width; + + // draw bottom row + while (w-- >= 0) { + planes.setScreenCharAndAttr(lastPos, (char) bottom, colorAttr, false); + + if (gui) { + planes.setUseGUI(lastPos, BOTTOM); + } + + setDirty(lastPos); + advancePos(); + } + + // set lower right + planes.setScreenCharAndAttr(lastPos, (char) lr, colorAttr, false); + + if (gui) { + planes.setUseGUI(lastPos, LOWER_RIGHT); + } + + setDirty(lastPos); + advancePos(); + // set ending attribute byte + planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); + setDirty(lastPos); + } + + /** + * Creates a scroll bar on the screen using the parameters provided. + * ** we only support vertical scroll bars at the time. + * + * @param flag - + * type to draw - vertical or horizontal + * @param totalRowScrollable + * @param totalColScrollable + * @param sliderRowPos + * @param sliderColPos + * @param sbSize + */ + protected void createScrollBar(int flag, int totalRowScrollable, + int totalColScrollable, int sliderRowPos, int sliderColPos, + int sbSize) { + // System.out.println("Scrollbar flag: " + flag + + // " scrollable Rows: " + totalRowScrollable + + // " scrollable Cols: " + totalColScrollable + + // " thumb Row: " + sliderRowPos + + // " thumb Col: " + sliderColPos + + // " size: " + sbSize + + // " row: " + getRow(lastPos) + + // " col: " + getCol(lastPos)); + int sp = lastPos; + int size = sbSize - 2; + int thumbPos = (int)(size * ((float) sliderColPos / (float) totalColScrollable)); + // System.out.println(thumbPos); + planes.setScreenCharAndAttr(sp, ' ', 32, false); + planes.setUseGUI(sp, BUTTON_SB_UP); + int ctr = 0; + + while (ctr < size) { + sp += numCols; + planes.setScreenCharAndAttr(sp, ' ', 32, false); + + if (ctr == thumbPos) + planes.setUseGUI(sp, BUTTON_SB_THUMB); + else + planes.setUseGUI(sp, BUTTON_SB_GUIDE); + + ctr++; + } + + sp += numCols; + planes.setScreenCharAndAttr(sp, ' ', 32, false); + planes.setUseGUI(sp, BUTTON_SB_DN); + } + + /** + * Write the title of the window that is on the screen + * + * @param pos + * @param depth + * @param width + * @param orientation + * @param monoAttr + * @param colorAttr + * @param title + */ + protected void writeWindowTitle(int pos, int depth, int width, + byte orientation, int monoAttr, int colorAttr, StringBuffer title) { + int len = title.length(); + + // get bit 0 and 1 for interrogation + switch (orientation & 0xc0) { + case 0x40: // right + pos += (4 + width - len); + break; + + case 0x80: // left + pos += 2; + break; + + default: // center + // this is to place the position to the first text position of the + // window + // the position passed in is the first attribute position, the next + // is the border character and then there is another attribute after + // that. + pos += (3 + ((width / 2) - (len / 2))); + break; + } + + // if bit 2 is on then this is a footer + if ((orientation & 0x20) == 0x20) + pos += ((depth + 1) * numCols); + + // System.out.println(pos + "," + width + "," + len+ "," + getRow(pos) + // + "," + getCol(pos) + "," + ((orientation >> 6) & 0xf0)); + + for (int x = 0; x < len; x++) { + planes.setChar(pos, title.charAt(x)); + planes.setUseGUI(pos++, NO_GUI); + } + } + + /** + * Roll the screen up or down. + * + * Byte 1: Bit 0 0 = Roll up 1 = Roll down Bits 1-2 Reserved Bits 3-7 Number + * of lines that the designated area is to be rolled Byte 2: Bits 0-7 Line + * number defining the top line of the area that will participate in the + * roll. Byte 3: Bits 0-7 Line number defining the bottom line of the area + * that will participate in the roll. + * + * @param direction + * @param topLine + * @param bottomLine + */ + protected void rollScreen(int direction, int topLine, int bottomLine) { + // get the number of lines which are the last 5 bits + /* int lines = direction & 0x7F; */ + // get the direction of the roll which is the first bit + // 0 - up + // 1 - down + int updown = direction & 0x80; + final int lines = direction & 0x7F; + // calculate the reference points for the move. + int start = this.getPos(topLine - 1, 0); + int end = this.getPos(bottomLine - 1, numCols - 1); + int len = end - start; + + // System.out.println(" starting roll"); + // dumpScreen(); + switch (updown) { + case 0: + + // Now round em up and head em UP. + for (int x = start; x < end + numCols; x++) { + if (x + lines * numCols >= lenScreen) { + //Clear at the end + planes.setChar(x, ' '); + } + else { + planes.setChar(x, planes.getChar(x + lines * numCols)); + } + } + + break; + + case 1: + + // Now round em up and head em DOWN. + for (int x = end + numCols; x > 0; x--) { + if ((x - lines * numCols) < 0) { + //Do nothing ... tooo small!!! + } + else { + planes.setChar(x - lines * numCols, planes.getChar(x)); + //and clear + planes.setChar(x, ' '); + } + } + + break; + + default: + Log.w(TAG, " Invalid roll parameter - please report this"); + } + + // System.out.println(" end roll"); + // dumpScreen(); + } + + public void dumpScreen() { + StringBuffer sb = new StringBuffer(); + char[] s = getScreenAsChars(); + int c = getColumns(); + int l = getRows() * c; + int col = 0; + + for (int x = 0; x < l; x++, col++) { + sb.append(s[x]); + + if (col == c) { + sb.append('\n'); + col = 0; + } + } + + Log.i(TAG, sb.toString()); + } + + /** + * Add a field to the field format table. + * + * @param attr - Field attribute + * @param len - length of field + * @param ffw1 - Field format word 1 + * @param ffw2 - Field format word 2 + * @param fcw1 - Field control word 1 + * @param fcw2 - Field control word 2 + */ + protected void addField(int attr, int len, int ffw1, int ffw2, int fcw1, + int fcw2) { + lastAttr = attr; + planes.setScreenCharAndAttr(lastPos, initChar, lastAttr, true); + setDirty(lastPos); + advancePos(); + ScreenField sf = null; + + // from 14.6.12 for Start of Field Order 5940 function manual + // examine the format table for an entry that begins at the current + // starting address plus 1. + if (screenFields.existsAtPos(lastPos)) { + screenFields.setCurrentFieldFFWs(ffw1, ffw2); + } + else { + sf = screenFields.setField(attr, getRow(lastPos), getCol(lastPos), + len, ffw1, ffw2, fcw1, fcw2); + lastPos = sf.startPos(); + int x = len; + boolean gui = guiInterface; + + if (sf.isBypassField()) + gui = false; + + while (x-- > 0) { + if (planes.getChar(lastPos) == 0) + planes.setScreenCharAndAttr(lastPos, ' ', lastAttr, false); + else + planes.setScreenAttr(lastPos, lastAttr); + + if (gui) { + planes.setUseGUI(lastPos, FIELD_MIDDLE); + } + + // now we set the field plane attributes + planes.setScreenFieldAttr(lastPos, ffw1); + advancePos(); + } + + if (gui) + if (len > 1) { + planes.setUseGUI(sf.startPos(), FIELD_LEFT); + + if (lastPos > 0) + planes.setUseGUI(lastPos - 1, FIELD_RIGHT); + else + planes.setUseGUI(lastPos, FIELD_RIGHT); + } + else { + planes.setUseGUI(lastPos - 1, FIELD_ONE); + } + + // screen[lastPos].setCharAndAttr(initChar,initAttr,true); + setEndingAttr(initAttr); + lastPos = sf.startPos(); + } + + // if (fcw1 != 0 || fcw2 != 0) { + // System.out.println("lr = " + lastRow + " lc = " + lastCol + " " + + // sf.toString()); + // } + sf = null; + } + + + // public void addChoiceField(int attr, int len, int ffw1, int ffw2, int + // fcw1, int fcw2) { + // + // lastAttr = attr; + // + // screen[lastPos].setCharAndAttr(initChar,lastAttr,true); + // setDirty(lastPos); + // + // advancePos(); + // + // boolean found = false; + // ScreenField sf = null; + // + // // from 14.6.12 for Start of Field Order 5940 function manual + // // examine the format table for an entry that begins at the current + // // starting address plus 1. + // for (int x = 0;x < sizeFields; x++) { + // sf = screenFields[x]; + // + // if (lastPos == sf.startPos()) { + // screenFields.getCurrentField() = sf; + // screenFields.getCurrentField().setFFWs(ffw1,ffw2); + // found = true; + // } + // + // } + // + // if (!found) { + // sf = + // setField(attr,getRow(lastPos),getCol(lastPos),len,ffw1,ffw2,fcw1,fcw2); + // + // lastPos = sf.startPos(); + // int x = len; + // + // boolean gui = guiInterface; + // if (sf.isBypassField()) + // gui = false; + // + // while (x-- > 0) { + // + // if (screen[lastPos].getChar() == 0) + // screen[lastPos].setCharAndAttr(' ',lastAttr,false); + // else + // screen[lastPos].setAttribute(lastAttr); + // + // if (gui) + // screen[lastPos].setUseGUI(FIELD_MIDDLE); + // + // advancePos(); + // + // } + // + // if (gui) + // if (len > 1) { + // screen[sf.startPos()].setUseGUI(FIELD_LEFT); + // if (lastPos > 0) + // screen[lastPos-1].setUseGUI(FIELD_RIGHT); + // else + // screen[lastPos].setUseGUI(FIELD_RIGHT); + // + // } + // else + // screen[lastPos-1].setUseGUI(FIELD_ONE); + // + // setEndingAttr(initAttr); + // + // lastPos = sf.startPos(); + // } + // + // // if (fcw1 != 0 || fcw2 != 0) { + // // + // // System.out.println("lr = " + lastRow + " lc = " + lastCol + " " + + // sf.toString()); + // // } + // sf = null; + // + // } + + /** + * Return the fields that are contained in the Field Format Table + * + * @return ScreenFields object + * @see org.tn5250j.ScreenFields + */ + public ScreenFields getScreenFields() { + return screenFields; + } + + /** + * Redraw the fields on the screen. Used for gui enhancement to redraw the + * fields when toggling + * + */ + protected void drawFields() { + ScreenField sf; + int sizeFields = screenFields.getSize(); + + for (int x = 0; x < sizeFields; x++) { + sf = screenFields.getField(x); + + if (!sf.isBypassField()) { + int pos = sf.startPos(); + int l = sf.length; + boolean f = true; + + if (l >= lenScreen) + l = lenScreen - 1; + + if (l > 1) { + while (l-- > 0) { + if (guiInterface && f) { + planes.setUseGUI(pos, FIELD_LEFT); + f = false; + } + else { + planes.setUseGUI(pos, FIELD_MIDDLE); + } + + if (guiInterface && l == 0) { + planes.setUseGUI(pos, FIELD_RIGHT); + } + + setDirty(pos++); + } + } + else { + planes.setUseGUI(pos, FIELD_ONE); + } + } + } + + //updateDirty(); + } + + /** + * Draws the field on the screen. Used to redraw or change the attributes of + * the field. + * + * @param sf - + * Field to be redrawn + * @see org.tn5250j.ScreenField.java + */ + protected void drawField(ScreenField sf) { + int pos = sf.startPos(); + int x = sf.length; + + while (x-- > 0) { + setDirty(pos++); + } + + updateDirty(); + } + + /** + * Set the field to be displayed as highlighted. + * + * @param sf - + * Field to be highlighted + */ + protected void setFieldHighlighted(ScreenField sf) { + int pos = sf.startPos(); + int x = sf.length; + int na = sf.getHighlightedAttr(); + + while (x-- > 0) { + planes.setScreenAttr(pos, na); + setDirty(pos++); + } + + fireScreenChanged(); + } + + /** + * Draw the field as un higlighted. This is used to reset the field + * presentation on the screen after the field is exited. + * + * @param sf - + * Field to be unhighlighted + */ + protected void unsetFieldHighlighted(ScreenField sf) { + int pos = sf.startPos(); + int x = sf.length; + int na = sf.getAttr(); + + while (x-- > 0) { + planes.setScreenAttr(pos, na); + setDirty(pos++); + } + + fireScreenChanged(); + } + + protected void setChar(int cByte) { + if (lastPos > 0) { + lastAttr = planes.getCharAttr(lastPos - 1); + } + + if (cByte > 0 && (char)cByte < ' ') { + planes.setScreenCharAndAttr(lastPos, (char) 0x00, 33, false); + setDirty(lastPos); + advancePos(); + } + else { + planes.setScreenCharAndAttr(lastPos, (char) cByte, lastAttr, false); + setDirty(lastPos); + + if (guiInterface && !isInField(lastPos, false)) { + planes.setUseGUI(lastPos, NO_GUI); + } + + advancePos(); + } + } + + protected void setEndingAttr(int cByte) { + int attr = lastAttr; + setAttr(cByte); + lastAttr = attr; + } + + protected void setAttr(int cByte) { + lastAttr = cByte; + // int sattr = screen[lastPos].getCharAttr(); + // System.out.println("changing from " + sattr + " to attr " + lastAttr + // + + // " at " + (this.getRow(lastPos) + 1) + "," + (this.getCol(lastPos) + + // 1)); + planes.setScreenCharAndAttr(lastPos, initChar, lastAttr, true); + setDirty(lastPos); + advancePos(); + int pos = lastPos; + int times = 0; + // sattr = screen[lastPos].getCharAttr(); + // System.out.println(" next position after change " + sattr + " last + // attr " + lastAttr + + // " at " + (this.getRow(lastPos) + 1) + "," + (this.getCol(lastPos) + + // 1) + + // " attr place " + screen[lastPos].isAttributePlace()); + + while (planes.getCharAttr(lastPos) != lastAttr + && !planes.isAttributePlace(lastPos)) { + planes.setScreenAttr(lastPos, lastAttr); + + if (guiInterface && !isInField(lastPos, false)) { + int g = planes.getWhichGUI(lastPos); + + if (g >= FIELD_LEFT && g <= FIELD_ONE) + planes.setUseGUI(lastPos, NO_GUI); + } + + setDirty(lastPos); + times++; + advancePos(); + } + + // sanity check for right now + // if (times > 200) + // System.out.println(" setAttr = " + times + " start = " + (sr + 1) + + // "," + (sc + 1)); + lastPos = pos; + } + + protected void setScreenCharAndAttr(char right, int colorAttr, boolean isAttr) { + planes.setScreenCharAndAttr(lastPos, right, colorAttr, isAttr); + setDirty(lastPos); + advancePos(); + } + + protected void setScreenCharAndAttr(char right, int colorAttr, + int whichGui, boolean isAttr) { + planes.setScreenCharAndAttr(lastPos, right, colorAttr, isAttr); + planes.setUseGUI(lastPos, whichGui); + setDirty(lastPos); + advancePos(); + } + + /** + * Draw or redraw the dirty parts of the screen and display them. + * + * Rectangle dirty holds the dirty area of the screen to be updated. + * + * If you want to change the screen in anyway you need to set the screen + * attributes before calling this routine. + */ + protected void updateDirty() { + fireScreenChanged(); + } + + protected void setDirty(int pos) { + int minr = Math.min(getRow(pos), getRow(dirtyScreen.x)); + int minc = Math.min(getCol(pos), getCol(dirtyScreen.x)); + int maxr = Math.max(getRow(pos), getRow(dirtyScreen.y)); + int maxc = Math.max(getCol(pos), getCol(dirtyScreen.y)); + int x1 = getPos(minr, minc); + int x2 = getPos(maxr, maxc); + dirtyScreen.setBounds(x1, x2, 0, 0); + } + + private void resetDirty(int pos) { + dirtyScreen.setBounds(pos, pos, 0, 0); + } + + /** + * Change the screen position by one column + */ + protected void advancePos() { + changePos(1); + } + + /** + * Change position of the screen by the increment of parameter passed. + * + * If the position change is under the minimum of the first screen position + * then the position is moved to the last row and column of the screen. + * + * If the position change is over the last row and column of the screen then + * cursor is moved to first position of the screen. + * + * @param i + */ + protected void changePos(int i) { + lastPos += i; + + while (lastPos < 0) lastPos += lenScreen; + + while (lastPos >= lenScreen) lastPos -= lenScreen; + } + + + protected void goHome() { + // now we try to move to first input field according to + // 14.6 WRITE TO DISPLAY Command + // ? If the WTD command is valid, after the command is processed, + // the cursor moves to one of three locations: + // - The location set by an insert cursor order (unless control + // character byte 1, bit 1 is equal to B'1'.) + // - The start of the first non-bypass input field defined in the + // format table + // - A default starting address of row 1 column 1. + if (pendingInsert && homePos > 0) { + setCursor(getRow(homePos), getCol(homePos)); + isInField(); + } + else { + if (!gotoField(1)) { + homePos = getPos(1, 1); + setCursor(1, 1); + isInField(0, 0); + } + else { + homePos = getPos(getCurrentRow(), getCurrentCol()); + } + } + } + + protected void setPendingInsert(boolean flag, int icX, int icY) { + pendingInsert = flag; + + if (pendingInsert) { + homePos = getPos(icX, icY); + } + + if (!isStatusErrorCode()) { + setCursor(icX, icY); + } + } + + protected void setPendingInsert(boolean flag) { + if (homePos != -1) + pendingInsert = flag; + } + + /** + * Set the error line number to that of number passed. + * + * @param line + */ + protected void setErrorLine(int line) { + planes.setErrorLine(line); + } + + /** + * Returns the current error line number + * + * @return current error line number + */ + protected int getErrorLine() { + return planes.getErrorLine(); + } + + /** + * Saves off the current error line characters to be used later. + * + */ + protected void saveErrorLine() { + planes.saveErrorLine(); + } + + /** + * Restores the error line characters from the save buffer. + * + * @see #saveErrorLine() + */ + protected void restoreErrorLine() { + if (planes.isErrorLineSaved()) { + planes.restoreErrorLine(); + fireScreenChanged(planes.getErrorLine() - 1, 0, planes.getErrorLine() - 1, numCols - 1); + } + } + + protected void setStatus(byte attr, byte value, String s) { + // set the status area + switch (attr) { + case STATUS_SYSTEM: + if (value == STATUS_VALUE_ON) { + oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, ScreenOIA.OIA_LEVEL_INPUT_INHIBITED, s); + } + else { + oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED, ScreenOIA.OIA_LEVEL_NOT_INHIBITED, s); + } + + break; + + case STATUS_ERROR_CODE: + if (value == STATUS_VALUE_ON) { + setPrehelpState(true, true, false); + oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_ERROR, s); + sessionVT.signalBell(); + } + else { + oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED, + ScreenOIA.OIA_LEVEL_NOT_INHIBITED); + setPrehelpState(false, true, true); + homePos = saveHomePos; + saveHomePos = 0; + pendingInsert = false; + } + + break; + } + } + + protected boolean isStatusErrorCode() { + return oia.getLevel() == ScreenOIA.OIA_LEVEL_INPUT_ERROR; + } + + /** + * This routine clears the screen, resets row and column to 0, resets the + * last attribute to 32, clears the fields, turns insert mode off, + * clears/initializes the screen character array. + */ + protected void clearAll() { + lastAttr = 32; + lastPos = 0; + clearTable(); + clearScreen(); + planes.setScreenAttr(0, initAttr); + oia.setInsertMode(false); + } + + /** + * Clear the fields table + */ + protected void clearTable() { + oia.setKeyBoardLocked(true); + screenFields.clearFFT(); + planes.initalizeFieldPlanes(); + pendingInsert = false; + homePos = -1; + } + + /** + * Clear the gui constructs + * + */ + protected void clearGuiStuff() { + for (int x = 0; x < lenScreen; x++) { + planes.setUseGUI(x, NO_GUI); + } + + dirtyScreen.setBounds(0, lenScreen - 1, 0, 0); + } + + /** + * Clear the screen by setting the initial character and initial attribute + * to all the positions on the screen + */ + protected void clearScreen() { + planes.initalizePlanes(); + dirtyScreen.setBounds(0, lenScreen - 1, 0, 0); + oia.clearScreen(); + } + + protected void restoreScreen() { + lastAttr = 32; + dirtyScreen.setBounds(0, lenScreen - 1, 0, 0); + updateDirty(); + } + + public void onFontSizeChanged(float size) { + fireScreenChanged(0, 0, numRows - 1, numCols - 1); + } + + /** + * repaint part of the screen + * + */ + private void fireScreenChanged(int startRow, int startCol, int endRow, int endCol) { + int [] vt320color = {0x0, // black + 0x4, // blue + 0x2, // green + 0x6, // cyan + 0x1, // red + 0x5, // magenta/purple + 0xb, // yellow + 0x7, // light gray/white + 0x8, // dark gray + 0xc, // light blue + 0xa, // light green + 0xe, // light cyan + 0x9, // light red + 0xd, // light magenta/purple + 0x3, // brown + 0xf // bright white + }; + + for (int r = startRow; r <= endRow; r++) { + for (int c = startCol; c <= endCol; c++) { + int p = getPos(r, c); + char ch = planes.getChar(p); + char co = planes.getCharColor(p); + char at = planes.getCharExtended(p); + boolean ia = planes.isAttributePlace(p); + + if (ch < ' ') ch = ' '; + + int bg = vt320color[(co >> 8) & 0x0f] + 1; + int fg = vt320color[co & 0x0f] + 1; + int ul = at & EXTENDED_5250_UNDERLINE; + int nd = at & EXTENDED_5250_NON_DSP; + int vt_attr = (fg << VDUBuffer.COLOR_FG_SHIFT) + (bg << VDUBuffer.COLOR_BG_SHIFT); + + if (ul > 0) vt_attr |= VDUBuffer.UNDERLINE; + + if (ia || (nd > 0)) vt_attr |= VDUBuffer.INVISIBLE; + + buffer.putChar(c, r, ch, vt_attr); + } + } + + buffer.redrawPassthru(); + dirtyScreen.setBounds(lenScreen, 0, 0, 0); + } + + /** + * repaint the dirty part of the screen + * + */ + + private synchronized void fireScreenChanged() { + if (dirtyScreen.x > dirtyScreen.y) return; + fireScreenChanged(getRow(dirtyScreen.x), getCol(dirtyScreen.x), + getRow(dirtyScreen.y), getCol(dirtyScreen.y)); + } + + /** + * update the cursor position + * + */ + + private synchronized void fireCursorChanged() { + int l = getRow(lastPos); + int c = getCol(lastPos); + buffer.setCursorPosition(c, l); + } + + /** + * update the screen size. + */ + private void fireScreenSizeChanged() { + buffer.setScreenSize(numCols, numRows, true); + } + + /** + * This method does a complete refresh of the screen. + */ + public final void updateScreen() { + repaintScreen(); + setCursorActive(false); + setCursorActive(true); + } + + /** + * Utility method to share the repaint behaviour between setBounds() and + * updateScreen. + */ + public void repaintScreen() { + setCursorOff(); + dirtyScreen.setBounds(0, lenScreen - 1, 0, 0); + updateDirty(); + + // restore statuses that were on the screen before resize + if (oia.getLevel() == ScreenOIA.OIA_LEVEL_INPUT_ERROR) { + oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_ERROR); + } + + if (oia.getLevel() == ScreenOIA.OIA_LEVEL_INPUT_INHIBITED) { + oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); + } + + if (oia.isMessageWait()) + oia.setMessageLightOn(); + + setCursorOn(); + } + + // ADDED BY BARRY - changed by Kenneth to use the character plane + // This should be replaced with the getPlane methods when they are implemented + public char[] getCharacters() { + return planes.screen; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/ScreenField.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,537 @@ +/** + * Title: tn5250J + * Copyright: Copyright (c) 2001 + * Company: + * @author Kenneth J. Pouncey + * @version 0.4 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.framework.tn5250; + +public class ScreenField { + + protected ScreenField(Screen5250 s) { + this.s = s; + } + + protected ScreenField setField(int attr, int len, int ffw1, int ffw2, + int fcw1, int fcw2) { + return setField(attr, + s.getCurrentRow() - 1, + s.getCurrentCol() - 1, + len, + ffw1, + ffw2, + fcw1, + fcw2); + } + + protected ScreenField setField(int attr, int row, int col, int len, int ffw1, int ffw2, + int fcw1, int fcw2) { +// startRow = row; +// startCol = col; + cursorProg = 0; + fieldId = 0; + length = len; + startPos = (row * s.getColumns()) + col; + endPos = startPos + length - 1; + this.attr = attr; + setFFWs(ffw1, ffw2); + setFCWs(fcw1, fcw2); + next = null; + prev = null; + return this; + } + + public int getAttr() { + return attr; + } + + public int getHighlightedAttr() { + return (fcw2 & 0x0f) | 0x20; + } + + public int getLength() { + return length; + } + + protected boolean setFFWs(int ffw1, int ffw2) { + this.ffw1 = ffw1; + this.ffw2 = ffw2; + int adj = getAdjustment(); + + if (adj > 0) { + checkCanSend = true; + + switch (adj) { + case 5: + case 6: + rightAdjd = false; + break; + + case 7: + mandatory = false; + break; + } + } + + mdt = (ffw1 & 0x8) == 0x8; +// if (mdt) +// s.masterMDT = true; + return mdt; + } + + + public int getFFW1() { + return ffw1; + } + public int getFFW2() { + return ffw2; + } + + protected void setFCWs(int fcw1, int fcw2) { + this.fcw1 = fcw1; + this.fcw2 = fcw2; + +// if ((fcw1 & 0x88) == 0x88) { + if (fcw1 == 0x88) { + cursorProg = fcw2; + } + } + + public int getFCW1() { + return fcw1; + } + + public int getFCW2() { + return fcw2; + } + + public int getFieldLength() { + return length; + } + + public int getCursorProgression() { + return cursorProg; + } + + public int getFieldId() { + return fieldId; + } + + protected void setFieldId(int fi) { + fieldId = fi; + } + + public int getCursorRow() { + return cursorPos / s.getColumns(); + } + + public int getCursorCol() { + return cursorPos % s.getColumns(); + } + + protected void changePos(int i) { + cursorPos += i; + } + + protected String getText() { + StringBuffer text = new StringBuffer(); + getKeyPos(endPos); + int x = length; + text.setLength(x); + + while (x-- > 0) { + // here we manipulate the unicode characters a little for attributes + // that are imbedded in input fields. We will offset them by unicode + // \uff00. All routines that process these fields will have to + // return them to their proper offsets. + // example: + // if we read an attribute byte of 32 for normal display the unicode + // character for this is \u0020 and the unicode character for + // a space is also \u0020 thus the offset. + if (s.planes.isAttributePlace(cursorPos)) { + text.setCharAt(x, (char)('\uff00' + s.planes.getCharAttr(cursorPos))); + } + else { + text.setCharAt(x, s.planes.getChar(cursorPos)); + } + + changePos(-1); + } + + // Since only the mdt of the first continued field is set we will get + // the text of the next continued field if we are dealing with continued + // fields. See routine setMDT for the whys of this. This is only + // executed if this is the first field of a continued field. + if (isContinued() && isContinuedFirst()) { + ScreenField sf = this; + + do { + sf = sf.next; + text.append(sf.getText()); + } + while (!sf.isContinuedLast()); + + sf = null; + } + + return text.toString(); + } + + public String getString() { + StringBuffer text = new StringBuffer(); + getKeyPos(endPos); + int x = length; + text.setLength(x); + + while (x-- > 0) { + // here we manipulate the unicode characters a little for attributes + // that are imbedded in input fields. We will offset them by unicode + // \uff00. All routines that process these fields will have to + // return them to their proper offsets. + // example: + // if we read an attribute byte of 32 for normal display the unicode + // character for this is \u0020 and the unicode character for + // a space is also \u0020 thus the offset. + if (s.planes.isAttributePlace(cursorPos)) { + text.setCharAt(x, (char)('\uff00' + s.planes.getCharAttr(cursorPos))); + } + else { + if (s.planes.getChar(cursorPos) < ' ') + text.setCharAt(x, ' '); + else + text.setCharAt(x, s.planes.getChar(cursorPos)); + } + + changePos(-1); + } + + // Since only the mdt of the first continued field is set we will get + // the text of the next continued field if we are dealing with continued + // fields. See routine setMDT for the whys of this. This is only + // executed if this is the first field of a continued field. + if (isContinued() && isContinuedFirst()) { + ScreenField sf = this; + + do { + sf = sf.next; + text.append(sf.getString()); + } + while (!sf.isContinuedLast()); + + sf = null; + } + + return text.toString(); + } + + public void setFieldChar(char c) { + int x = length; + cursorPos = startPos; + + while (x-- > 0) { + s.planes.setChar(cursorPos, c); + changePos(1); + } + } + + public void setFieldChar(int lastPos, char c) { + int x = endPos - lastPos + 1; + cursorPos = lastPos; + + while (x-- > 0) { + s.planes.setChar(cursorPos, c); + s.setDirty(cursorPos); + changePos(1); + } + } + + protected void setRightAdjusted() { + rightAdjd = true; + } + + protected void setMandatoryEntered() { + mandatory = true; + } + + protected void resetMDT() { + mdt = false; + } + + protected void setMDT() { + // get the first field of a continued edit field if it is continued + if (isContinued() && !isContinuedFirst()) { + ScreenField sf = prev; + + while (sf.isContinued() && !sf.isContinuedFirst()) { + sf = sf.prev; + } + + sf.setMDT(); + sf = null; + } + else { + mdt = true; + } + } + + public boolean isBypassField() { + return (ffw1 & 0x20) == 0x20; + } + + public int getAdjustment() { + return (ffw2 & 0x7); + } + + // is field exit required + public boolean isFER() { + return (ffw2 & 0x40) == 0x40; + } + + // is field mandatory enter + public boolean isMandatoryEnter() { + return (ffw2 & 0x8) == 0x8; + } + + public boolean isToUpper() { + return (ffw2 & 0x20) == 0x20; + } + + // bits 5 - 7 + public int getFieldShift() { + return (ffw1 & 0x7); + } + + public boolean isHiglightedEntry() { + return (fcw1 == 0x89); + } + + public boolean isAutoEnter() { + return (ffw2 & 0x80) == 0x80; + } + + public boolean isSignedNumeric() { + return (getFieldShift() == 7); + } + + public boolean isRightToLeft() { + return (getFieldShift() == 0x04); + } + + public boolean isNumeric() { + return (getFieldShift() == 3); + } + + public boolean isDupEnabled() { + return (ffw1 & 0x10) == 0x10; + } + + public boolean isContinued() { + return (fcw1 & 0x86) == 0x86 && (fcw2 >= 1 && fcw2 <= 3) ; + } + + public boolean isContinuedFirst() { + return (fcw1 & 0x86) == 0x86 && (fcw2 == 1); + } + + public boolean isContinuedMiddle() { + return (fcw1 & 0x86) == 0x86 && (fcw2 == 3); + } + + public boolean isContinuedLast() { + return (fcw1 & 0x86) == 0x86 && (fcw2 == 2); + } + + protected boolean isCanSend() { + int adj = getAdjustment(); + + // here we need to check the Field Exit Required value first before checking + // the adjustments. If the last character has been entered and we are + // now setting past the last position then we are allowed to process the + // the field without continuing. + if (isFER() && cursorPos > endPos) { + return true; + } + + // signed numeric fields need to be checked as well. + if (isSignedNumeric() && cursorPos < endPos - 1) { + return false; + } + + if (adj > 0) { + switch (adj) { + case 5: + case 6: + return rightAdjd; + + case 7: + return mandatory; + + default: + return true; + } + } + + return true; + } + + public boolean isSelectionField() { + return isSelectionField; + } + + public void setSelectionFieldInfo(int type, int index, int position) { + selectionFieldType = type; + selectionIndex = index; + selectionPos = position; + isSelectionField = true; + } + + protected int getKeyPos(int row1, int col1) { + int x = ((row1 * s.getColumns()) + col1); + int y = x - startPos(); + cursorPos = x; + return y; + } + + protected int getKeyPos(int pos) { + int y = pos - startPos(); + cursorPos = pos; + return y; + } + + public int getCurrentPos() { + return cursorPos; + } + + public boolean withinField(int pos) { + if (pos >= startPos && pos <= endPos) + return true; + + return false; + } + + public int startPos() { + return startPos; + } + + /** + * Get the starting row of the field. Offset is 0 so row 6 returned + * is row 7 mapped to screen + * @return int starting row of the field offset 0 + */ + public int startRow() { + return startPos / s.getColumns(); + } + + /** + * Get the starting column of the field. Offset is 0 so column 6 returned + * is column 7 mapped to screen + * @return int starting column of the field offset 0 + */ + public int startCol() { + return startPos % s.getColumns(); + } + + public int endPos() { + return endPos; + } + + /** + * Sets the field's text plane to the specified string. If the string is + * shorter than the length of the field, the rest of the field is cleared. + * If the string is longer than the field, the text is truncated. A subsequent + * call to getText on this field will not show the changed text. To see the + * changed text, do a refresh on the iOhioFields collection and retrieve the + * refreshed field object. + * + * @param text - The text to be placed in the field's text plane. + */ + public void setString(String text) { + cursorPos = startPos; + + if (isRightToLeft()) { + text = new StringBuilder(text).reverse().toString(); + } + + final ScreenPlanes planes = s.getPlanes(); + for (int x = 0,len = text.length(); x < length; x++) { + char tc = (x < len) ? text.charAt(x) : ' '; + planes.setChar(cursorPos, tc); + changePos(1); + } + setMDT(); + s.getScreenFields().setMasterMDT(); + } + + @Override + public String toString() { + int fcw = (fcw1 & 0xff) << 8 | fcw2 & 0xff; + return "startRow = " + startRow() + " startCol = " + startCol() + + " length = " + length + " ffw1 = (0x" + Integer.toHexString(ffw1) + + ") ffw2 = (0x" + Integer.toHexString(ffw2) + + ") fcw1 = (0x" + Integer.toHexString(fcw1) + + ") fcw2 = (0x" + Integer.toHexString(fcw2) + + ") fcw = (" + Integer.toBinaryString(fcw) + + ") fcw hex = (0x" + Integer.toHexString(fcw) + + ") is bypass field = " + isBypassField() + + ") is autoenter = " + isAutoEnter() + + ") is mandatoryenter = " + isMandatoryEnter() + + ") is field exit required = " + isFER() + + ") is Numeric = " + isNumeric() + + ") is Signed Numeric = " + isSignedNumeric() + + ") is cursor progression = " + (fcw1 == 0x88) + + ") next progression field = " + fcw2 + + ") field id " + fieldId + + " continued edit field = " + isContinued() + + " first continued edit field = " + isContinuedFirst() + + " middle continued edit field = " + isContinuedMiddle() + + " last continued edit field = " + isContinuedLast() + + " mdt = " + mdt; + } + + public int getStartPos() { + return startPos; + } + + int startPos = 0; + int endPos = 0; + boolean mdt = false; + protected boolean checkCanSend; + protected boolean rightAdjd; + protected boolean mandatory; + boolean canSend = true; + int attr = 0; + int length = 0; + int ffw1 = 0; + int ffw2 = 0; + int fcw1 = 0; + int fcw2 = 0; + int cursorPos = 0; + Screen5250 s; + int cursorProg = 0; + int fieldId = 0; + ScreenField next = null; + ScreenField prev = null; + boolean isSelectionField; + int selectionFieldType; + int selectionIndex; + int selectionPos; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/ScreenFields.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,685 @@ +/** + * Title: tn5250J + * Copyright: Copyright (c) 2001 + * Company: + * @author Kenneth J. Pouncey + * @version 0.5 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.framework.tn5250; + +import static org.tn5250j.TN5250jConstants.CMD_READ_INPUT_FIELDS; +import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_FIELDS; +import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_IMMEDIATE_ALT; + +import java.io.ByteArrayOutputStream; + +import org.tn5250j.encoding.ICodePage; + +public class ScreenFields { + + private ScreenField[] screenFields; + private ScreenField currentField; + private ScreenField saveCurrent; + private int sizeFields; + private boolean cpfExists; + private int nextField; + private int fieldIds; + private Screen5250 screen; + private boolean masterMDT; + protected boolean currentModified; + + public ScreenFields(Screen5250 s) { + screen = s; + screenFields = new ScreenField[256]; + } + + protected void clearFFT() { + sizeFields = nextField = fieldIds = 0; + cpfExists = false; // clear the cursor progression fields flag + currentField = null; + masterMDT = false; + } + + protected boolean existsAtPos(int lastPos) { + ScreenField sf = null; + + // from 14.6.12 for Start of Field Order 5940 function manual + // examine the format table for an entry that begins at the current + // starting address plus 1. + for (int x = 0; x < sizeFields; x++) { + sf = screenFields[x]; + + if (lastPos == sf.startPos()) { + currentField = sf; + currentModified = false; + return true; + } + } + + return false; + } + + public boolean isMasterMDT() { + return masterMDT; + } + + protected void setMasterMDT() { + masterMDT = true; + } + + public boolean isCurrentField() { + return currentField == null; + } + + public boolean isCurrentFieldFER() { + return currentField.isFER(); + } + + public boolean isCurrentFieldDupEnabled() { + return currentField.isDupEnabled(); + } + + public boolean isCurrentFieldToUpper() { + return currentField.isToUpper(); + } + + public boolean isCurrentFieldBypassField() { + return currentField.isBypassField(); + } + + public boolean isCurrentFieldHighlightedEntry() { + if (currentField != null) + return currentField.isHiglightedEntry(); + else + return false; + } + + public boolean isCurrentFieldAutoEnter() { + return currentField.isAutoEnter(); + } + + public boolean withinCurrentField(int pos) { + return currentField.withinField(pos); + } + + public boolean isCurrentFieldContinued() { + return currentField.isContinued(); + } + + public boolean isCurrentFieldContinuedFirst() { + return currentField.isContinuedFirst(); + } + + public boolean isCurrentFieldContinuedMiddle() { + return currentField.isContinuedMiddle(); + } + + public boolean isCurrentFieldContinuedLast() { + return currentField.isContinuedLast(); + } + + public boolean isCurrentFieldModified() { + return currentModified; + } + + /** + * This routine is used to check if we can send the Aid key to the host + * + * Taken from Section 16.2.1.2 Enter/Rec Adv Key + * + * In the normal unlocked state, when the workstation operator presses the + * Enter/Rec Adv key: + * + * 1. The 5494 checks for the completion of mandatory-fill, self-check, and + * right-adjust fields when in an active field. (An active field is one in + * which the workstation operator has begun entering data.) If the + * requirements of the field have not been satisfied, an error occurs. + * + * @return + * + */ + public boolean isCanSendAid() { + // We also have to check if we are still in the field. + if (currentField != null && + (currentField.getAdjustment() > 0 || currentField.isSignedNumeric()) + && currentModified && isInField() + && !currentField.isCanSend()) + return false; + else + return true; + } + + protected void saveCurrentField() { + saveCurrent = currentField; + } + + protected void restoreCurrentField() { + currentField = saveCurrent; + } + + protected void setCurrentField(ScreenField sf) { + currentField = sf; + } + + protected void setCurrentFieldMDT() { + currentField.setMDT(); + currentModified = true; + masterMDT = true; + } + + protected void setCurrentFieldFFWs(int ffw1, int ffw2) { + masterMDT = currentField.setFFWs(ffw1, ffw2); + } + + + protected ScreenField setField(int attr, int row, int col, int len, int ffw1, + int ffw2, int fcw1, int fcw2) { + ScreenField sf = null; + screenFields[nextField] = new ScreenField(screen); + screenFields[nextField].setField(attr, row, col, len, ffw1, ffw2, fcw1, fcw2); + sf = screenFields[nextField++]; + sizeFields++; + // set the field id if it is not a bypass field + // this is used for cursor progression + // changed this because of problems not allocating field id's for + // all fields. kjp 2002/10/21 +// if (!sf.isBypassField()) + sf.setFieldId(++fieldIds); + + // check if the cursor progression field flag should be set. +// if ((fcw1 & 0x88) == 0x88) + if (fcw1 == 0x88) + cpfExists = true; + + if (currentField != null) { + currentField.next = sf; + sf.prev = currentField; + } + + currentField = sf; + + // check if the Modified Data Tag was set while creating the field + if (!masterMDT) + masterMDT = currentField.mdt; + + currentModified = false; + return currentField; + } + + public ScreenField getField(int index) { + return screenFields[index]; + } + + public ScreenField getCurrentField() { + return currentField; + } + + public int getCurrentFieldPos() { + return currentField.getCurrentPos(); + } + + protected int getCurrentFieldShift() { + return currentField.getFieldShift(); + } + + public String getCurrentFieldText() { + return currentField.getText(); + } + + public int getCurrentFieldHighlightedAttr() { + return currentField.getHighlightedAttr(); + } + + public int getSize() { + return sizeFields; + } + + public int getFieldCount() { + return sizeFields; + } + + protected boolean isInField(int pos) { + return isInField(pos, true); + } + + protected boolean isInField() { + return isInField(screen.getLastPos(), true); + } + + protected boolean isInField(int pos, boolean chgToField) { + ScreenField sf; + + for (int x = 0; x < sizeFields; x++) { + sf = screenFields[x]; + + if (sf.withinField(pos)) { + if (chgToField) { + if (!currentField.equals(sf)) + currentModified = false; + + currentField = sf; + } + + return true; + } + } + + return false; + } + + /** + * Searches the collection for the target string and returns the iOhioField + * object containing that string. The string must be totally contained + * within the field to be considered a match. + * + * @param targetString The target string. + * @param startPos The row and column where to start the search. The position + * is inclusive (for example, row 1, col 1 means that + * position 1,1 will be used as the starting location and + * 1,1 will be included in the search). + * @param length The length from startPos to include in the search. + * @param dir An OHIO_DIRECTION value: + * + * <table BORDER COLS=3 WIDTH="50%" > + * <tr><th>Constant </th><th>Value</th> + * <th>Description</th></tr> + * <tr><td>OS_OHIO_DIRECTION_FORWARD </td><td>0</td> + * <td>Forward (beginning towards end)</td></tr> + * <tr><td>OS_OHIO_DIRECTION_BACKWARD </td><td>1</td> + * <td>Backward (end towards beginning)</td></tr> + * </table> + * Constant Value Description + * ignoreCase - Indicates whether the search is case sensitive. + * True means that case will be ignored. False means the search will + * be case sensitive. + * @return If found, an iOhioField object containing the target string. If + * not found, returns a null. + */ + public ScreenField findByString(String targetString, + int startPos, + int length, + int dir, + boolean ignoreCase) { + // first lets check if the string exists in the screen space +// iOhioPosition pos = screen.findString(targetString, startPos, length, +// dir, ignoreCase); + // if it does exist then lets search the fields by the position that + // was found and return the results of that search. +// if (pos != null) { + return findByPosition(startPos); +// } + //return null; + } + + /** + * Searches the collection for the target position and returns the ScreenField + * object containing that position. + * + * @param targetPosition The target row and column expressed as a linear + * position within the presentation space. + * + * @return If found, a ScreenField object containing the target position. + * If not found, returns a null. + */ + public ScreenField findByPosition(int targetPosition) { + ScreenField sf = null; + + for (int x = 0; x < sizeFields; x++) { + sf = screenFields[x]; + + if (sf.withinField(targetPosition)) { + return sf; + } + } + + return null; + } + + /** + * Searches the collection for the target position and returns the ScreenField + * object containing that position. + * + * @param row The beginning row to start search with in the presentation space. + * @param col The beginning column to start search with in the presentation space. + * + * @return If found, a ScreenField object containing the target position. + * If not found, returns a null. + */ + public ScreenField findByPosition(int row, int col) { + return findByPosition(screen.getPos(row, col)); + } + + public ScreenField[] getFields() { + ScreenField[] fields = new ScreenField[sizeFields]; + + for (int x = 0; x < sizeFields; x++) { + fields[x] = screenFields[x]; + } + + return fields; + } + + public ScreenField getFirstInputField() { + if (sizeFields <= 0) + return null; + + int f = 0; + ScreenField sf = screenFields[f]; + + while (sf.isBypassField() && f++ < sizeFields) { + sf = screenFields[f]; + } + + if (sf.isBypassField()) + return null; + else + return sf; + } + + public void gotoFieldNext() { + // sanity check - we were getting null pointers after a restore of screen + // and cursor was not positioned on a field when returned + // *** Note *** to myself + // maybe this is fixed I will have to check this some time + int lastPos = screen.getLastPos(); + + if (currentField == null && (sizeFields != 0) && !isInField(lastPos, true)) { + int pos = lastPos; + screen.setCursorOff(); + screen.advancePos(); + lastPos = screen.getLastPos(); + + while (!isInField() && pos != lastPos) { + screen.advancePos(); + } + + screen.setCursorOn(); + } + + // if we are still null do nothing + if (currentField == null) + return; + + ScreenField sf = currentField; + + if (!sf.withinField(lastPos)) { + screen.setCursorOff(); + + if (sizeFields > 0) { + // lets get the current position so we can test if we have looped + // the screen and not found a valid field. + int pos = lastPos; + int savPos = lastPos; + boolean done = false; + + do { + screen.advancePos(); + lastPos = screen.getLastPos(); + + if (isInField(lastPos) + || pos == lastPos) { + if (!currentField.isBypassField()) { + screen.gotoField(currentField); + done = true; + } + } + } + while (!done && lastPos != savPos); + } + + currentModified = false; + screen.setCursorOn(); + } + else { + if (!cpfExists) { + do { + sf = sf.next; + } + while (sf != null && sf.isBypassField()); + } + else { + int f = 0; + int cp = sf.getCursorProgression(); + + if (cp == 0) { + do { + sf = sf.next; + } + while (sf != null && sf.isBypassField()); + } + else { + ScreenField sf1 = null; + boolean found = false; + + while (!found && f < sizeFields) { + sf1 = screenFields[f++]; + + if (sf1.getFieldId() == cp) + found = true; + } + + if (found) + sf = sf1; + else { + do { + sf = sf.next; + } + while (sf != null && sf.isBypassField()); + } + + sf1 = null; + } + } + + if (sf == null) + screen.gotoField(1); + else { + currentField = sf; + screen.gotoField(currentField); + } + + currentModified = false; + } + } + + public void gotoFieldPrev() { + ScreenField sf = currentField; + int lastPos = screen.getLastPos(); + + if (!sf.withinField(lastPos)) { + screen.setCursorOff(); + + if (sizeFields > 0) { + // lets get the current position so we can test if we have looped + // the screen and not found a valid field. + int pos = lastPos; + int savPos = lastPos; + boolean done = false; + + do { + screen.changePos(-1); + lastPos = screen.getLastPos(); + + if (isInField(lastPos) + || (pos == lastPos)) { + if (!currentField.isBypassField()) { + screen.gotoField(currentField); + done = true; + } + } + } + while (!done && lastPos != savPos); + } + + screen.setCursorOn(); + } + else { + if (sf.startPos() == lastPos) { + if (!cpfExists) { + do { + sf = sf.prev; + } + while (sf != null && sf.isBypassField()); + } + else { + int f = 0; + int cp = sf.getFieldId(); + ScreenField sf1 = null; + boolean found = false; + + while (!found && f < sizeFields) { + sf1 = screenFields[f++]; + + if (sf1.getCursorProgression() == cp) + found = true; + } + + if (found) + sf = sf1; + else { + do { + sf = sf.prev; + } + while (sf != null && sf.isBypassField()); + } + + sf1 = null; + } + } + + if (sf == null) { + int size = sizeFields; + sf = screenFields[size - 1]; + + while (sf.isBypassField() && size-- > 0) { + sf = screenFields[size]; + } + } + + currentField = sf; + currentModified = false; + screen.gotoField(currentField); + } + } + + protected void readFormatTable(ByteArrayOutputStream baosp, int readType, ICodePage codePage) { + ScreenField sf; + boolean isSigned = false; + char c; + + if (masterMDT) { + StringBuffer sb = new StringBuffer(); + + for (int x = 0; x < sizeFields; x++) { + isSigned = false; + sf = screenFields[x]; + + if (sf.mdt || (readType == CMD_READ_INPUT_FIELDS)) { + sb.setLength(0); + sb.append(sf.getText()); + + if (readType == CMD_READ_MDT_FIELDS || + readType == CMD_READ_MDT_IMMEDIATE_ALT) { + int len = sb.length() - 1; + + // we strip out all '\u0020' and less + while (len >= 0 && +// (sb.charAt(len) <= ' ' || sb.charAt(len) >= '\uff20' )) { + (sb.charAt(len) < ' ' || sb.charAt(len) >= '\uff20')) { + // if we have the dup character and dup is enabled then we + // stop here + if (sb.charAt(len) == 0x1C && sf.isDupEnabled()) + break; + + sb.deleteCharAt(len--); + } + } + +// System.out.println("field " + sf.toString()); +// System.out.println(">" + sb.toString() + "<"); +// System.out.println(" field is all nulls"); + if (sf.isSignedNumeric() && sb.length() > 0 && sb.charAt(sb.length() - 1) == '-') { + isSigned = true; + sb.setLength(sb.length() - 1); + } + + int len3 = sb.length(); + + if (len3 > 0 || (readType == CMD_READ_MDT_FIELDS || + readType == CMD_READ_MDT_IMMEDIATE_ALT)) { + if ((readType == CMD_READ_MDT_FIELDS || + readType == CMD_READ_MDT_IMMEDIATE_ALT)) { + baosp.write(17); // start of field data + + if (sf.isSelectionField()) { + baosp.write(screen.getRow(sf.selectionPos) + 1); + baosp.write(screen.getCol(sf.selectionPos) + 1); + } + else { + baosp.write(sf.startRow() + 1); + baosp.write(sf.startCol() + 1); + } + } + +// int len = sb.length(); + if (sf.isSelectionField()) { + baosp.write(0); + baosp.write(sf.selectionIndex + 0x1F); + } + else { + for (int k = 0; k < len3; k++) { + c = sb.charAt(k); + + // here we have to check for special instances of the + // characters in the string field. Attribute bytes + // are encoded with an offset of \uff00 + // This is a hack !!!!!!!!!!! + // See ScreenField object for a description + if (c < ' ' || c >= '\uff20') { + // if it is an offset attribute byte we just pass + // it straight on to the output stream + if (c >= '\uff20' && c <= '\uff3f') { + baosp.write(c - '\uff00'); + } + else + + // check for dup character + if (c == 0x1C) + baosp.write(c); + else + baosp.write(codePage.uni2ebcdic(' ')); + } + else { + if (isSigned && k == len3 - 1) { + baosp.write(0xd0 | (0x0f & c)); + } + else + baosp.write(codePage.uni2ebcdic(c)); + } + } + } + } + } + } + } + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/ScreenOIA.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,282 @@ +/** + * <p>Title: ScreenOIA.java</p> + * <p>Description: Main interface to control Operator information area screen</p> + * <p>Copyright: Copyright (c) 2000 - 2002</p> + * <p> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * </p> + * @author Kenneth J. Pouncey + * @version 0.5 + */ +package org.tn5250j.framework.tn5250; + +import java.util.Vector; + +import org.tn5250j.event.ScreenOIAListener; + +/** + * The operator information area of a host session. This area is used to provide + * status information regarding the state of the host session and location of + * the cursor. A ScreenOIA object can be obtained using the GetOIA() method on + * an instance of Screen5250. + * + * + */ +public class ScreenOIA { + // OIA_LEVEL + public static final int OIA_LEVEL_INPUT_INHIBITED = 1; + public static final int OIA_LEVEL_NOT_INHIBITED = 2; + public static final int OIA_LEVEL_MESSAGE_LIGHT_ON = 3; + public static final int OIA_LEVEL_MESSAGE_LIGHT_OFF = 4; + public static final int OIA_LEVEL_AUDIBLE_BELL = 5; + public static final int OIA_LEVEL_INSERT_MODE = 6; + public static final int OIA_LEVEL_KEYBOARD = 7; + public static final int OIA_LEVEL_CLEAR_SCREEN = 8; + public static final int OIA_LEVEL_SCREEN_SIZE = 9; + public static final int OIA_LEVEL_INPUT_ERROR = 10; + public static final int OIA_LEVEL_KEYS_BUFFERED = 11; + public static final int OIA_LEVEL_SCRIPT = 12; + + // INPUTINHIBITED + public static final int INPUTINHIBITED_NOTINHIBITED = 0; + public static final int INPUTINHIBITED_SYSTEM_WAIT = 1; + public static final int INPUTINHIBITED_COMMCHECK = 2; + public static final int INPUTINHIBITED_PROGCHECK = 3; + public static final int INPUTINHIBITED_MACHINECHECK = 4; + public static final int INPUTINHIBITED_OTHER = 5; + + public ScreenOIA(Screen5250 screen) { + source = screen; + } + + public boolean isInsertMode() { + return insertMode; + } + + protected void setInsertMode(boolean mode) { + level = OIA_LEVEL_INSERT_MODE; + insertMode = mode; + fireOIAChanged(ScreenOIAListener.OIA_CHANGED_INSERT_MODE); + } + + public int getCommCheckCode() { + return commCheck; + } + + public int getInputInhibited() { + return inputInhibited; + } + + public int getMachineCheckCode() { + return machineCheck; + } + + public int getOwner() { + return owner; + } + + public int getProgCheckCode() { + return 0; + } + + /** + * Is the keyboard locked or not + * + * @return locked or not + */ + public boolean isKeyBoardLocked() { + return locked; + } + + public boolean isKeysBuffered() { + return keysBuffered; + } + + public void setKeysBuffered(boolean kb) { + level = OIA_LEVEL_KEYS_BUFFERED; + boolean oldKB = keysBuffered; + keysBuffered = kb; + + if (keysBuffered != oldKB) + fireOIAChanged(ScreenOIAListener.OIA_CHANGED_KEYS_BUFFERED); + } + + protected void setKeyBoardLocked(boolean lockIt) { + level = OIA_LEVEL_KEYBOARD; + boolean oldLocked = locked; + locked = lockIt; + + if (!lockIt) { + if (isKeysBuffered()) { + source.sendKeys(""); + } + } + + if (locked != oldLocked) + fireOIAChanged(ScreenOIAListener.OIA_CHANGED_KEYBOARD_LOCKED); + } + + public boolean isMessageWait() { + return messageWait; + } + + protected void setMessageLightOn() { + level = OIA_LEVEL_MESSAGE_LIGHT_ON; + messageWait = true; + fireOIAChanged(ScreenOIAListener.OIA_CHANGED_MESSAGELIGHT); + } + + protected void setMessageLightOff() { + level = OIA_LEVEL_MESSAGE_LIGHT_OFF; + messageWait = false; + fireOIAChanged(ScreenOIAListener.OIA_CHANGED_MESSAGELIGHT); + } + + public void setScriptActive(boolean running) { + level = OIA_LEVEL_SCRIPT; + scriptRunning = running; + fireOIAChanged(ScreenOIAListener.OIA_CHANGED_SCRIPT); + } + + public boolean isScriptActive() { + return scriptRunning; + } + + public void setAudibleBell() { + level = OIA_LEVEL_AUDIBLE_BELL; + fireOIAChanged(ScreenOIAListener.OIA_CHANGED_BELL); + } + + protected void clearScreen() { + level = OIA_LEVEL_CLEAR_SCREEN; + fireOIAChanged(ScreenOIAListener.OIA_CHANGED_CLEAR_SCREEN); + } + + /** + * Add a ScreenOIAListener to the listener list. + * + * @param listener The ScreenOIAListener to be added + */ + public void addOIAListener(ScreenOIAListener listener) { + if (listeners == null) { + listeners = new java.util.Vector<ScreenOIAListener>(3); + } + + listeners.addElement(listener); + } + + /** + * Remove a iOhioSessionListener from the listener list. + * + * @param listener The iOhioSessionListener to be removed + */ + public void removeOIAListener(ScreenOIAListener listener) { + if (listeners == null) { + return; + } + + listeners.removeElement(listener); + } + + // object methods + public Screen5250 getSource() { + return source; + } + + + public void setSource(Screen5250 screen) { + source = screen; + } + + public void setOwner(int newOwner) { + owner = newOwner; + } + + public int getLevel() { + return level; + } + + public String getInhibitedText() { + return inhibitedText; + } + + public void setInputInhibited(int inhibit , int whatCode) { + setInputInhibited(inhibit, whatCode, null); + } + + public void setInputInhibited(int inhibit , int whatCode, String message) { + inputInhibited = inhibit; + level = OIA_LEVEL_INPUT_INHIBITED; + inhibitedText = message; + +// if (saveInhibit != inhibit || saveInhibitLevel != whatCode) { + switch (inhibit) { + case INPUTINHIBITED_COMMCHECK : + commCheck = whatCode; + break; + + case INPUTINHIBITED_PROGCHECK : +// progCheck = whatCode; // never used + break; + + case INPUTINHIBITED_MACHINECHECK : + machineCheck = whatCode; + break; + + case INPUTINHIBITED_SYSTEM_WAIT : + level = whatCode; + break; + + case INPUTINHIBITED_NOTINHIBITED : + level = whatCode; + break; + } + + fireOIAChanged(ScreenOIAListener.OIA_CHANGED_INPUTINHIBITED); +// } + } + + /** + * Notify all registered listeners of the onOIAChanged event. + * + */ + private void fireOIAChanged(int change) { + if (listeners != null) { + int size = listeners.size(); + + for (int i = 0; i < size; i++) { + ScreenOIAListener target = + listeners.elementAt(i); + target.onOIAChanged(this, change); + } + } + } + + private Vector<ScreenOIAListener> listeners = null; + private boolean insertMode; + private boolean locked; + private boolean keysBuffered; + private int owner = 0; + private int level = 0; + private Screen5250 source = null; + private int commCheck = 0; + private int machineCheck = 0; + private boolean messageWait; + private boolean scriptRunning; + private int inputInhibited = INPUTINHIBITED_NOTINHIBITED; + private String inhibitedText; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/ScreenPlanes.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,803 @@ +/** + * Title: ScreenPlanes.java + * Copyright: Copyright (c) 2001 + * Company: + * @author Kenneth J. Pouncey + * @version 0.5 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.framework.tn5250; + +import static org.tn5250j.TN5250jConstants.*; + +public class ScreenPlanes { + + private final Screen5250 scr; + private int screenSize; + private int numRows; + private int numCols; + private int errorLineNum; + + private static final int initAttr = 32; + private static final char initChar = 0; + + protected char[] screen; // text plane + private char[] screenAttr; // attribute plane + private char[] screenGUI; // gui plane + private char[] screenIsAttr; + private char[] fieldExtended; + private char[] screenField; + private char[] screenColor; // color plane + protected char[] screenExtended; // extended plane + private char[] screenIsChanged; + + private char[] initArray; + + private char[] errorLine; + private char[] errorLineAttr; + private char[] errorLineIsAttr; + private char[] errorLineGui; + + public ScreenPlanes(Screen5250 s5250, int size) { + scr = s5250; + setSize(size); + } + + protected void setSize(int newSize) { + screenSize = newSize; + numCols = 80; + + switch (newSize) { + case 24: + numRows = 24; + break; + + case 27: + numRows = 27; + numCols = 132; + break; + } + + // this is used here when size changes + setErrorLine(numRows); + screenSize = numRows * numCols; + screen = new char[screenSize]; + screenAttr = new char[screenSize]; + screenIsAttr = new char[screenSize]; + screenGUI = new char[screenSize]; + screenColor = new char[screenSize]; + screenExtended = new char[screenSize]; + fieldExtended = new char[screenSize]; + screenIsChanged = new char[screenSize]; + screenField = new char[screenSize]; + initArray = new char[screenSize]; + initalizePlanes(); + } + + protected void setErrorLine(int line) { + // * NOTE * for developers I have changed the send qry to pass different + // parameters to the host so check setsize for setting error line as well. + // + if (line == 0 || line > numRows) + errorLineNum = numRows; + else + errorLineNum = line; + } + + /** + * Returns the current error line number + * + * @return current error line number + */ + protected int getErrorLine() { + return errorLineNum; + } + + protected void saveErrorLine() { + // if there is already an error line saved then do not save it again + // This signifies that there was a previous error and the original error + // line was not restored yet. + if (errorLine == null) { + errorLine = new char[numCols]; + errorLineAttr = new char[numCols]; + errorLineIsAttr = new char[numCols]; + errorLineGui = new char[numCols]; + int r = scr.getPos(errorLineNum - 1, 0); + + for (int x = 0; x < numCols; x++) { + errorLine[x] = screen[r + x]; + errorLineAttr[x] = screenAttr[r + x]; + errorLineIsAttr[x] = screenIsAttr[r + x]; + errorLineGui[x] = screenGUI[r + x]; + } + } + } + + /** + * Restores the error line characters from the save buffer. + * + * @see #saveErrorLine() + */ + protected void restoreErrorLine() { + if (errorLine != null) { + int r = scr.getPos(errorLineNum - 1, 0); + + for (int x = 0; x < numCols - 1; x++) { + setScreenCharAndAttr(r + x, errorLine[x], errorLineAttr[x], + (errorLineIsAttr[x] == '1' ? true : false)); + screenGUI[x] = errorLineGui[x]; + } + + errorLine = null; + errorLineAttr = null; + errorLineIsAttr = null; + errorLineGui = null; + } + } + + protected boolean isErrorLineSaved() { + return errorLine == null ? false : true; + } + + protected void setScreenCharAndAttr(int pos, char c, int attr, boolean isAttr) { + screen[pos] = c; + screenAttr[pos] = (char)attr; + disperseAttribute(pos, attr); + screenIsAttr[pos] = (isAttr ? (char)1 : (char)0); + screenGUI[pos] = NO_GUI; + } + + protected void setScreenAttr(int pos, int attr, boolean isAttr) { + screenAttr[pos] = (char)attr; + screenIsAttr[pos] = isAttr ? (char)1 : (char)0; + disperseAttribute(pos, attr); + screenGUI[pos] = initChar; + } + + protected void setScreenAttr(int pos, int attr) { + screenAttr[pos] = (char)attr; + //screenGUI[pos] = initChar; + disperseAttribute(pos, attr); + } + + protected void setScreenFieldAttr(int pos, int attr) { + screenField[pos] = (char)attr; + } + + protected final void setChar(int pos, char c) { + screenIsChanged[pos] = screen[pos] == c ? '0' : '1'; + screen[pos] = c; + + if (screenIsAttr[pos] == 1) + setScreenCharAndAttr(pos, c, 32, false); + } + + protected final char getChar(int pos) { + return screen[pos]; + } + + protected final char getCharColor(int pos) { + return screenColor[pos]; + } + + protected final int getCharAttr(int pos) { + return screenAttr[pos]; + } + + protected final char getCharExtended(int pos) { + return screenExtended[pos]; + } + + protected final boolean isAttributePlace(int pos) { + return screenIsAttr[pos] == 1 ? true : false; + } + + public final void setUseGUI(int pos, int which) { + screenIsChanged[pos] = screenGUI[pos] == which ? '0' : '1'; + screenGUI[pos] = (char)which; + } + + private void disperseAttribute(int pos, int attr) { + char c = 0; + char cs = 0; + char ul = 0; + char nd = 0; + + if (attr == 0) + return; + + switch (attr) { + case 32: // green normal + c = ATTR_32; + break; + + case 33: // green/revers + c = ATTR_33; + break; + + case 34: // white normal + c = ATTR_34; + break; + + case 35: // white/reverse + c = ATTR_35; + break; + + case 36: // green/underline + c = ATTR_36; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 37: // green/reverse/underline + c = ATTR_37; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 38: // white/underline + c = ATTR_38; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 39: + nd = EXTENDED_5250_NON_DSP; + break; + + case 40: + case 42: // red/normal + c = ATTR_40; + break; + + case 41: + case 43: // red/reverse + c = ATTR_41; + break; + + case 44: + case 46: // red/underline + c = ATTR_44; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 45: // red/reverse/underline + c = ATTR_45; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 47: + nd = EXTENDED_5250_NON_DSP; + break; + + case 48: + c = ATTR_48; + cs = EXTENDED_5250_COL_SEP; + break; + + case 49: + c = ATTR_49; + cs = EXTENDED_5250_COL_SEP; + break; + + case 50: + c = ATTR_50; + cs = EXTENDED_5250_COL_SEP; + break; + + case 51: + c = ATTR_51; + cs = EXTENDED_5250_COL_SEP; + break; + + case 52: + c = ATTR_52; + // colSep = true; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 53: + c = ATTR_53; + // colSep = true; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 54: + c = ATTR_54; + // colSep = true; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 55: + nd = EXTENDED_5250_NON_DSP; + break; + + case 56: // pink + c = ATTR_56; + break; + + case 57: // pink/reverse + c = ATTR_57; + break; + + case 58: // blue/reverse + c = ATTR_58; + break; + + case 59: // blue + c = ATTR_59; + break; + + case 60: // pink/underline + c = ATTR_60; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 61: // pink/reverse/underline + c = ATTR_61; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 62: // blue/underline + c = ATTR_62; + ul = EXTENDED_5250_UNDERLINE; + break; + + case 63: // nondisplay + nd = EXTENDED_5250_NON_DSP; + cs = EXTENDED_5250_COL_SEP; + break; + + default: + c = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_YELLOW & 0xff); + break; + } + + screenColor[pos] = c; + screenExtended[pos] = (char)(ul | cs | nd); + } + + protected void initalizePlanes() { + char c = (COLOR_BG_BLACK << 8 & 0xff00) | + (COLOR_FG_GREEN & 0xff); + + for (int y = 0; y < screenSize; y++) { + screenAttr[y] = initAttr; + screenColor[y] = c; + } + + // here we will just copy the initialized plane onto the other planes + // using arraycopy which will be faster. I hope. + System.arraycopy(initArray, 0, screen, 0, screenSize); + System.arraycopy(initArray, 0, screenGUI, 0, screenSize); + System.arraycopy(initArray, 0, screenIsAttr, 0, screenSize); + System.arraycopy(initArray, 0, screenExtended, 0, screenSize); + System.arraycopy(initArray, 0, fieldExtended, 0, screenSize); + System.arraycopy(initArray, 0, screenField, 0, screenSize); + } + + protected void initalizeFieldPlanes() { + System.arraycopy(initArray, 0, fieldExtended, 0, screenSize); + System.arraycopy(initArray, 0, screenField, 0, screenSize); + } + + protected final int getWhichGUI(int pos) { + return screenGUI[pos]; + } + + protected final boolean isChanged(int pos) { + return screenIsChanged[pos] == 0 ? false : true; + } + + protected final boolean isUseGui(int pos) { + return screenGUI[pos] == NO_GUI ? false : true; + } + + /** + * Return the data associated with the plane that is passed. + * + * @param from Position from which to start + * @param to Position to end + * @param plane From which plane to obtain the data + * @return Character array containing the data requested + */ + + protected synchronized char[] getPlaneData(int from, int to, int plane) { + int len = (to - from); + char[] planeChars = new char[len + 1]; + + switch (plane) { + case PLANE_TEXT: + System.arraycopy(screen, from, planeChars, 0, len); + break; + + case PLANE_ATTR: + System.arraycopy(screenAttr, from, planeChars, 0, len); + break; + + case PLANE_COLOR: + System.arraycopy(screenColor, from, planeChars, 0, len); + break; + + case PLANE_EXTENDED: + System.arraycopy(screenExtended, from, planeChars, 0, len); + break; + + case PLANE_EXTENDED_GRAPHIC: + System.arraycopy(screenGUI, from, planeChars, 0, len); + break; + + case PLANE_FIELD: + System.arraycopy(screenField, from, planeChars, 0, len); + break; + + case PLANE_IS_ATTR_PLACE: + System.arraycopy(screenIsAttr, from, planeChars, 0, len); + break; + + default: + System.arraycopy(screen, from, planeChars, 0, len); + } + + return planeChars; + } + + /** + * Converts a linear presentation space position to its corresponding row. + * + * @param pos The position to be converted + * @return The row which corresponds to the position given + * @throws OhioException + */ + private int convertPosToRow(int pos) { + return (pos / numCols) + 1; + } + + /** + * Converts a linear presentation space position to its corresponding column. + * + * @param pos The position to be converted + * @return The column which corresponds to the position given + * @throws OhioException + */ + private int convertPosToColumn(int pos) { + return (pos % numCols) + 1; + } + + /** + * + * Converts a row and column coordinate to its corresponding linear position. + * + * @param row - The row of the coordinate + * @param col - The column of the coordinate + * @return The linear position which corresponds to the coordinate given. + * @throws OhioException + */ + private int convertRowColToPos(int row, int col) { + return (row - 1) * numCols + col - 1; + } + + + /** + * <p> + * GetScreen retrieves the various planes associated with the presentation + * space. The data is returned as a linear array of character values in the + * array provided. The array is not terminated by a null character except + * when data is retrieved from the text plane, in which case a single null + * character is appended. + * </p> + * <p> + * The application must supply a buffer for the returned data and the length + * of the buffer. Data is returned starting from the beginning of the + * presentation space and continuing until the buffer is full or the entire + * plane has been copied. For text plane data, the buffer must include one + * extra position for the terminating null character. + * <p> + * + * @param buffer + * @param bufferLength + * @param plane + * @return The number of characters copied to the buffer + * @throws OhioException + */ + + public synchronized int GetScreen(char buffer[], int bufferLength, int plane) { + return GetScreen(buffer, bufferLength, 0, screenSize, plane); + } + + /** + * <p> + * GetScreen retrieves the various planes associated with the presentation + * space. The data is returned as a linear array of character values in the + * array provided. The array is not terminated by a null character except + * when data is retrieved from the text plane, in which case a single null + * character is appended. + * </p> + * <p> + * The application must supply a buffer for the returned data and the length + * of the buffer. Data is returned starting from the given position and + * continuing until the specified number of characters have been copied, the + * buffer is full or the entire plane has been copied. For text plane data, + * the buffer must include one extra position for the terminating null character. + * </p> + * + * @param buffer + * @param bufferLength + * @param from + * @param length + * @param plane + * @return The number of characters copied to the buffer + * @throws OhioException + */ + + public synchronized int GetScreen(char buffer[], int bufferLength, int from, + int length, int plane) { + // if(buffer == null) + // throw new OhioException(sessionVT.getSessionConfiguration(), + // OhioScreen.class.getName(), "osohio.screen.ohio00300", 1); + if (buffer == null) + return 0; + + int min = Math.min(Math.min(buffer.length, bufferLength), screenSize); + + if ((from + min) > screenSize) { + min = screenSize - from; + } + + char[] pd = getPlaneData(from, from + min, plane); + + if (pd != null) { + System.arraycopy(pd, 0, buffer, 0, min); + return pd.length; + } + + return 0; + } + + /** + * <p> + * GetScreen retrieves the various planes associated with the presentation + * space. The data is returned as a linear array of character values in the + * array provided. The array is not terminated by a null character except + * when data is retrieved from the text plane, in which case a single null + * character is appended. + * </p> + * <p> + * The application must supply a buffer for the returned data and the length + * of the buffer. Data is returned starting from the given coordinates and + * continuing until the specified number of characters have been copied, + * the buffer is full, or the entire plane has been copied. For text plane + * data, the buffer must include one extra position for the terminating null + * character. + * </p> + * + * @param buffer + * @param bufferLength + * @param row + * @param col + * @param length + * @param plane + * @return The number of characters copied to the buffer. + * @throws OhioException + */ + + public synchronized int GetScreen(char buffer[], int bufferLength, int row, + int col, int length, int plane) + // throws OhioException { + { + // Call GetScreen function after converting row and column to + // a position. + return GetScreen(buffer, bufferLength, convertRowColToPos(row, col), + length, plane); + } + + /** + * <p> + * GetScreenRect retrieves data from the various planes associated with the + * presentation space. The data is returned as a linear array of character + * values in the buffer provided. + * </p> + * + * <p> + * The application supplies two positions that represent opposing corners of + * a rectangle within the presentation space. The starting and ending + * positions can have any spatial relationship to each other. The data + * returned starts from the row containing the upper-most point to the row + * containing the lower-most point, and from the left-most column to the + * right-most column. + * </p> + * <p> + * The specified buffer must be at least large enough to contain the number + * of characters in the rectangle. If the buffer is too small, no data is + * copied and zero is returned by the method. Otherwise, the method returns + * the number of characters copied. + * </p> + * + * @param buffer + * @param bufferLength + * @param startPos + * @param endPos + * @param plane + * @return The number of characters copied to the buffer + * @throws OhioException + */ + protected int GetScreenRect(char buffer[], int bufferLength, + int startPos, int endPos, int plane) + // throws OhioException { + { + // We will use the row,col routine here because it is easier to use + // row colum than it is for position since I wrote the other first and + // am to lazy to implement it here + // Maybe it would be faster to do it the other way? + int startRow = convertPosToRow(startPos); + int startCol = convertPosToColumn(startPos); + int endRow = convertPosToRow(endPos); + int endCol = convertPosToColumn(endPos); + return GetScreenRect(buffer, bufferLength, startRow, startCol, + endRow, endCol, plane); + } + + /** + * <p> + * GetScreenRect retrieves data from the various planes associated with the + * presentation space. The data is returned as a linear array of character + * values in the buffer provided. The buffer is not terminated by a null + * character. + * </p> + * <p> + * The application supplies two coordinates that represent opposing corners + * of a rectangle within the presentation space. The starting and ending + * coordinates can have any spatial relationship to each other. The data + * returned starts from the row containing the upper-most point to the row + * containing the lower-most point, and from the left-most column to the + * right-most column. + * </p> + * <p> + * The specified buffer must be at least large enough to contain the number + * of characters in the rectangle. If the buffer is too small, no data is + * copied and zero is returned by the method. Otherwise, the method returns + * the number of characters copied. + * </p> + * + * @param buffer + * @param bufferLength + * @param startRow + * @param startCol + * @param endRow + * @param endCol + * @param plane + * @return The number characters copied to the buffer + * @throws OhioException + */ + protected int GetScreenRect(char buffer[], int bufferLength, + int startRow, int startCol, + int endRow, int endCol, int plane) + // throws OhioException { + { + // number of bytes obtained + int numBytes = 0; + + // lets check the row range. If they are reversed then we need to + // place them in the correct order. + if (startRow > endRow) { + int r = startRow; + startRow = endRow; + endRow = r; + } + + // lets check the column range. If they are reversed then we need to + // place them in the correct order. + if (startCol > endCol) { + int c = startCol; + startCol = endCol; + endCol = c; + } + + int numCols = (endCol - startCol) + 1; + int numRows = (endRow - startRow) + 1; + + // lets make sure it is within the bounds of the character array passed + // if not the return as zero bytes where read as per documentation. + if (numCols * numRows <= bufferLength) { + // make sure it is one larger. I guess for other languanges to + // reference like in C which is terminated by a zero byte at the end + // of strings. + char cb[] = new char[numCols + 1]; + int charOffset = 0; + int bytes = 0; + + // now let's loop through and get the screen information for + // each row; + for (int row = startRow; row <= endRow;) { + if ((bytes = GetScreen(cb, cb.length, row, startCol, numCols, plane)) != 0) { + System.arraycopy(cb, 0, buffer, charOffset, numCols); + } + + row++; + charOffset += numCols; + // make sure we count the number of bytes returned + numBytes += bytes; + } + } + + return numBytes; + } + + private int isOption(char[] screen, + int x, + int lenScreen, + int numPref, + int numSuff, + char suff) { + boolean hs = true; + int sp = x; + int os = 0; + + // check to the left for option + while (--sp >= 0 && screen[sp] <= ' ') { + if (x - sp > numPref || screen[sp] == suff || + screen[sp] == '.' || + screen[sp] == '*') { + hs = false; + break; + } + } + + // now lets check for how long the option is it has to be numPref or less + os = sp; + + while (hs && --os > 0 && screen[os] > ' ') { + if (sp - os >= numPref || screen[os] == suff || + screen[os] == '.' || + screen[os] == '*') { + hs = false; + break; + } + } + + if (sp - os > 1 && !Character.isDigit(screen[os + 1])) { + hs = false; + } + + sp = x; + + if (Character.isDigit(screen[sp + 1])) + hs = false; + + // now lets make sure there are no more than numSuff spaces after option + while (hs && (++sp < lenScreen && screen[sp] <= ' ' + || screen[sp] == suff)) { + if (sp - x >= numSuff || screen[sp] == suff || + screen[sp] == '.' || + screen[sp] == '*') { + hs = false; + break; + } + } + + if (hs && !Character.isLetterOrDigit(screen[sp])) + hs = false; + + if (hs) { + return os; + } + + return -1; + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/Stream5250.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,164 @@ +/** + * Title: tn5250J + * Copyright: Copyright (c) 2001 + * Company: + * @author Kenneth J. Pouncey + * @version 0.4 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.framework.tn5250; + +public class Stream5250 { + + public int streamSize; + public int opCode; + public int dataStart; + public int pos; + public byte buffer[]; + + public Stream5250(byte abyte0[]) { + buffer = abyte0; + // size without end of record 0xFF 0xEF + streamSize = (abyte0[0] & 0xff) << 8 | abyte0[1] & 0xff; + opCode = abyte0[9]; + dataStart = 6 + abyte0[6]; + pos = dataStart; + } + + public Stream5250() { + buffer = null; + streamSize = 0; + opCode = 0; + dataStart = 0; + pos = dataStart; + } + + /** + * This method takes a byte array and initializes the object information + * to be used. + * + * @param abyte0 + */ + public void initialize(byte abyte0[]) { + buffer = abyte0; + // size without end of record 0xFF 0xEF + streamSize = (abyte0[0] & 0xff) << 8 | abyte0[1] & 0xff; + opCode = abyte0[9]; + dataStart = 6 + abyte0[6]; + pos = dataStart; + } + + public final int getOpCode() { + return opCode; + } + + public final byte getNextByte() + throws Exception { + if (buffer == null || pos > buffer.length) + throw new Exception("Buffer length exceeded: " + pos); + else + return buffer[pos++]; + } + + public final void setPrevByte() + throws Exception { + if (pos == 0) { + throw new Exception("Index equals zero."); + } + else { + pos--; + return; + } + } + + /** + * Returns where we are in the buffer + * @return position in the buffer + */ + public final int getCurrentPos() { + return pos; + } + + public final byte getByteOffset(int off) + throws Exception { + if (buffer == null || (pos + off) > buffer.length) + throw new Exception("Buffer length exceeded: " + pos); + else + return buffer[pos + off]; + } + + public final boolean size() { + return pos >= streamSize; + } + + + /** + * Determines if any more bytes are available in the buffer to be processed. + * @return yes or no + */ + public final boolean hasNext() { +// return pos >= buffer.length; + return pos < streamSize; + } + + /** + * This routine will retrieve a segment based on the first two bytes being + * the length of the segment. + * + * @return a new byte array containing the bytes of the segment. + * @throws Exception + */ + public final byte[] getSegment() throws Exception { + // The first two bytes contain the length of the segment. + int length = ((buffer[pos] & 0xff) << 8 | (buffer[pos + 1] & 0xff)); + // allocate space for it. + byte[] segment = new byte[length]; + getSegment(segment, length, true); + return segment; + } + + + /** + * This routine will retrieve a byte array based on the first two bytes being + * the length of the segment. + * + * @param segment - byte array + * @param length - length of segment to return + * @param adjustPos - adjust the position of the buffer to the end of the seg + * ment + * @throws Exception + */ + public final void getSegment(byte[] segment, int length, boolean adjustPos) + throws Exception { + // If the length is larger than what is available throw an exception + if ((pos + length) > buffer.length) + throw new Exception("Buffer length exceeded: start " + pos + + " length " + length); + + // use the system array copy to move the bytes from the buffer + // to the allocated byte array + System.arraycopy(buffer, pos, segment, 0, length); + + // update the offset to be after the segment so the next byte can be read + if (adjustPos) + pos += length; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/WTDSFParser.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,927 @@ +/** + * Title: tn5250J + * Copyright: Copyright (c) 2001 + * Company: + * @author Kenneth J. Pouncey + * @version 0.5 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.framework.tn5250; + +import static org.tn5250j.TN5250jConstants.BOTTOM; +import static org.tn5250j.TN5250jConstants.GUI_LEFT; +import static org.tn5250j.TN5250jConstants.GUI_RIGHT; +import static org.tn5250j.TN5250jConstants.LOWER_LEFT; +import static org.tn5250j.TN5250jConstants.LOWER_RIGHT; +import static org.tn5250j.TN5250jConstants.NO_GUI; +import static org.tn5250j.TN5250jConstants.NR_REQUEST_ERROR; +import static org.tn5250j.TN5250jConstants.UPPER; +import static org.tn5250j.TN5250jConstants.UPPER_LEFT; +import static org.tn5250j.TN5250jConstants.UPPER_RIGHT; + +import java.util.ArrayList; +import java.util.List; + +import org.tn5250j.encoding.ICodePage; +import android.util.Log; + + +/** + * + * Write To Display Structured Field: + * + * This module will parse the structured field information for enhanced + * emulation mode. + * + */ +public class WTDSFParser { + private static final String TAG = "WTDSFParser"; + private Screen5250 screen52; + private tnvt vt; + private ICodePage codePage; + int pos; + byte[] segment; + int length; + boolean error; + boolean guiStructsExist; + + + + private final List<Window> guiStructs = new ArrayList<Window>(3); + private final List<ChoiceField> choices = new ArrayList<ChoiceField>(3); + + + WTDSFParser(tnvt vt) { + this.vt = vt; + screen52 = vt.screen52; + codePage = vt.codePage; + } + + protected class ChoiceField { + + int x; + int y; + int row; + int col; + int width; + int height; + char mnemonic; + int fieldId; + int selectIndex; + + ChoiceField(int row, int col, int fldRow, int fldCol) { + x = row; + y = col; + row = fldRow; + col = fldCol; + } + } + + protected class Window { + + byte[] window; + int pos; + + Window(byte[] seg, int pos) { + //Log.i(TAG,"window created at " + pos); + window = seg; + this.pos = pos; + guiStructsExist = true; + } + + } + + protected void addChoiceField(int row, int col, int fldRow, int fldCol, String text) { + ChoiceField cf = new ChoiceField(row, col, fldRow, fldCol); + cf.fieldId = screen52.getScreenFields().getCurrentField().getFieldId(); + choices.add(cf); + } + + protected boolean isGuisExists() { + return guiStructsExist; + } + + protected byte[] getSegmentAtPos(int pos) { + int len = guiStructs.size(); + + for (int x = 0; x < len; x++) { + Window w = guiStructs.get(x); + + if (w.pos == pos) + return w.window; + } + + return null; + } + + protected void clearGuiStructs() { + guiStructs.clear(); + } + + protected boolean parseWriteToDisplayStructuredField(byte[] seg) { +// bk = vt.bk; + error = false; + boolean done = false; + boolean windowDefined = false; +// int nextone; + pos = 0; + segment = seg; +// try { + length = ((segment[pos++] & 0xff) << 8 | (segment[pos++] & 0xff)); + + while (!done) { + int s = segment[pos++] & 0xff; + + switch (s) { + case 0xD9: // Class Type 0xD9 - Create Window + switch (segment[pos++]) { + case 0x50: // Define Selection Field + defineSelectionField(length); + done = true; + break; + + case 0x51: // Create Window + guiStructs.add(new Window(segment, screen52.getLastPos())); + boolean cr = false; + int rows = 0; + int cols = 0; + + // pull down not supported yet + if ((segment[pos++] & 0x80) == 0x80) + cr = true; // restrict cursor + + pos++; // get reserved field pos 6 + pos++; // get reserved field pos 7 + rows = segment[pos++]; // get window depth rows pos 8 + cols = segment[pos++]; // get window width cols pos 9 + length -= 9; + + if (length == 0) { + done = true; +// System.out.println("Create Window"); +// System.out.println(" restrict cursor " + cr); +// System.out.println(" Depth = " + rows + " Width = " + cols); +// screen52.createWindow(rows,cols,1,true,32,58, + createWindow(rows, cols, 1, true, 32, 58, + '.', + '.', + '.', + ':', + ':', + ':', + '.', + ':'); + windowDefined = true; + break; + } + + // pos 10 is Minor Structure + int ml = 0; + int type = 0; + int lastPos = screen52.getLastPos(); +// if (cr) +// screen52.setPendingInsert(true, +// screen52.getCurrentRow(), +// screen52.getCurrentCol()); + int mAttr = 0; + int cAttr = 0; + + while (length > 0) { + // get minor length + ml = (segment[pos++] & 0xff); + length -= ml; + // only normal windows are supported at this time + type = segment[pos++]; + + switch (type) { + case 0x01 : // Border presentation + boolean gui = false; + + if ((segment[pos++] & 0x80) == 0x80) + gui = true; + + mAttr = segment[pos++]; + cAttr = segment[pos++]; + char ul = '.'; + char upper = '.'; + char ur = '.'; + char left = ':'; + char right = ':'; + char ll = ':'; + char bottom = '.'; + char lr = ':'; + + // if minor length is greater than 5 then + // the border characters are specified + if (ml > 5) { + ul = codePage.ebcdic2uni(segment[pos++]); + +// ul = getASCIIChar(segment[pos++]); + if (ul == 0) + ul = '.'; + + upper = codePage.ebcdic2uni(segment[pos++]); + +// upper = getASCIIChar(segment[pos++]); + if (upper == 0) + upper = '.'; + + ur = codePage.ebcdic2uni(segment[pos++]); + +// ur = getASCIIChar(segment[pos++]); + if (ur == 0) + ur = '.'; + + left = codePage.ebcdic2uni(segment[pos++]); + +// left = getASCIIChar(segment[pos++]); + if (left == 0) + left = ':'; + + right = codePage.ebcdic2uni(segment[pos++]); + +// right = getASCIIChar(segment[pos++]); + if (right == 0) + right = ':'; + + ll = codePage.ebcdic2uni(segment[pos++]); + +// ll = getASCIIChar(segment[pos++]); + if (ll == 0) + ll = ':'; + + bottom = codePage.ebcdic2uni(segment[pos++]); + +// bottom = getASCIIChar(segment[pos++]); + if (bottom == 0) + bottom = '.'; + + lr = codePage.ebcdic2uni(segment[pos++]); + +// lr = getASCIIChar(segment[pos++]); + if (lr == 0) + lr = ':'; + } + +// System.out.println("Create Window"); +// System.out.println(" restrict cursor " + cr); +// System.out.println(" Depth = " + rows + " Width = " + cols); +// System.out.println(" type = " + type + " gui = " + gui); +// System.out.println(" mono attr = " + mAttr + " color attr = " + cAttr); +// System.out.println(" ul = " + ul + " upper = " + upper + +// " ur = " + ur + +// " left = " + left + +// " right = " + right + +// " ll = " + ll + +// " bottom = " + bottom + +// " lr = " + lr +// ); +// screen52.createWindow(rows,cols,type,gui,mAttr,cAttr, + createWindow(rows, cols, type, gui, mAttr, cAttr, + ul, + upper, + ur, + left, + right, + ll, + bottom, + lr); + windowDefined = true; + break; + + // + // The following shows the input for window with a title + // + // +0000 019A12A0 00000400 00020411 00200107 .?.?..?...?..?. + // +0010 00000018 00000011 06131500 37D95180 ........?.?..R?? + // +0020 00000A24 0D018023 23404040 40404040 ..??..??? + // +0030 40211000 000000D7 C2C1D9C4 C5D4D67A \uFFFD.....PBARDEMO: + // +0040 40D79996 879985A2 A2408281 99408485 Progress bar de + // +0050 94961108 1520D5A4 94828599 40968640 mo.???Number of + // +0060 8595A399 8985A24B 4B4B4B4B 4B7A2011 entries......:?. + // +0070 082E2040 404040F5 F0F06BF0 F0F02011 ?.? 500,000?. + // +0080 091520C3 A4999985 95A34085 95A399A8 \uFFFD??Current entry + // +0090 4095A494 8285994B 4B4B7A20 11092E20 number...:?.\uFFFD.? + // +00A0 40404040 4040F56B F0F0F020 110A1520 5,000?.??? + // +00B0 D9859481 89958995 87408595 A3998985 Remaining entrie + // +00C0 A24B4B4B 4B4B4B7A 20110A2E 20404040 s......:?.?.? + // +00D0 40F4F9F5 6BF0F0F0 20110C15 20E2A381 495,000?..??Sta + // +00E0 99A340A3 8994854B 4B4B4B4B 4B4B4B4B rt time......... + // +00F0 4B4B4B4B 7A20110C 2F2040F7 7AF5F37A ....:?...? 7:53: + + case 0x10 : // Window title/footer + if (!windowDefined) { +// screen52.createWindow(rows,cols,1,true,32,58, + guiStructs.add(new Window(segment, screen52.getLastPos())); + createWindow(rows, cols, 1, true, 32, 58, + '.', + '.', + '.', + ':', + ':', + ':', + '.', + ':'); + windowDefined = true; + } + + byte orientation = segment[pos++]; + mAttr = segment[pos++]; + cAttr = segment[pos++]; + //reserved + pos++; + ml -= 6; + StringBuffer hfBuffer = new StringBuffer(ml); + + while (ml-- > 0) { + //LDC - 13/02/2003 - Convert it to unicode + hfBuffer.append(codePage.ebcdic2uni(segment[pos++])); +// hfBuffer.append(getASCIIChar(segment[pos++])); + } + + Log.d(TAG, + " orientation " + Integer.toBinaryString(orientation) + + " mAttr " + mAttr + + " cAttr " + cAttr + + " Header/Footer " + hfBuffer); + screen52.writeWindowTitle(lastPos, + rows, + cols, + orientation, + mAttr, + cAttr, + hfBuffer); + break; + + default: + Log.w(TAG, "Invalid Window minor structure"); + length = 0; + done = true; + } + } + + done = true; + break; + + case 0x53: // Scroll Bar + int sblen = 15; + byte sbflag = segment[pos++]; // flag position 5 + pos++; // reserved position 6 + // position 7,8 + int totalRowScrollable = ((segment[pos++] & 0xff) << 8 + | (segment[pos++] & 0xff)); + // position 9,10 + int totalColScrollable = ((segment[pos++] & 0xff) << 8 + | (segment[pos++] & 0xff)); + // position 11,12 + int sliderRowPos = ((segment[pos++] & 0xff) << 8 + | (segment[pos++] & 0xff)); + // position 13,14 + int sliderColPos = ((segment[pos++] & 0xff) << 8 + | (segment[pos++] & 0xff)); + // position 15 + int sliderRC = segment[pos++]; + screen52.createScrollBar(sbflag, totalRowScrollable, + totalColScrollable, + sliderRowPos, + sliderColPos, + sliderRC); + length -= 15; + done = true; + break; + + case 0x5B: // Remove GUI ScrollBar field + pos++; // reserved must be set to off pos 5 + pos++; // reserved must be set to zero pos 6 + done = true; + break; + + case 0x5F: // Remove All GUI Constructs + Log.i(TAG, "remove all gui contructs"); + clearGuiStructs(); + guiStructsExist = false; + int len = 4; + int d = 0; + length -= s; + + while (--len > 0) + d = segment[pos++]; + +// if (length > 0) { +// len = (segment[pos++] & 0xff )<< 8; +// +// while (--len > 0) +// d = segment[pos++]; +// } + screen52.clearGuiStuff(); + // per 14.6.13.4 documentation we should clear the + // format table after this command + screen52.clearTable(); + done = true; + break; + + case 0x59: // remove gui window + Log.i(TAG, " remove window at " + screen52.getCurrentPos()); + done = true; + break; + + case 0x60: // Erase/Draw Grid Lines - not supported + // do not know what they are + // as of 03/11/2002 we should not be getting + // this anymore but I will leave it here + // just in case. +// System.out.println("erase/draw grid lines " + length); + len = 6; + d = 0; + length -= 9; + + while (--len > 0) + d = segment[pos++]; + + if (length > 0) { + len = (segment[pos++] & 0xff) << 8; + + while (--len > 0) { + d = segment[pos++]; + } + } + + done = true; + break; + + default: + vt.sendNegResponse(NR_REQUEST_ERROR, 0x03, 0x01, 0x01, "invalid wtd structured field sub command " + + (pos - 1)); +// + bk.getByteOffset(-1)); + error = true; + break; + } + + break; + + default: + vt.sendNegResponse(NR_REQUEST_ERROR, 0x03, 0x01, 0x01, + "invalid wtd structured field command " + + (pos - 1)); +// + bk.getByteOffset(-1)); + error = true; + break; + } + + if (error) + done = true; + } + +// } +// catch (Exception e) {}; + return error; + } + + /** + * Creates a window on the screen + * + * @param depth + * @param width + * @param type + * @param gui + * @param monoAttr + * @param colorAttr + * @param ul + * @param upper + * @param ur + * @param left + * @param right + * @param ll + * @param bottom + * @param lr + */ + protected void createWindow(int depth, int width, int type, boolean gui, + int monoAttr, int colorAttr, int ul, int upper, int ur, int left, + int right, int ll, int bottom, int lr) { + int lastPos = screen52.getLastPos(); + int numCols = screen52.getColumns(); + int c = screen52.getCol(lastPos); + int w = 0; + width++; + w = width; + char initChar = Screen5250.initChar; + int initAttr = Screen5250.initAttr; + // set leading attribute byte + screen52.setScreenCharAndAttr(initChar, initAttr, true); + + // set upper left + if (gui) { + screen52.setScreenCharAndAttr((char) ul, colorAttr, UPPER_LEFT, false); + } + else { + screen52.setScreenCharAndAttr((char) ul, colorAttr, false); + } + + // draw top row + while (w-- >= 0) { + if (gui) { + screen52.setScreenCharAndAttr((char) upper, colorAttr, UPPER, false); + } + else { + screen52.setScreenCharAndAttr((char) upper, colorAttr, false); + } + } + + // set upper right + if (gui) { + screen52.setScreenCharAndAttr((char) ur, colorAttr, UPPER_RIGHT, false); + } + else { + screen52.setScreenCharAndAttr((char) ur, colorAttr, false); + } + + // set ending attribute byte + screen52.setScreenCharAndAttr(initChar, initAttr, true); + lastPos = ((screen52.getRow(lastPos) + 1) * numCols) + c; + screen52.goto_XY(lastPos); + + // now handle body of window + while (depth-- > 0) { + // set leading attribute byte + screen52.setScreenCharAndAttr(initChar, initAttr, true); + + // set left + if (gui) { + screen52.setScreenCharAndAttr((char) left, colorAttr, GUI_LEFT, false); + } + else { + screen52.setScreenCharAndAttr((char) left, colorAttr, false); + } + + w = width - 2; + screen52.setScreenCharAndAttr(initChar, initAttr, NO_GUI, true); + + // fill it in + while (w-- >= 0) { +// if (!planes.isUseGui(screen52.getLastPos())) + screen52.setScreenCharAndAttr(initChar, initAttr, NO_GUI, false); + } + + screen52.setScreenCharAndAttr(initChar, initAttr, NO_GUI, true); + + // set right + if (gui) { + screen52.setScreenCharAndAttr((char) right, colorAttr, GUI_RIGHT, false); + } + else { + screen52.setScreenCharAndAttr((char) right, colorAttr, false); + } + + screen52.setScreenCharAndAttr(initChar, initAttr, true); + lastPos = ((screen52.getRow(lastPos) + 1) * numCols) + c; + screen52.goto_XY(lastPos); + } + + // set leading attribute byte + screen52.setScreenCharAndAttr(initChar, initAttr, true); + + if (gui) { + screen52.setScreenCharAndAttr((char) ll, colorAttr, LOWER_LEFT, false); + } + else { + screen52.setScreenCharAndAttr((char) ll, colorAttr, false); + } + + w = width; + + // draw bottom row + while (w-- >= 0) { + if (gui) { + screen52.setScreenCharAndAttr((char) bottom, colorAttr, BOTTOM, false); + } + else { + screen52.setScreenCharAndAttr((char) bottom, colorAttr, false); + } + } + + // set lower right + if (gui) { + screen52.setScreenCharAndAttr((char) lr, colorAttr, LOWER_RIGHT, false); + } + else { + screen52.setScreenCharAndAttr((char) lr, colorAttr, false); + } + + // set ending attribute byte + screen52.setScreenCharAndAttr(initChar, initAttr, true); + } + + /* *** NEVER USED LOCALLY ************************************************** */ +// private void clearWindowBody(ScreenPlanes planes, int startPos, int depth, int width) { +// +// int lastPos = startPos; +// char initChar = Screen5250.initChar; +// int initAttr = Screen5250.initAttr; +// +// // now handle body of window +// while (depth-- > 0) { +// +// // set leading attribute byte +//// planes.setScreenCharAndAttr(lastPos,initChar, initAttr, true); +//// setDirty(lastPos); +//// advancePos(); +//// +//// // set left +//// planes.setScreenCharAndAttr(lastPos, (char) left, colorAttr, false); +//// +//// if (gui) { +//// planes.setUseGUI(lastPos,GUI_LEFT); +//// } +//// setDirty(lastPos); +//// advancePos(); +// +// int w = width; +// // fill it in +// while (w-- >= 0) { +//// screen[lastPos].setCharAndAttr(initChar, initAttr, true); +// planes.setScreenCharAndAttr(lastPos,initChar, initAttr, true); +//// screen[lastPos].setUseGUI(NO_GUI); +// planes.setUseGUI(lastPos,NO_GUI); +//// setDirty(lastPos); +// lastPos++; +// advancePos(); +// } +// +//// // set right +//// // screen[lastPos].setCharAndAttr((char) right, colorAttr, false); +//// planes.setScreenCharAndAttr(lastPos,(char) right, colorAttr, false); +//// if (gui) { +//// // screen[lastPos].setUseGUI(RIGHT); +//// planes.setUseGUI(lastPos,GUI_RIGHT); +//// } +//// +//// setDirty(lastPos); +//// advancePos(); +//// +//// // set ending attribute byte +//// // screen[lastPos].setCharAndAttr(initChar, initAttr, true); +//// planes.setScreenCharAndAttr(lastPos,initChar, initAttr, true); +//// setDirty(lastPos); +// +// lastPos = startPos; +// } +// +// } + + /* *** NEVER USED LOCALLY ************************************************** */ +// private void setDirty(int pos) { +// +// screen52.setDirty(pos); +// +// } + + /* *** NEVER USED LOCALLY ************************************************** */ +// private void advancePos() { +// +// screen52.advancePos(); +// } + + private void defineSelectionField(int majLen) { + // 0030: 20 00 2C 3E 00 00 00 69 12 A0 00 00 04 00 00 03 .,>...i........ + // 0040: 04 40 04 11 00 28 01 07 00 00 00 19 00 00 04 11 .@...(.......... + // 0050: 14 19 15 00 48 D9 50 00 60 00 11 01 84 84 00 00 ....H.P.`....... + // 0060: 05 03 01 01 00 00 00 13 01 E0 00 21 00 21 00 3B ...........!.!.; + // 0070: 22 20 20 20 20 3A 24 20 20 3A 0B 10 08 00 E0 00 " :$ :...... + // 0080: D6 95 85 40 40 0B 10 08 00 E0 00 E3 A6 96 40 40 ...@@.........@@ + // 0090: 0B 10 08 00 E0 00 E3 88 99 85 85 04 52 00 00 FF ............R... + // 00A0: EF . + try { + int flag1 = segment[pos++]; // Flag byte 1 - byte 5 + int flag2 = segment[pos++]; // Flag byte 2 - byte 6 + int flag3 = segment[pos++]; // Flag byte 3 - byte 7 + int typeSelection = segment[pos++]; // Type of selection Field - byte 8 + // GUI Device Characteristics: + // This byte is used if the target device is a GUI PWS or a GUI-like + // NWS. If neigher of these WS are the targets, this byte is ignored + int guiDevice = segment[pos++]; // byte 9 + int withMnemonic = segment[pos++]; // byte 10 + int noMnemonic = segment[pos++]; // byte 11 + pos++; // Reserved - byte 12 + pos++; // Reserved - byte 13 + int cols = segment[pos++]; // Text Size - byte 14 + int rows = segment[pos++]; // Rows - byte 15 + int maxColChoice = segment[pos++]; // byte 16 num of column choices + int padding = segment[pos++]; // byte 17 + int numSepChar = segment[pos++]; // byte 18 + int ctySepChar = segment[pos++]; // byte 19 + int cancelAID = segment[pos++]; // byte 20 + int cnt = 0; + int minLen = 0; + majLen -= 21; + Log.d(TAG, " row: " + screen52.getCurrentRow() + + " col: " + screen52.getCurrentCol() + + " type " + typeSelection + + " gui " + guiDevice + + " withMnemonic " + Integer.toHexString(withMnemonic & 0xf0) + + " noMnemonic " + Integer.toHexString(noMnemonic & 0xf0) + + " noMnemonic " + Integer.toBinaryString(noMnemonic) + + " noMnemonicType " + Integer.toBinaryString((noMnemonic & 0xf0)) + + " noMnemonicSel " + Integer.toBinaryString((noMnemonic & 0x0f)) + + " maxcols " + maxColChoice + + " cols " + cols + + " rows " + rows); + int rowCtr = 0; + int colCtr = 0; + int chcRowStart = screen52.getCurrentRow(); + int chcColStart = screen52.getCurrentCol(); + int chcRow = chcRowStart; + int chcCol = chcColStart; + int chcPos = screen52.getPos(chcRow - 1, chcCol); +// client access +//0000 00 04 ac 9e b9 35 00 01 02 32 bb 4e 08 00 45 00 .....5...2.N..E. +//0010 00 3c 4f 8e 40 00 80 06 00 00 c1 a8 33 58 c1 a8 .<O.@.......3X.. +//0020 33 01 09 e4 00 17 5b bf b7 a4 c3 41 43 d1 50 18 3.....[....AC.P. +//0030 fc de e9 d8 00 00 00 12 12 a0 00 00 04 00 80 03 ................ +//0040 16 18 f1 11 14 1a 00 22 ff ef .......".. + int colAvail = 0x20; + int colSelAvail = 0x20; + int fld = 0; + + do { + minLen = segment[pos++]; // Minor Length byte 21 + int minType = segment[pos++]; // Minor Type + + switch (minType) { + case 0x01: // Choice Presentation Display + // flag + int flagCP1 = segment[pos++]; + pos++; // mon select cursor avail emphasis - byte4 + colSelAvail = segment[pos++]; // -byte 5 + pos++; // mon select cursor - byte 6 + int colSelCur = segment[pos++]; // -byte 7 + pos++; // mon select cursor not avail emphasis - byte 8 + int colSelNotAvail = segment[pos++]; // -byte 9 + pos++; // mon avail emphasis - byte 10 + colAvail = segment[pos++]; // -byte 11 + pos++; // mon select emphasis - byte 12 + int colSel = segment[pos++]; // -byte 13 + pos++; // mon not avail emphasis - byte 14 + int colNotAvail = segment[pos++]; // -byte 15 + pos++; // mon indicator emphasis - byte 16 + int colInd = segment[pos++]; // -byte 17 + pos++; // mon indicator not avail emphasis - byte 18 + int colNotAvailInd = segment[pos++]; // -byte 19 + break; + + case 0x10: // Choice Text minor structure + cnt = 5; + int flagCT1 = segment[pos++]; + int flagCT2 = segment[pos++]; + int flagCT3 = segment[pos++]; + int mnemOffset = 0; + boolean aid = false; + boolean selected = false; + + // is in selected state + if ((flagCT1 & 0x40) == 0x40) { + Log.d(TAG, " selected "); + selected = true; + } + + //System.out.println(Integer.toBinaryString((flagCT1 & 0xf0))); + // is mnemonic offset specified + if ((flagCT1 & 0x08) == 8) { + Log.d(TAG, " mnemOffset " + mnemOffset); + mnemOffset = segment[pos++]; + cnt++; + } + + // is aid key specified + if ((flagCT1 & 0x04) == 4) { + aid = true; + Log.d(TAG, " aidKey " + aid); +// cnt++; + } + + // is single digit number specified + if ((flagCT1 & 0x01) == 0x01) { + Log.d(TAG, " single digit "); + pos++; + cnt++; + } + + // is double digint number specified + if ((flagCT1 & 0x02) == 0x02) { + Log.d(TAG, " double digit "); + pos++; + cnt++; + } + + String s = ""; + byte byte0 = 0; + fld++; + screen52.setCursor(chcRowStart, chcColStart); + + // we do not add a selection if it is marked as unavailable + if ((flagCT1 & 0x80) != 0x80) { + screen52.addField(0x26, 1, 0, 0, 0, 0); + screen52.getScreenFields().getCurrentField().setFieldChar('.'); + screen52.getScreenFields().getCurrentField().setSelectionFieldInfo(17, + fld, + chcPos); + screen52.setCursor(chcRowStart, chcColStart + 3); + + for (; cnt < minLen; cnt++) { + byte0 = segment[pos++]; + s += vt.codePage.ebcdic2uni(byte0); + screen52.setChar(vt.codePage.ebcdic2uni(byte0)); + } + + addChoiceField(chcRowStart, chcColStart, chcRow, chcCol, s); + } + +// screen52.getScreenFields().getCurrentField().setMDT(); + Log.d(TAG, s + " selected " + selected); +// chcRowStart; + //maxColChoice + colCtr++; + +// rowCtr++; + if (colCtr >= maxColChoice) { + rowCtr++; + colCtr = 0; + chcColStart = chcCol; + chcRowStart = chcRow + rowCtr; + + if (rowCtr > rows) { + chcRowStart = chcRow; + rowCtr = 0; + chcColStart = chcColStart + 3 + cols + padding; + } + } + else { + chcColStart = chcColStart + padding + cols + 3; +// + } + + break; + + default: + for (cnt = 2; cnt < minLen; cnt++) { + pos++; + } + } + + majLen -= minLen; + } + while (majLen > 0); + } + catch (Exception exc) { + Log.w(TAG, " defineSelectionField :", exc); + exc.printStackTrace(); + } + } + + // negotiating commands +// private static final byte IAC = (byte)-1; // 255 FF +// private static final byte DONT = (byte)-2; //254 FE +// private static final byte DO = (byte)-3; //253 FD +// private static final byte WONT = (byte)-4; //252 FC +// private static final byte WILL = (byte)-5; //251 FB +// private static final byte SB = (byte)-6; //250 Sub Begin FA +// private static final byte SE = (byte)-16; //240 Sub End F0 +// private static final byte EOR = (byte)-17; //239 End of Record EF +// private static final byte TERMINAL_TYPE = (byte)24; // 18 +// private static final byte OPT_END_OF_RECORD = (byte)25; // 19 +// private static final byte TRANSMIT_BINARY = (byte)0; // 0 +// private static final byte QUAL_IS = (byte)0; // 0 +// private static final byte TIMING_MARK = (byte)6; // 6 +// private static final byte NEW_ENVIRONMENT = (byte)39; // 27 +// private static final byte IS = (byte)0; // 0 +// private static final byte SEND = (byte)1; // 1 +// private static final byte INFO = (byte)2; // 2 +// private static final byte VAR = (byte)0; // 0 +// private static final byte VALUE = (byte)1; // 1 +// private static final byte NEGOTIATE_ESC = (byte)2; // 2 +// private static final byte USERVAR = (byte)3; // 3 + + // miscellaneous +// private static final byte ESC = 0x04; // 04 +// private static final char char0 = 0; + +// private static final byte CMD_READ_IMMEDIATE_ALT = (byte)0x83; // 131 + + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/tn5250/tnvt.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,2609 @@ +/** + * Title: tnvt.java + * Copyright: Copyright (c) 2001 Company: + * + * @author Kenneth J. Pouncey + * @version 0.5 + * + * Description: + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this software; see the file COPYING. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.framework.tn5250; + +import static java.lang.Math.max; +import static java.lang.Math.min; +import static org.tn5250j.TN5250jConstants.AID_HELP; +import static org.tn5250j.TN5250jConstants.AID_PRINT; +import static org.tn5250j.TN5250jConstants.CMD_CLEAR_FORMAT_TABLE; +import static org.tn5250j.TN5250jConstants.CMD_CLEAR_UNIT; +import static org.tn5250j.TN5250jConstants.CMD_CLEAR_UNIT_ALTERNATE; +import static org.tn5250j.TN5250jConstants.CMD_READ_INPUT_FIELDS; +import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_FIELDS; +import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_IMMEDIATE_ALT; +import static org.tn5250j.TN5250jConstants.CMD_READ_SCREEN_IMMEDIATE; +import static org.tn5250j.TN5250jConstants.CMD_READ_SCREEN_TO_PRINT; +import static org.tn5250j.TN5250jConstants.CMD_RESTORE_SCREEN; +import static org.tn5250j.TN5250jConstants.CMD_ROLL; +import static org.tn5250j.TN5250jConstants.CMD_SAVE_SCREEN; +import static org.tn5250j.TN5250jConstants.CMD_WRITE_ERROR_CODE; +import static org.tn5250j.TN5250jConstants.CMD_WRITE_ERROR_CODE_TO_WINDOW; +import static org.tn5250j.TN5250jConstants.CMD_WRITE_STRUCTURED_FIELD; +import static org.tn5250j.TN5250jConstants.CMD_WRITE_TO_DISPLAY; +import static org.tn5250j.TN5250jConstants.NR_REQUEST_ERROR; +import static org.tn5250j.TN5250jConstants.PF1; +import static org.tn5250j.TN5250jConstants.PF10; +import static org.tn5250j.TN5250jConstants.PF11; +import static org.tn5250j.TN5250jConstants.PF12; +import static org.tn5250j.TN5250jConstants.PF13; +import static org.tn5250j.TN5250jConstants.PF14; +import static org.tn5250j.TN5250jConstants.PF15; +import static org.tn5250j.TN5250jConstants.PF16; +import static org.tn5250j.TN5250jConstants.PF17; +import static org.tn5250j.TN5250jConstants.PF18; +import static org.tn5250j.TN5250jConstants.PF19; +import static org.tn5250j.TN5250jConstants.PF2; +import static org.tn5250j.TN5250jConstants.PF20; +import static org.tn5250j.TN5250jConstants.PF21; +import static org.tn5250j.TN5250jConstants.PF22; +import static org.tn5250j.TN5250jConstants.PF23; +import static org.tn5250j.TN5250jConstants.PF24; +import static org.tn5250j.TN5250jConstants.PF3; +import static org.tn5250j.TN5250jConstants.PF4; +import static org.tn5250j.TN5250jConstants.PF5; +import static org.tn5250j.TN5250jConstants.PF6; +import static org.tn5250j.TN5250jConstants.PF7; +import static org.tn5250j.TN5250jConstants.PF8; +import static org.tn5250j.TN5250jConstants.PF9; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.util.Arrays; +import java.util.Properties; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLSocket; + +import android.content.Intent; +import android.net.Uri; +import android.util.Log; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.bean.HostBean; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; +import de.mud.terminal.vt320; + +import org.tn5250j.TN5250jConstants; +import org.tn5250j.encoding.CharMappings; +import org.tn5250j.encoding.ICodePage; +import org.tn5250j.framework.transport.SocketConnector; + + +public final class tnvt implements Runnable { + private static final String TAG = "tnvt"; + // negotiating commands + private static final byte IAC = (byte) - 1; // 255 FF + private static final byte DONT = (byte) - 2; //254 FE + private static final byte DO = (byte) - 3; //253 FD + private static final byte WONT = (byte) - 4; //252 FC + private static final byte WILL = (byte) - 5; //251 FB + private static final byte SB = (byte) - 6; //250 Sub Begin FA + private static final byte SE = (byte) - 16; //240 Sub End F0 + private static final byte EOR = (byte) - 17; //239 End of Record EF + private static final byte TERMINAL_TYPE = (byte) 24; // 18 + private static final byte OPT_END_OF_RECORD = (byte) 25; // 19 + private static final byte TRANSMIT_BINARY = (byte) 0; // 0 + private static final byte QUAL_IS = (byte) 0; // 0 + private static final byte TIMING_MARK = (byte) 6; // 6 + private static final byte NEW_ENVIRONMENT = (byte) 39; // 27 + private static final byte IS = (byte) 0; // 0 + private static final byte SEND = (byte) 1; // 1 + private static final byte INFO = (byte) 2; // 2 + private static final byte VAR = (byte) 0; // 0 + private static final byte VALUE = (byte) 1; // 1 + private static final byte NEGOTIATE_ESC = (byte) 2; // 2 + private static final byte USERVAR = (byte) 3; // 3 + + // miscellaneous + private static final byte ESC = 0x04; // 04 + + private Socket sock; + public BufferedInputStream bin; + public BufferedOutputStream bout; + private final BlockingQueue<Object> dsq = new ArrayBlockingQueue<Object>(25); + private Stream5250 bk; + private DataStreamProducer producer; + protected Screen5250 screen52; + private boolean waitingForInput; + private boolean invited; + private boolean negotiated = false; + private Thread me; + private Thread pthread; + private int readType; + private boolean enhanced = true; + private boolean cursorOn = false; + private String hostname = ""; + private int port = 23; + private vt320 buffer; + private boolean connected = false; + private boolean support132 = true; + private ByteArrayOutputStream baosp = null; + private ByteArrayOutputStream baosrsp = null; + private int devSeq = -1; + private String devName; + private String devNameUsed; + private KbdTypesCodePages kbdTypesCodePage; + // WVL - LDC : TR.000300 : Callback scenario from 5250 + private boolean scan; // = false; + private static int STRSCAN = 1; + // WVL - LDC : 05/08/2005 : TFX.006253 - support STRPCCMD + private boolean strpccmd; // = false; + private String encryption; + private String user; + private String password = null; + private String library; + private String initialMenu; + private String program; + private boolean keepTrucking = true; + private boolean pendingUnlock = false; + private boolean[] dataIncluded; + protected ICodePage codePage; + private String sslType; + private WTDSFParser sfParser; + private TerminalBridge bridge; + private TerminalManager manager; + + + + /** + * @param screen52 + * @param enhanced + * @param support132 + * @param bridge + * @param manager + */ + public tnvt(Screen5250 screen52, boolean enhanced, boolean support132, TerminalBridge bridge, TerminalManager manager) { + this.screen52 = screen52; + this.support132 = support132; + this.enhanced = enhanced; + this.bridge = bridge; + this.manager = manager; + setCodePage("37"); + dataIncluded = new boolean[24]; + baosp = new ByteArrayOutputStream(); + baosrsp = new ByteArrayOutputStream(); + } + + public void showURL(String url) { + if (url.indexOf("://") < 0) url = "http://" + url; + + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + manager.startActivity(intent); + } + + public String getHostName() { + return hostname; + } + + public void setDeviceName(String name) { + devName = name; + } + + public String getDeviceName() { + return devName; + } + + public String getAllocatedDeviceName() { + return devNameUsed; + } + + public boolean isConnected() { + return connected; + } + + /** + * @return true when SSL is used and socket is connected. + * @see {@link #isConnected()} + */ + public boolean isSslSocket() { + if (this.connected && this.sock != null && this.sock instanceof SSLSocket) { + return true; + } + else { + return false; + } + } + + public final void setProxy(String proxyHost, String proxyPort) { + Properties systemProperties = System.getProperties(); + systemProperties.put("socksProxySet", "true"); + systemProperties.put("socksProxyHost", proxyHost); + systemProperties.put("socksProxyPort", proxyPort); + System.setProperties(systemProperties); + Log.i(TAG, " socks set "); + } + + private String fixer(String value, String def) { + if ((value == null) || (value.length() == 0)) return def; + + return value; + } + + public final boolean connect(HostBean host, String homeDirectory, vt320 buffer) { + try { + this.hostname = host.getHostname(); + this.port = host.getPort(); + this.buffer = buffer; + this.encryption = fixer(host.getEncryption5250(), "NONE"); + this.user = host.getUsername(); + this.library = host.getLibrary(); + this.initialMenu = host.getInitialMenu(); + this.program = host.getProgram(); + + try { + screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED, "X - Connecting"); + } + catch (Exception exc) { + Log.w(TAG, "setStatus(ON) " + exc.getMessage()); + } + + SocketConnector sc = new SocketConnector(); + sock = sc.createSocket(hostname, port, encryption, homeDirectory, bridge, manager); + + if (sock == null) { + Log.w(TAG, "I did not get a socket"); + disconnect(); + return false; + } + + connected = true; + // used for JDK1.3 + sock.setKeepAlive(true); + sock.setTcpNoDelay(true); + sock.setSoLinger(false, 0); + InputStream in = sock.getInputStream(); + OutputStream out = sock.getOutputStream(); + bin = new BufferedInputStream(in, 8192); + bout = new BufferedOutputStream(out); + byte abyte0[]; + + while (negotiate(abyte0 = readNegotiations())); + + negotiated = true; + + try { + screen52.setCursorActive(false); + } + catch (Exception excc) { + Log.w(TAG, "setCursorOff " + excc.getMessage()); + } + + producer = new DataStreamProducer(this, bin, dsq, abyte0); + pthread = new Thread(producer); + // pthread.setPriority(pthread.MIN_PRIORITY); + pthread.setPriority(Thread.NORM_PRIORITY); + // pthread.setPriority(Thread.NORM_PRIORITY / 2); + pthread.start(); + + try { + screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); + } + catch (Exception exc) { + Log.w(TAG, "setStatus(OFF) " + exc.getMessage()); + } + + keepTrucking = true; + me = new Thread(this); + me.start(); + } + catch (Exception exception) { + if (exception.getMessage() == null) + exception.printStackTrace(); + + Log.w(TAG, "connect() " + exception.getMessage()); + + if (sock == null) + Log.w(TAG, "I did not get a socket"); + + disconnect(); + return false; + } + + return true; + } + + public final boolean disconnect() { + if (!connected) { + screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED, "X - Disconnected"); + return false; + } + + if (me != null && me.isAlive()) { + me.interrupt(); + keepTrucking = false; + pthread.interrupt(); + } + + screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED, "X - Disconnected"); + screen52.getOIA().setKeyBoardLocked(false); + pendingUnlock = false; + + try { + if (sock != null) { + Log.i(TAG, "Closing socket"); + sock.close(); + } + + if (bin != null) bin.close(); + + if (bout != null) bout.close(); + + connected = false; + // WVL - LDC : TR.000345 : properly disconnect and clear screen + // Is this the right place to set screen realestate on disconnect? + //controller.getScreen().clearAll(); + screen52.goto_XY(0); + screen52.setCursorActive(false); + screen52.clearAll(); + screen52.restoreScreen(); + } + catch (Exception exception) { + Log.w(TAG, exception.getMessage()); + connected = false; + devSeq = -1; + return false; + } + + devSeq = -1; + return true; + } + + private final ByteArrayOutputStream appendByteStream(byte abyte0[]) { + ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); + + for (int i = 0; i < abyte0.length; i++) { + bytearrayoutputstream.write(abyte0[i]); + + if (abyte0[i] == -1) + bytearrayoutputstream.write(-1); + } + + return bytearrayoutputstream; + } + + private final byte[] readNegotiations() throws IOException { + int i = bin.read(); + + if (i < 0) { + throw new IOException("Connection closed."); + } + else { + int j = bin.available(); + byte abyte0[] = new byte[j + 1]; + abyte0[0] = (byte) i; + bin.read(abyte0, 1, j); + return abyte0; + } + } + + private final void writeByte(byte abyte0[]) throws IOException { + bout.write(abyte0); + bout.flush(); + } + + private final void readImmediate(int readType) { + if (screen52.isStatusErrorCode()) { + screen52.restoreErrorLine(); + screen52.setStatus(Screen5250.STATUS_ERROR_CODE, + Screen5250.STATUS_VALUE_OFF, null); + } + + if (!enhanced) { + screen52.setCursorActive(false); + } + + // screen52.setStatus(Screen5250.STATUS_SYSTEM, + // Screen5250.STATUS_VALUE_ON, null); + screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); + screen52.getOIA().setKeyBoardLocked(true); + pendingUnlock = false; + invited = false; + screen52.getScreenFields().readFormatTable(baosp, readType, codePage); + + try { + Log.i(TAG, "readImmediate() writeGDS()"); + writeGDS(0, 3, baosp.toByteArray()); + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + } + + baosp.reset(); + } + + public final boolean sendAidKey(int aid) { + if (screen52.isStatusErrorCode()) { + screen52.restoreErrorLine(); + screen52.setStatus(Screen5250.STATUS_ERROR_CODE, + Screen5250.STATUS_VALUE_OFF, null); + } + + if (!enhanced) { + screen52.setCursorActive(false); + } + + // screen52.setStatus(Screen5250.STATUS_SYSTEM, + // Screen5250.STATUS_VALUE_ON, null); + screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); + screen52.getOIA().setKeyBoardLocked(true); + pendingUnlock = false; + invited = false; + baosp.write(screen52.getCurrentRow()); + baosp.write(screen52.getCurrentCol()); + baosp.write(aid); + + if (dataIncluded(aid)) + screen52.getScreenFields().readFormatTable(baosp, readType, + codePage); + + try { + Log.i(TAG, "sendAidKey() writeGDS()"); + writeGDS(0, 3, baosp.toByteArray()); + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + baosp.reset(); + return false; + } + + baosp.reset(); + return true; + } + + private boolean dataIncluded(int aid) { + switch (aid) { + case PF1: + return !dataIncluded[0]; + + case PF2: + return !dataIncluded[1]; + + case PF3: + return !dataIncluded[2]; + + case PF4: + return !dataIncluded[3]; + + case PF5: + return !dataIncluded[4]; + + case PF6: + return !dataIncluded[5]; + + case PF7: + return !dataIncluded[6]; + + case PF8: + return !dataIncluded[7]; + + case PF9: + return !dataIncluded[8]; + + case PF10: + return !dataIncluded[9]; + + case PF11: + return !dataIncluded[10]; + + case PF12: + return !dataIncluded[11]; + + case PF13: + return !dataIncluded[12]; + + case PF14: + return !dataIncluded[13]; + + case PF15: + return !dataIncluded[14]; + + case PF16: + return !dataIncluded[15]; + + case PF17: + return !dataIncluded[16]; + + case PF18: + return !dataIncluded[17]; + + case PF19: + return !dataIncluded[18]; + + case PF20: + return !dataIncluded[19]; + + case PF21: + return !dataIncluded[20]; + + case PF22: + return !dataIncluded[21]; + + case PF23: + return !dataIncluded[22]; + + case PF24: + return !dataIncluded[23]; + + default: + return true; + } + } + + /** + * Help request - + * + * + * See notes inside method + */ + public final void sendHelpRequest() { + // Client sends header 000D12A0000004000003####F3FFEF + // operation code 3 + // row - first ## + // column - second ## + // F3 - Help Aid Key + // System.out.println("Help request sent"); + baosp.write(screen52.getCurrentRow()); + baosp.write(screen52.getCurrentCol()); + baosp.write(AID_HELP); + + try { + Log.i(TAG, "sendHelpRequest() writeGDS()"); + writeGDS(0, 3, baosp.toByteArray()); + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + } + + baosp.reset(); + } + + /** + * Attention Key - + * + * + * See notes inside method + */ + public final void sendAttentionKey() { + // Client sends header 000A12A000004400000FFEF + // 0x40 -> 01000000 + // + // flags + // bit 0 - ERR + // bit 1 - ATN Attention + // bits 2-4 - reserved + // bit 5 - SRQ system request + // bit 6 - TRQ Test request key + // bit 7 - HLP + + // System.out.println("Attention key sent"); + try { + Log.i(TAG, "sendAttentionKey() writeGDS()"); + writeGDS(0x40, 0, null); + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + } + } + + /** + * Opens a dialog and asks the user before sending a request + * + * @see {@link #systemRequest(String)} + */ + public final void systemRequest() { + String ask = manager.res.getString(R.string.prompt_sys_request); + String sysreq = bridge.promptHelper.requestStringPrompt(null, ask); + systemRequest(sysreq); + } + + /** + * @param sr - system request option + * @see {@link #systemRequest(String)} + */ + public final void systemRequest(char sr) { + systemRequest(Character.toString(sr)); + } + + /** + * System request, taken from the rfc1205, 5250 Telnet interface section 4.3 + * + * @param sr system request option (allowed to be null, but than nothing happens) + */ + public final void systemRequest(String sr) { + byte[] bytes = null; + + if ((sr != null) && (sr.length() > 0)) { + // XXX: Not sure, if this is a sufficient check for 'clear dataq' + if (sr.charAt(0) == '2') { + dsq.clear(); + } + + for (int i = 0, l = sr.length(); i < l; i++) { + baosp.write(codePage.uni2ebcdic(sr.charAt(i))); + } + + bytes = baosp.toByteArray(); + } + + try { + Log.i(TAG, "systemRequest() writeGDS()"); + writeGDS(4, 0, bytes); + } + catch (IOException ioe) { + Log.i(TAG, ioe.getMessage()); + } + + baosp.reset(); + } + + /** + * Cancel Invite - taken from the rfc1205 - 5250 Telnet interface section + * 4.3 + * + * See notes inside method + */ + public final void cancelInvite() { + // screen52.setStatus(Screen5250.STATUS_SYSTEM, + // Screen5250.STATUS_VALUE_ON, null); + screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); + + // from rfc1205 section 4.3 + // Server: Sends header with the 000A12A0 00000400 000AFFEF + // Opcode = Cancel Invite. + + // Client: sends header with the 000A12A0 00000400 000AFFEF + // Opcode = Cancel Invite to + // indicate that the work station is + // no longer invited. + try { + Log.i(TAG, "cancelInvite() writeGDS()"); + writeGDS(0, 10, null); + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + } + } + + public final void hostPrint(int aid) { + if (screen52.isStatusErrorCode()) { + screen52.restoreErrorLine(); + screen52.setStatus(Screen5250.STATUS_ERROR_CODE, + Screen5250.STATUS_VALUE_OFF, null); + } + + screen52.setCursorActive(false); + // screen52.setStatus(Screen5250.STATUS_SYSTEM, + // Screen5250.STATUS_VALUE_ON, null); + screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); + // From client access ip capture + // it seems to use an operation code of 3 and 4 + // also note that the flag field that says reserved is being sent as + // well + // with a value of 0x80 + // + // I have tried with not setting these flags and sending with 3 or 1 + // there is no effect and I still get a host print screen. Go figure + //0000: 000D 12A0 0000 0400 8003 1407 F6FFEF + //0000: 000D 12A0 0000 0400 8001 110E F6FFEF + // + // Client sends header 000D12A0000004000003####F6FFEF + // operation code 3 + // row - first ## + // column - second ## + // F6 - Print Aid Key + baosp.write(screen52.getCurrentRow()); + baosp.write(screen52.getCurrentCol()); + baosp.write(AID_PRINT); // aid key + + try { + Log.i(TAG, "hostPrint() writeGDS()"); + writeGDS(0, 3, baosp.toByteArray()); + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + } + + baosp.reset(); + } + + public final void toggleDebug() { + producer.toggleDebug(codePage); + } + + // write gerneral data stream + private final void writeGDS(int flags, int opcode, byte abyte0[]) + throws IOException { + // Added to fix for JDK 1.4 this was null coming from another method. + // There was a weird keyRelease event coming from another panel when + // using a key instead of the mouse to select button. + // The other method was fixed as well but this check should be here + // anyway. + if (bout == null) + return; + + int length; + + if (abyte0 != null) + length = abyte0.length + 10; + else + length = 10; + + // refer to rfc1205 - 5250 Telnet interface + // Section 3. Data Stream Format + // Logical Record Length - 16 bits + baosrsp.write(length >> 8); // Length LL + baosrsp.write(length & 0xff); // LL + // Record Type - 16 bits + // It should always be set to '12A0'X to indicate the + // General Data Stream (GDS) record type. + baosrsp.write(18); // 0x12 + baosrsp.write(160); // 0xA0 + // the next 16 bits are not used + baosrsp.write(0); // 0x00 + baosrsp.write(0); // 0x00 + // The second part is meant to be variable in length + // currently this portion is 4 octets long (1 byte or 8 bits for us ;-O) + baosrsp.write(4); // 0x04 + baosrsp.write(flags); // flags + // bit 0 - ERR + // bit 1 - ATN Attention + // bits 2-4 - reserved + // bit 5 - SRQ system request + // bit 6 - TRQ Test request key + // bit 7 - HLP + baosrsp.write(0); // reserved - set to 0x00 + baosrsp.write(opcode); // opcode + + if (abyte0 != null) + baosrsp.write(abyte0, 0, abyte0.length); + + baosrsp = appendByteStream(baosrsp.toByteArray()); + // make sure we indicate no more to be sent + baosrsp.write(IAC); + baosrsp.write(EOR); + baosrsp.writeTo(bout); + bout.flush(); + baosrsp.reset(); + } + + protected final int getOpCode() { + return bk.getOpCode(); + } + + protected boolean[] getActiveAidKeys() { + boolean aids[] = new boolean[dataIncluded.length]; + System.arraycopy(dataIncluded, 0, aids, 0, dataIncluded.length); + return aids; + } + + private final void setInvited() { + Log.d(TAG, "invited"); + if (!screen52.isStatusErrorCode()) + screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED, + ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); + invited = true; + screen52.updateDirty(); + buffer.testChanged(); + } + + // WVL - LDC : 05/08/2005 : TFX.006253 - Support STRPCCMD + private void strpccmd() { + try { + int str = 11; + char c; + ScreenPlanes planes = screen52.getPlanes(); + c = planes.getChar(str); + boolean waitFor = !(c == 'a'); + StringBuffer command = new StringBuffer(); + + for (int i = str + 1; i < 132; i++) { + c = planes.getChar(i); + + if (Character.isISOControl(c)) + c = ' '; + + command.append(c); + } + + String cmd = command.toString().trim(); + run(cmd, waitFor); + } + finally { + strpccmd = false; + screen52.sendKeys(TN5250jConstants.MNEMONIC_ENTER); + } + } + + // WVL - LDC : 05/08/2005 : TFX.006253 - Support STRPCCMD + private void run(String cmd, boolean waitFor) { + try { + Log.d(TAG, "RUN cmd = " + cmd); + Log.d(TAG, "RUN wait = " + waitFor); + Runtime r = Runtime.getRuntime(); + Process p = r.exec(cmd); + + if (waitFor) { + int result = p.waitFor(); + Log.d(TAG, "RUN result = " + result); + } + } + catch (Throwable t) { + Log.e(TAG, "exception", t); + } + } + + + // WVL - LDC : TR.000300 : Callback scenario from 5250 + /** + * Activate or deactivate the command scanning behaviour. + * + * @param scan + * if true, scanning is enabled; disabled otherwise. + * + * @see scan4Cmd() + */ + public void setScanningEnabled(boolean scan) { + this.scan = scan; + } + + // WVL - LDC : TR.000300 : Callback scenario from 5250 + /** + * Checks whether command scanning is enabled. + * + * @return true is command scanning is enabled; false otherwise. + */ + public boolean isScanningEnabled() { + return this.scan; + } + + // WVL - LDC : TR.000300 : Callback scenario from 5250 + /** + * When command scanning is activated, the terminal reads the first and + * second character in the datastream (the zero position allows to + * devisualize the scan stream). If the sequence <code>#!</code> is + * encountered and if this sequence is <strong>not </strong> followed by a + * blank character, the {@link parseCommand(ScreenChar[])}is called. + */ + private void scan() { + // System.out.println("Checking command : " + + // screen52.screen[1].getChar() + screen52.screen[2].getChar()); + // ScreenChar[] screen = screen52.screen; + ScreenPlanes planes = screen52.getPlanes(); + + if ((planes.getChar(STRSCAN) == '#') + && (planes.getChar(STRSCAN + 1) == '!') + && (planes.getChar(STRSCAN + 2) != ' ')) { + try { + parseCommand(); + } + catch (Throwable t) { + Log.i(TAG, "Exec cmd: " + t.getMessage()); + t.printStackTrace(); + } + } + } + + // WVL - LDC : TR.000300 : Callback scenario from 5250 + /** + * The screen is parsed starting from second position until a white space is + * encountered. When found the Session#execCommand(String, int) is + * called with the parsed string. The position immediately following the + * encountered white space, separating the command from the rest of the + * screen, is passed as starting index. + * + * Note that the character at the starting position can potentially be a + * white space itself. The starting position in <code>execCommand</code> + * provided to make the scanning sequence more flexible. We'd like for + * example to embed also a <code>+</code> or <code>-</code> sign to + * indicate whether the tnvt should trigger a repaint or not. This would + * allow the flashing of command sequences without them becoming visible. + * + * <ul> + * <li><strong>PRE </strong> The screen character at position + * <code>STRSCAN + 2</code> is not a white space.</li> + * </ul> + */ + private void parseCommand() { + // Search for the command i.e. the first token in the stream + // after the #! sequence separated by a space from the rest + // of the screen. + char[] screen = screen52.getScreenAsChars(); + + for (int s = STRSCAN + 2, i = s; i < screen.length; i++) { + if (screen[i] == ' ') { + String command = new String(screen, s, i - s); + // Skip all white spaces between the command and the rest of + // the screen. + //for (; (i < screen.length) && (screen[i] == ' '); i++); + String remainder = new String(screen, i + 1, screen.length + - (i + 1)); + //controller.fireScanned(command, remainder); + Log.i(TAG, "trying to run " + command + " " + remainder); + break; + } + } + } + + public void run() { + if (enhanced) sfParser = new WTDSFParser(this); + + bk = new Stream5250(); + + while (keepTrucking) { + try { + Object e = dsq.take(); + + if ((e instanceof Integer) && ((Integer)e == 0)) { + screen52.updateDirty(); + buffer.testChanged(); + continue; + }; + + bk.initialize((byte[])e); + } + catch (InterruptedException ie) { + Log.w(TAG, " vt thread interrupted and stopping "); + keepTrucking = false; + continue; + } + + invited = false; + screen52.setCursorActive(false); + if (bk == null) continue; + + switch (bk.getOpCode()) { + case 00: + Log.d(TAG, "No operation"); + break; + + case 1: + Log.d(TAG, "Invite Operation"); + parseIncoming(); + pendingUnlock = true; + cursorOn = true; + setInvited(); + break; + + case 2: + Log.d(TAG, "Output Only"); + parseIncoming(); + screen52.updateDirty(); + break; + + case 3: + Log.d(TAG, "Put/Get Operation"); + parseIncoming(); + setInvited(); + break; + + case 4: + Log.d(TAG, "Save Screen Operation"); + parseIncoming(); + break; + + case 5: + Log.d(TAG, "Restore Screen Operation"); + parseIncoming(); + break; + + case 6: + Log.d(TAG, "Read Immediate"); + sendAidKey(0); + break; + + case 7: + Log.d(TAG, "Reserved"); + break; + + case 8: + Log.d(TAG, "Read Screen Operation"); + + try { + readScreen(); + } + catch (IOException ex) { + Log.w(TAG, ex.getMessage()); + } + + break; + + case 9: + Log.d(TAG, "Reserved"); + break; + + case 10: + Log.d(TAG, "Cancel Invite Operation"); + cancelInvite(); + break; + + case 11: + Log.d(TAG, "Turn on message light"); + screen52.getOIA().setMessageLightOn(); + screen52.setCursorActive(true); + break; + + case 12: + Log.d(TAG, "Turn off Message light"); + screen52.getOIA().setMessageLightOff(); + screen52.setCursorActive(true); + break; + + default: + break; + } + + if (screen52.isUsingGuiInterface()) + screen52.drawFields(); + + try { + if (!strpccmd) { + screen52.updateDirty(); + } + else { + strpccmd(); + } + } + catch (Exception exd) { + Log.w(TAG, " tnvt.run: " + exd.getMessage()); + exd.printStackTrace(); + } + + if (pendingUnlock && !screen52.isStatusErrorCode()) { + screen52.getOIA().setKeyBoardLocked(false); + pendingUnlock = false; + } + + if (cursorOn && !screen52.getOIA().isKeyBoardLocked()) { + screen52.setCursorActive(true); + cursorOn = false; + } + } + } + + public void dumpStuff() { + Log.d(TAG, " Pending unlock " + pendingUnlock); + Log.d(TAG, " Status Error " + screen52.isStatusErrorCode()); + Log.d(TAG, " Keyboard Locked " + screen52.getOIA().isKeyBoardLocked()); + Log.d(TAG, " Cursor On " + cursorOn); + Log.d(TAG, " Cursor Active " + screen52.cursorActive); + } + + + private final void readScreen() throws IOException { + int rows = screen52.getRows(); + int cols = screen52.getColumns(); + byte abyte0[] = new byte[rows * cols]; + fillScreenArray(abyte0, rows, cols); + Log.i(TAG, "readScreen() writeGDS()"); + writeGDS(0, 0, abyte0); + abyte0 = null; + } + + private final void fillScreenArray(byte[] sa, int rows, int cols) { + int la = 32; + int sac = 0; + int len = rows * cols; + ScreenPlanes planes = screen52.planes; + + try { + for (int y = 0; y < len; y++) { // save the screen data + if (planes.isAttributePlace(y)) { + la = planes.getCharAttr(y); + sa[sac++] = (byte) la; + } + else { + // The characters on screen are in unicode + char ch = planes.getChar(y); + byte byteCh; + if (isDataUnicode(ch)) byteCh = codePage.uni2ebcdic(ch); + else byteCh = (byte) ch; + sa[sac++] = byteCh; + } + } + } + catch (Exception exc) { + Log.i(TAG, exc.getMessage()); + exc.printStackTrace(); + } + } + + private final void fillRegenerationBuffer(ByteArrayOutputStream sc, int rows, int cols) + throws IOException { + int la = 32; + int sac = 0; + int len = rows * cols; + ScreenPlanes planes = screen52.planes; + byte[] sa = new byte[len]; + + try { + boolean guiExists = sfParser != null && sfParser.isGuisExists(); + + for (int y = 0; y < len; y++) { // save the screen data + if (guiExists) { + byte[] guiSeg = sfParser.getSegmentAtPos(y); + + if (guiSeg != null) { + //Log.i(TAG," gui saved at " + y + " - " + screen52.getRow(y) + "," + + // screen52.getCol(y)); + byte[] gsa = new byte[sa.length + guiSeg.length + 2]; + System.arraycopy(sa, 0, gsa, 0, sa.length); + System.arraycopy(guiSeg, 0, gsa, sac + 2, guiSeg.length); + sa = new byte[gsa.length]; + System.arraycopy(gsa, 0, sa, 0, gsa.length); + sa[sac++] = (byte)0x04; + sa[sac++] = (byte)0x11; + sac += guiSeg.length; + //y--; + // continue; + } + } + + if (planes.isAttributePlace(y)) { + la = planes.getCharAttr(y); + sa[sac++] = (byte) la; + } + else { + // The characters on screen are in unicode + char ch = planes.getChar(y); + byte byteCh; + if (isDataUnicode(ch)) byteCh = codePage.uni2ebcdic(ch); + else byteCh = (byte) ch; + sa[sac++] = byteCh; + } + } + } + catch (Exception exc) { + Log.i(TAG, exc.getMessage()); + exc.printStackTrace(); + } + + sc.write(sa); + } + + public final void saveScreen() throws IOException { + ByteArrayOutputStream sc = new ByteArrayOutputStream(); + sc.write(4); + sc.write(0x12); // 18 + sc.write(0); // 18 + sc.write(0); // 18 + sc.write((byte) screen52.getRows()); // store the current size + sc.write((byte) screen52.getColumns()); // "" + int cp = screen52.getCurrentPos(); // save off current position + // fix below submitted by Mitch Blevins + //int cp = screen52.getScreenFields().getCurrentFieldPos(); + // save off current position + sc.write((byte)(cp >> 8 & 0xff)); // "" + sc.write((byte)(cp & 0xff)); // "" + sc.write((byte)(screen52.homePos >> 8 & 0xff)); // save home pos + sc.write((byte)(screen52.homePos & 0xff)); // "" + int rows = screen52.getRows(); // store the current size + int cols = screen52.getColumns(); // "" + // byte[] sa = new byte[rows * cols]; + fillRegenerationBuffer(sc, rows, cols); + // fillScreenArray(sa, rows, cols); + // + // sc.write(sa); + // sa = null; + int sizeFields = screen52.getScreenFields().getSize(); + sc.write((byte)(sizeFields >> 8 & 0xff)); // "" + sc.write((byte)(sizeFields & 0xff)); // "" + + if (sizeFields > 0) { + int x = 0; + int s = screen52.getScreenFields().getSize(); + ScreenField sf = null; + + while (x < s) { + sf = screen52.getScreenFields().getField(x); + sc.write((byte) sf.getAttr()); // attribute + int sp = sf.startPos(); + sc.write((byte)(sp >> 8 & 0xff)); // "" + sc.write((byte)(sp & 0xff)); // "" + + if (sf.mdt) + sc.write((byte) 1); + else + sc.write((byte) 0); + + sc.write((byte)(sf.getLength() >> 8 & 0xff)); // "" + sc.write((byte)(sf.getLength() & 0xff)); // "" + sc.write((byte) sf.getFFW1() & 0xff); + sc.write((byte) sf.getFFW2() & 0xff); + sc.write((byte) sf.getFCW1() & 0xff); + sc.write((byte) sf.getFCW2() & 0xff); + Log.d(TAG, "Saved "); + Log.d(TAG, sf.toString()); + x++; + } + + sf = null; + } + + // The following two lines of code looks to have caused all sorts of + // problems so for now we have commented them out. + // screen52.getScreenFields().setCurrentField(null); // set it to null + // for GC ? + // screen52.clearTable(); + + try { + Log.i(TAG, "saveScreen() writeGDS()"); + writeGDS(0, 3, sc.toByteArray()); + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + } + + sc = null; + Log.d(TAG, "Save Screen end "); + } + + /** + * + * @throws IOException + */ + public final void restoreScreen() throws IOException { + int which = 0; + ScreenPlanes planes = screen52.planes; + + try { + Log.d(TAG, "Restore "); + bk.getNextByte(); + bk.getNextByte(); + int rows = bk.getNextByte() & 0xff; + int cols = bk.getNextByte() & 0xff; + int pos = bk.getNextByte() << 8 & 0xff00; // current position + pos |= bk.getNextByte() & 0xff; + int hPos = bk.getNextByte() << 8 & 0xff00; // home position + hPos |= bk.getNextByte() & 0xff; + + if ((rows != screen52.getRows()) || (cols != screen52.getColumns())) + screen52.setRowsCols(rows, cols); + + screen52.clearAll(); // initialize what we currenty have + + if (sfParser != null && sfParser.isGuisExists()) + sfParser.clearGuiStructs(); + + int b = 32; + int la = 32; + int len = rows * cols; + + for (int y = 0; y < len; y++) { + b = bk.getNextByte(); + + if (b == 0x04) { + Log.i(TAG, " gui restored at " + y + " - " + screen52.getRow(y) + "," + + screen52.getCol(y)); + int command = bk.getNextByte(); + byte[] seg = bk.getSegment(); + + if (seg.length > 0) { + screen52.goto_XY(y); + sfParser.parseWriteToDisplayStructuredField(seg); + } + + y--; + // screen52.goto_XY(y); + } + else { + // b = bk.getNextByte(); + if (planes.isUseGui(y)) + continue; + + if (isAttribute(b)) { + planes.setScreenCharAndAttr(y, planes.getChar(y), b, true); + la = b; + } + else { + // The characters on screen are in unicode + char ch; + if (isDataEBCDIC(b)) ch = codePage.ebcdic2uni(b); + else ch = (char) b; + planes.setScreenCharAndAttr(y, ch, la, false); + } + } + } + + int numFields = bk.getNextByte() << 8 & 0xff00; + numFields |= bk.getNextByte() & 0xff; + Log.d(TAG, "number of fields " + numFields); + + if (numFields > 0) { + int x = 0; + int attr = 0; + int fPos = 0; + int fLen = 0; + int ffw1 = 0; + int ffw2 = 0; + int fcw1 = 0; + int fcw2 = 0; + boolean mdt = false; + ScreenField sf = null; + + while (x < numFields) { + attr = bk.getNextByte(); + fPos = bk.getNextByte() << 8 & 0xff00; + fPos |= bk.getNextByte() & 0xff; + + if (bk.getNextByte() == 1) + mdt = true; + else + mdt = false; + + fLen = bk.getNextByte() << 8 & 0xff00; + fLen |= bk.getNextByte() & 0xff; + ffw1 = bk.getNextByte(); + ffw2 = bk.getNextByte(); + fcw1 = bk.getNextByte(); + fcw2 = bk.getNextByte(); + sf = screen52.getScreenFields().setField(attr, + screen52.getRow(fPos), screen52.getCol(fPos), fLen, + ffw1, ffw2, fcw1, fcw2); + + while (fLen-- > 0) { + // now we set the field plane attributes + planes.setScreenFieldAttr(fPos++, ffw1); + } + + if (mdt) { + sf.setMDT(); + screen52.getScreenFields().setMasterMDT(); + } + + Log.d(TAG, "Restored "); + Log.d(TAG, sf.toString()); + x++; + } + } + + // Redraw the gui fields if we are in gui mode + if (screen52.isUsingGuiInterface()) + screen52.drawFields(); + + screen52.restoreScreen(); // display the screen + // The position was saved with currentPos which 1,1 offset of the + // screen position. + // The setPendingInsert is the where the cursor position will be + // displayed after the restore. + screen52.setPendingInsert(true, screen52.getRow(pos + cols), screen52 + .getCol(pos + cols)); + // We need to offset the pos by -1 since the position is 1,1 based + // and the goto_XY is 0,0 based. + screen52.goto_XY(pos - 1); + screen52.isInField(); + // // Redraw the gui fields if we are in gui mode + // if (screen52.isUsingGuiInterface()) + // screen52.drawFields(); + } + catch (Exception e) { + Log.w(TAG, "error restoring screen " + which + " with " + + e.getMessage()); + } + } + + public final boolean waitingForInput() { + return waitingForInput; + } + + private void parseIncoming() { + boolean done = false; + boolean error = false; + + try { + while (bk.hasNext() && !done) { + byte b = bk.getNextByte(); + + switch (b) { + case 0: + case 1: + break; + + case CMD_SAVE_SCREEN: // 0x02 2 Save Screen + case 3: // 0x03 3 Save Partial Screen + Log.d(TAG, "save screen partial"); + saveScreen(); + break; + + case ESC: // ESCAPE + break; + + case 7: // audible bell + manager.playBeep(); + bk.getNextByte(); + bk.getNextByte(); + break; + + case CMD_WRITE_TO_DISPLAY: // 0x11 17 write to display + error = writeToDisplay(true); + + // WVL - LDC : TR.000300 : Callback scenario from 5250 + // Only scan when WRITE_TO_DISPLAY operation (i.e. refill + // screen buffer) + // has been issued! + if (scan) + scan(); + + break; + + case CMD_RESTORE_SCREEN: // 0x12 18 Restore Screen + case 13: // 0x13 19 Restore Partial Screen + Log.d(TAG, "restore screen partial"); + restoreScreen(); + break; + + case CMD_CLEAR_UNIT_ALTERNATE: // 0x20 32 clear unit alternate + int param = bk.getNextByte(); + + if (param != 0) { + Log.d(TAG, " clear unit alternate error " + + Integer.toHexString(param)); + sendNegResponse(NR_REQUEST_ERROR, 03, 01, 05, + " clear unit alternate not supported"); + done = true; + } + else { + if (screen52.getRows() != 27) + screen52.setRowsCols(27, 132); + + screen52.clearAll(); + + if (sfParser != null && sfParser.isGuisExists()) + sfParser.clearGuiStructs(); + } + + break; + + case CMD_WRITE_ERROR_CODE: // 0x21 33 Write Error Code + writeErrorCode(); + error = writeToDisplay(false); + break; + + case CMD_WRITE_ERROR_CODE_TO_WINDOW: // 0x22 34 + // Write Error Code to window + writeErrorCodeToWindow(); + error = writeToDisplay(false); + break; + + case CMD_READ_SCREEN_IMMEDIATE: // 0x62 98 + case CMD_READ_SCREEN_TO_PRINT: // 0x66 102 read screen to print + readScreen(); + break; + + case CMD_CLEAR_UNIT: // 64 0x40 clear unit + if (screen52.getRows() != 24) + screen52.setRowsCols(24, 80); + + screen52.clearAll(); + + if (sfParser != null && sfParser.isGuisExists()) + sfParser.clearGuiStructs(); + + break; + + case CMD_CLEAR_FORMAT_TABLE: // 80 0x50 Clear format table + screen52.clearTable(); + break; + + case CMD_READ_INPUT_FIELDS: //0x42 66 read input fields + case CMD_READ_MDT_FIELDS: // 0x52 82 read MDT Fields + bk.getNextByte(); + bk.getNextByte(); + readType = b; + screen52.goHome(); + // do nothing with the cursor here it is taken care of + // in the main loop. + //////////////// screen52.setCursorOn(); + waitingForInput = true; + pendingUnlock = true; + // screen52.setKeyboardLocked(false); + break; + + case CMD_READ_MDT_IMMEDIATE_ALT: // 0x53 83 + readType = b; + // screen52.goHome(); + // waitingForInput = true; + // screen52.setKeyboardLocked(false); + readImmediate(readType); + break; + + case CMD_WRITE_STRUCTURED_FIELD: // 243 0xF3 -13 Write + // structured field + writeStructuredField(); + break; + + case CMD_ROLL: // 0x23 35 Roll Not sure what it does right now + int updown = bk.getNextByte(); + int topline = bk.getNextByte(); + int bottomline = bk.getNextByte(); + screen52.rollScreen(updown, topline, bottomline); + break; + + default: + done = true; + sendNegResponse(NR_REQUEST_ERROR, 03, 01, 01, + "parseIncoming"); + break; + } + + if (error) + done = true; + } + } + catch (Exception exc) { + Log.w(TAG, "incoming " + exc.getMessage()); + } + } + + /** + * This routine handles sending negative responses back to the host. + * + * You can find a description of the types of responses to be sent back by + * looking at section 12.4 of the 5250 Functions Reference manual + * + * + * @param cat + * @param modifier + * @param uByte1 + * @param uByte2 + * @param from + * + */ + protected void sendNegResponse(int cat, int modifier, int uByte1, + int uByte2, String from) { + try { + int os = bk.getByteOffset(-1) & 0xf0; + int cp = (bk.getCurrentPos() - 1); + Log.i(TAG, "invalid " + from + " command " + os + + " at pos " + cp); + } + catch (Exception e) { + Log.w(TAG, "Send Negative Response error " + e.getMessage()); + } + + baosp.write(cat); + baosp.write(modifier); + baosp.write(uByte1); + baosp.write(uByte2); + + try { + Log.i(TAG, "sendNegResponse() writeGDS()"); + writeGDS(128, 0, baosp.toByteArray()); + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + } + + baosp.reset(); + } + + public void sendNegResponse2(int ec) { + screen52.setPrehelpState(true, true, false); + baosp.write(0x00); + baosp.write(ec); + + try { + Log.i(TAG, "sendNegResponse2() writeGDS()"); + writeGDS(1, 0, baosp.toByteArray()); + } + catch (IOException ioe) { + Log.w(TAG, ioe.getMessage()); + } + + baosp.reset(); + } + + private boolean writeToDisplay(boolean controlsExist) { + boolean error = false; + boolean done = false; + int attr; + byte control0 = 0; + byte control1 = 0; + int saRows = screen52.getRows(); + int saCols = screen52.getColumns(); + + try { + if (controlsExist) { + control0 = bk.getNextByte(); + control1 = bk.getNextByte(); + processCC0(control0); + } + + while (bk.hasNext() && !done) { + // pos = bk.getCurrentPos(); + // int rowc = screen52.getCurrentRow(); + // int colc = screen52.getCurrentCol(); + byte bytebk = bk.getNextByte(); + + switch (bytebk) { + case 1: // SOH - Start of Header Order + Log.d(TAG, "SOH - Start of Header Order"); + error = processSOH(); + break; + + case 02: // RA - Repeat to address + Log.d(TAG, "RA - Repeat to address"); + int row = screen52.getCurrentRow(); + int col = screen52.getCurrentCol(); + int toRow = bk.getNextByte(); + int toCol = bk.getNextByte() & 0xff; + + if (toRow >= row) { + int repeat = bk.getNextByte(); + + // a little intelligence here I hope + if (row == 1 && col == 2 && toRow == screen52.getRows() + && toCol == screen52.getColumns()) + screen52.clearScreen(); + else { + if (repeat != 0) { + //LDC - 13/02/2003 - convert it to unicode + repeat = codePage.ebcdic2uni(repeat); + //repeat = getASCIIChar(repeat); + } + + int times = ((toRow * screen52.getColumns()) + toCol) + - ((row * screen52.getColumns()) + col); + + while (times-- >= 0) { + screen52.setChar(repeat); + } + } + } + else { + sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x23, + " RA invalid"); + error = true; + } + + break; + + case 03: // EA - Erase to address + Log.d(TAG, "EA - Erase to address"); + int EArow = screen52.getCurrentRow(); + int EAcol = screen52.getCurrentCol(); + int toEARow = bk.getNextByte(); + int toEACol = bk.getNextByte() & 0xff; + int EALength = bk.getNextByte() & 0xff; + + while (--EALength > 0) { + bk.getNextByte(); + } + + char EAAttr = (char) 0; + + // a little intelligence here I hope + if (EArow == 1 && EAcol == 2 + && toEARow == screen52.getRows() + && toEACol == screen52.getColumns()) + screen52.clearScreen(); + else { + int times = ((toEARow * screen52.getColumns()) + toEACol) + - ((EArow * screen52.getColumns()) + EAcol); + + while (times-- >= 0) { + screen52.setChar(EAAttr); + } + } + + break; + + case 04: // Command - Escape + Log.d(TAG, "Command - Escape"); + done = true; + break; + + case 16: // TD - Transparent Data + Log.d(TAG, "TD - Transparent Data"); + int j = (bk.getNextByte() & 0xff) << 8 | bk.getNextByte() + & 0xff; // length + break; + + case 17: // SBA - set buffer address order (row column) + //Log.d(TAG,"SBA - set buffer address order (row column)"); + int saRow = bk.getNextByte(); + int saCol = bk.getNextByte() & 0xff; + + // make sure it is in bounds + if (saRow >= 0 && saRow <= screen52.getRows() && saCol >= 0 + && saCol <= screen52.getColumns()) { + screen52.setCursor(saRow, saCol); // now set screen + // position for output + } + else { + sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x22, + "invalid row/col order" + " saRow = " + saRow + + " saRows = " + screen52.getRows() + + " saCol = " + saCol); + error = true; + } + + break; + + case 18: // WEA - Extended Attribute + Log.d(TAG, "WEA - Extended Attribute"); + bk.getNextByte(); + bk.getNextByte(); + break; + + case 19: // IC - Insert Cursor + Log.d(TAG, "IC - Insert Cursor"); + int icX = bk.getNextByte(); + int icY = bk.getNextByte() & 0xff; + + if (icX >= 0 && icX <= saRows && icY >= 0 && icY <= saCols) { + Log.d(TAG, " IC " + icX + " " + icY); + screen52.setPendingInsert(true, icX, icY); + } + else { + sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x22, + " IC/IM position invalid "); + error = true; + } + + break; + + case 20: // MC - Move Cursor + Log.d(TAG, "MC - Move Cursor"); + int imcX = bk.getNextByte(); + int imcY = bk.getNextByte() & 0xff; + + if (imcX >= 0 && imcX <= saRows && imcY >= 0 + && imcY <= saCols) { + Log.d(TAG, " MC " + imcX + " " + imcY); + screen52.setPendingInsert(false, imcX, imcY); + } + else { + sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x22, + " IC/IM position invalid "); + error = true; + } + + break; + + case 21: // WTDSF - Write To Display Structured Field order + Log.d(TAG, "WTDSF - Write To Display Structured Field order"); + byte[] seg = bk.getSegment(); + error = sfParser.parseWriteToDisplayStructuredField(seg); + break; + + case 29: // SF - Start of Field + Log.d(TAG, "SF - Start of Field"); + int fcw1 = 0; + int fcw2 = 0; + int ffw1 = 0; + int ffw0 = bk.getNextByte() & 0xff; // FFW + + if ((ffw0 & 0x40) == 0x40) { + ffw1 = bk.getNextByte() & 0xff; // FFW 1 + fcw1 = bk.getNextByte() & 0xff; // check for field + + // control word + + // check if the first fcw1 is an 0x81 if it is then get + // the next pair for checking + if (fcw1 == 0x81) { + bk.getNextByte(); + fcw1 = bk.getNextByte() & 0xff; // check for field + // control word + } + + if (!isAttribute(fcw1)) { + fcw2 = bk.getNextByte() & 0xff; // FCW 2 + attr = bk.getNextByte() & 0xff; // attribute field + + while (!isAttribute(attr)) { + Log.i(TAG, Integer.toHexString(fcw1) + " " + + Integer.toHexString(fcw2) + + " "); + Log.i(TAG, Integer.toHexString(attr) + + " " + + Integer.toHexString(bk + .getNextByte() & 0xff)); + attr = bk.getNextByte() & 0xff; // attribute field + } + } + else { + attr = fcw1; // attribute of field + fcw1 = 0; + } + } + else { + attr = ffw0; + } + + int fLength = (bk.getNextByte() & 0xff) << 8 + | bk.getNextByte() & 0xff; + screen52.addField(attr, fLength, ffw0, ffw1, fcw1, fcw2); + break; + + // WVL - LDC : 05/08/2005 : TFX.006253 - Support STRPCCMD + case -128: //STRPCCMD + // if (screen52.getCurrentPos() == 82) { + Log.d(TAG, "STRPCCMD got a -128 command at " + screen52.getCurrentPos()); + StringBuffer value = new StringBuffer(); + int b; + char c; + int[] pco = new int[9]; + int[] pcoOk = {0xfc, 0xd7, 0xc3, 0xd6, 0x40, 0x83, 0x80, 0xa1, 0x80}; + + for (int i = 0; i < 9; i++) { + b = bk.getNextByte(); + pco[i] = ((b & 0xff)); + c = codePage.ebcdic2uni(b); + value.append(c); + } + + // Check "PCO-String" + if (Arrays.equals(pco, pcoOk)) { + strpccmd = true; + } + + // we return in the stream to have all chars + // arrive at the screen for later processing + for (int i = 0; i < 9; i++) + bk.setPrevByte(); + + //} + // no break: so every chars arrives + // on the screen for later parsing + //break; + + default: // all others must be output to screen + //Log.d(TAG,"all others must be output to screen"); + byte byte0 = bk.getByteOffset(-1); + + if (isAttribute(byte0)) { + screen52.setAttr(byte0); + } + else { + if (!screen52.isStatusErrorCode()) { + if (!isDataEBCDIC(byte0)) { + // if (byte0 == 255) { + // sendNegResponse(NR_REQUEST_ERROR,0x05,0x01,0x42, + // " Attempt to send FF to screen"); + // } + // else + screen52.setChar(byte0); + } + else + //LDC - 13/02/2003 - Convert it to unicode + //screen52.setChar(getASCIIChar(byte0)); + screen52.setChar(codePage.ebcdic2uni(byte0)); + } + else { + if (byte0 == 0) + screen52.setChar(byte0); + else + //LDC - 13/02/2003 - Convert it to unicode + //screen52.setChar(getASCIIChar(byte0)); + screen52.setChar(codePage.ebcdic2uni(byte0)); + } + } + + break; + } + + if (error) + done = true; + } + } + catch (Exception e) { + Log.w(TAG, "write to display " + e.getMessage()); + e.printStackTrace(); + } + + ; + + processCC1(control1); + + return error; + } + + private boolean processSOH() throws Exception { + int l = bk.getNextByte(); // length + Log.d(TAG, " byte 0 " + l); + + if (l > 0 && l <= 7) { + bk.getNextByte(); // flag byte 2 + bk.getNextByte(); // reserved + bk.getNextByte(); // resequence fields + screen52.clearTable(); + + // well that is the first time I have seen this. This fixes a + // problem with S/36 command line. Finally got it. + if (l <= 3) return false; + + screen52.setErrorLine(bk.getNextByte()); // error row + int byte1 = 0; + + if (l >= 5) { + byte1 = bk.getNextByte(); + dataIncluded[23] = (byte1 & 0x80) == 0x80; + dataIncluded[22] = (byte1 & 0x40) == 0x40; + dataIncluded[21] = (byte1 & 0x20) == 0x20; + dataIncluded[20] = (byte1 & 0x10) == 0x10; + dataIncluded[19] = (byte1 & 0x8) == 0x8; + dataIncluded[18] = (byte1 & 0x4) == 0x4; + dataIncluded[17] = (byte1 & 0x2) == 0x2; + dataIncluded[16] = (byte1 & 0x1) == 0x1; + } + + if (l >= 6) { + byte1 = bk.getNextByte(); + dataIncluded[15] = (byte1 & 0x80) == 0x80; + dataIncluded[14] = (byte1 & 0x40) == 0x40; + dataIncluded[13] = (byte1 & 0x20) == 0x20; + dataIncluded[12] = (byte1 & 0x10) == 0x10; + dataIncluded[11] = (byte1 & 0x8) == 0x8; + dataIncluded[10] = (byte1 & 0x4) == 0x4; + dataIncluded[9] = (byte1 & 0x2) == 0x2; + dataIncluded[8] = (byte1 & 0x1) == 0x1; + } + + if (l >= 7) { + byte1 = bk.getNextByte(); + dataIncluded[7] = (byte1 & 0x80) == 0x80; + dataIncluded[6] = (byte1 & 0x40) == 0x40; + dataIncluded[5] = (byte1 & 0x20) == 0x20; + dataIncluded[4] = (byte1 & 0x10) == 0x10; + dataIncluded[3] = (byte1 & 0x8) == 0x8; + dataIncluded[2] = (byte1 & 0x4) == 0x4; + dataIncluded[1] = (byte1 & 0x2) == 0x2; + dataIncluded[0] = (byte1 & 0x1) == 0x1; + } + + return false; + } + else { + sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x2B, + "invalid SOH length"); + return true; + } + } + + private void processCC0(byte byte0) { + Log.d(TAG, " Control byte0 " + Integer.toBinaryString(byte0 & 0xff)); + boolean lockKeyboard = true; + boolean resetMDT = false; + boolean resetMDTAll = false; + boolean nullMDT = false; + boolean nullAll = false; + + // Bits 3 to 6 are reserved and should be set to '0000' + // 0xE0 = '11100000' - only the first 3 bits are tested + if ((byte0 & 0xE0) == 0x00) { + lockKeyboard = false; + } + + // '00100000' = 0x20 /32 -- just lock keyboard + // '01000000' = 0x40 /64 + // '01100000' = 0x60 /96 + // '10000000' = 0x80 /128 + // '10100000' = 0xA0 /160 + // '11000000' = 0xC0 /192 + // '11100000' = 0xE0 /224 + + switch (byte0 & 0xE0) { + case 0x40: + resetMDT = true; + break; + + case 0x60: + resetMDTAll = true; + break; + + case 0x80: + nullMDT = true; + break; + + case 0xA0: + resetMDT = true; + nullAll = true; + break; + + case 0xC0: + resetMDT = true; + nullMDT = true; + break; + + case 0xE0: + resetMDTAll = true; + nullAll = true; + break; + } + + if (lockKeyboard) { + screen52.getOIA().setKeyBoardLocked(true); + pendingUnlock = false; + } + else + pendingUnlock = false; + + if (resetMDT || resetMDTAll || nullMDT || nullAll) { + ScreenField sf; + int f = screen52.getScreenFields().getSize(); + + for (int x = 0; x < f; x++) { + sf = screen52.getScreenFields().getField(x); + + if (!sf.isBypassField()) { + if ((nullMDT && sf.mdt) || nullAll) { + sf.setFieldChar((char) 0x0); + screen52.drawField(sf); + } + } + + if (resetMDTAll || (resetMDT && !sf.isBypassField())) + sf.resetMDT(); + } + + sf = null; + } + } + + private void processCC1(byte byte1) { + Log.d(TAG, " Control byte1 " + Integer.toBinaryString(byte1 & 0xff)); + + if ((byte1 & 0x04) == 0x04) { + manager.playBeep(); + } + + if ((byte1 & 0x02) == 0x02) { + screen52.getOIA().setMessageLightOff(); + } + + if ((byte1 & 0x01) == 0x01) { + screen52.getOIA().setMessageLightOn(); + } + + if ((byte1 & 0x01) == 0x01 && (byte1 & 0x02) == 0x02) { + screen52.getOIA().setMessageLightOn(); + } + + // reset blinking cursor seems to control whether to set or not set the + // the cursor position. No documentation for this just testing and + // looking at the bit settings of this field. This was a pain in the + // ass! + // + // if it is off '0' then keep existing cursor positioning information + // if it is on '1' then reset the cursor positioning information + // *** Note *** unless we receive bit 4 on at the same time + // this seems to work so far + if ((byte1 & 0x20) == 0x20 && (byte1 & 0x08) == 0x00) { + screen52.setPendingInsert(false); + Log.d(TAG, " WTD position no move"); + } + else { + screen52.setPendingInsert(true); + Log.d(TAG, " WTD position move to home" + screen52.homePos + " row " + + screen52.getRow(screen52.homePos) + " col " + + screen52.getCol(screen52.homePos)); + } + + // in enhanced mode we sometimes only receive bit 6 turned on which + // is reset blinking cursor + if ((byte1 & 0x20) == 0x20 && enhanced) { + cursorOn = true; + } + + if (!screen52.isStatusErrorCode() && (byte1 & 0x08) == 0x08) { + // screen52.setStatus(screen52.STATUS_SYSTEM,screen52.STATUS_VALUE_OFF,null); + cursorOn = true; + } + + if ((byte1 & 0x20) == 0x20 && (byte1 & 0x08) == 0x00) { + screen52.setPendingInsert(false, 1, 1); + } + } + + private boolean isAttribute(int byte0) { + int byte1 = byte0 & 0xff; + return (byte1 & 0xe0) == 0x20; + } + + //LDC - 12/02/2003 - Function name changed from isData to isDataEBCDIC + private boolean isDataEBCDIC(int byte0) { + int byte1 = byte0 & 0xff; + + // here it should always be less than 255 + if (byte1 >= 64 && byte1 < 255) + return true; + else + return false; + } + + //LDC - 12/02/2003 - Test if the unicode character is a displayable + // character. + // The first 32 characters are non displayable characters + // This is normally the inverse of isDataEBCDIC (That's why there is a + // check on 255 -> 0xFFFF + private boolean isDataUnicode(int byte0) { + return (((byte0 < 0) || (byte0 >= 32)) && (byte0 != 0xFFFF)); + } + + private void writeStructuredField() { + boolean done = false; + + try { + int length = ((bk.getNextByte() & 0xff) << 8 | (bk.getNextByte() & 0xff)); + + while (bk.hasNext() && !done) { + switch (bk.getNextByte()) { + case -39: // SOH - Start of Header Order + switch (bk.getNextByte()) { + case 112: // 5250 Query + bk.getNextByte(); // get null required field + sendQueryResponse(); + break; + + default: + Log.d(TAG, "invalid structured field sub command " + + bk.getByteOffset(-1)); + break; + } + + break; + + default: + Log.d(TAG, "invalid structured field command " + + bk.getByteOffset(-1)); + break; + } + } + } + catch (Exception e) { + } + + ; + } + + private final void writeErrorCode() throws Exception { + screen52.setCursor(screen52.getErrorLine(), 1); // Skip the control byte + screen52.setStatus(Screen5250.STATUS_ERROR_CODE, + Screen5250.STATUS_VALUE_ON, null); + screen52.saveErrorLine(); + cursorOn = true; + } + + private final void writeErrorCodeToWindow() throws Exception { + int fromCol = bk.getNextByte() & 0xff; // from column + int toCol = bk.getNextByte() & 0xff; // to column + screen52.setCursor(screen52.getErrorLine(), fromCol); // Skip the control byte + screen52.setStatus(Screen5250.STATUS_ERROR_CODE, + Screen5250.STATUS_VALUE_ON, null); + screen52.saveErrorLine(); + cursorOn = true; + } + + /** + * Method sendQueryResponse + * + * The query command is used to obtain information about the capabilities of + * the 5250 display. + * + * The Query command must follow an Escape (0x04) and Write Structured Field + * command (0xF3). + * + * This section is modeled after the rfc1205 - 5250 Telnet Interface section + * 5.3 + * + * @throws IOException + */ + private final void sendQueryResponse() throws IOException { + Log.i(TAG, "sending query response"); + byte abyte0[] = new byte[64]; + abyte0[0] = 0; // Cursor Row/column (set to zero) + abyte0[1] = 0; // "" + abyte0[2] = -120; // X'88' inbound write structure Field aid + + if (enhanced) { + abyte0[3] = 0; // 0x003D (61) length of query response + abyte0[4] = 64; // "" see note below ????????? + } + else { + abyte0[3] = 0; // 0x003A (58) length of query response + abyte0[4] = 58; // "" + // the length between 58 and 64 seems to cause + // different formatting codes to be sent from + // the host ???????????????? why ??????? + // Well the why can be found in the manual if + // read a little more ;-) + } + + abyte0[5] = -39; // command class 0xD9 + abyte0[6] = 112; // Command type query 0x70 + abyte0[7] = -128; // 0x80 Flag byte + abyte0[8] = 6; // Controller Hardware Class + abyte0[9] = 0; // 0x0600 - Other WSF or another 5250 Emulator + abyte0[10] = 1; // Controller Code Level + abyte0[11] = 1; // Version 1 Rel 1.0 + abyte0[12] = 0; // "" + abyte0[13] = 0; // 13 - 28 are reserved so set to 0x00 + abyte0[14] = 0; // "" + abyte0[15] = 0; // "" + abyte0[16] = 0; // "" + abyte0[17] = 0; // "" + abyte0[18] = 0; // "" + abyte0[19] = 0; // "" + abyte0[20] = 0; // "" + abyte0[21] = 0; // "" + abyte0[22] = 0; // "" + abyte0[23] = 0; // "" + abyte0[24] = 0; // "" + abyte0[25] = 0; // "" + abyte0[26] = 0; // "" + abyte0[27] = 0; // "" + abyte0[28] = 0; // "" + abyte0[29] = 1; // Device type - 0x01 5250 Emulator + abyte0[30] = codePage.uni2ebcdic('5'); // Device type character + abyte0[31] = codePage.uni2ebcdic('2'); // "" + abyte0[32] = codePage.uni2ebcdic('5'); // "" + abyte0[33] = codePage.uni2ebcdic('1'); // "" + abyte0[34] = codePage.uni2ebcdic('0'); // "" + abyte0[35] = codePage.uni2ebcdic('1'); // "" + abyte0[36] = codePage.uni2ebcdic('1'); // "" + abyte0[37] = 2; // Keyboard Id - 0x02 Standard Keyboard + abyte0[38] = 0; // extended keyboard id + abyte0[39] = 0; // reserved + abyte0[40] = 0; // 40 - 43 Display Serial Number + abyte0[41] = 36; // + abyte0[42] = 36; // + abyte0[43] = 0; // + abyte0[44] = 1; // Maximum number of display fields - 256 + abyte0[45] = 0; // 0x0100 + abyte0[46] = 0; // 46 -48 Reserved set to 0x00 + abyte0[47] = 0; + abyte0[48] = 0; + abyte0[49] = 1; // 49 - 53 Controller Display Capability + abyte0[50] = 17; // see rfc - tired of typing :-) + abyte0[51] = 0; // "" + abyte0[52] = 0; // "" + + // 53 + // Bit 0-2: B'000' - no graphics capability + // B'001' - 5292-2 style graphics + // Bit 3-7: B '00000' = reserved (it seems for Client access) + + if (enhanced) { + // abyte0[53] = 0x5E; // 0x5E turns on enhanced mode + // abyte0[53] = 0x27; // 0x5E turns on enhanced mode + abyte0[53] = 0x7; // 0x5E turns on ehnhanced mode + Log.i(TAG, "enhanced options"); + } + else + abyte0[53] = 0x0; // 0x0 is normal emulation + + abyte0[54] = 24; // 54 - 60 Reserved set to 0x00 + // 54 - I found out is used for enhanced user + // interface level 3. Bit 4 allows headers + // and footers for windows + abyte0[54] = 8; // 54 - 60 Reserved set to 0x00 + // 54 - I found out is used for enhanced user + // interface level 3. Bit 4 allows headers + // and footers for windows + abyte0[55] = 0; + abyte0[56] = 0; + abyte0[57] = 0; + abyte0[58] = 0; + abyte0[59] = 0; + abyte0[60] = 0; + abyte0[61] = 0; // gridlines are not supported + abyte0[62] = 0; // gridlines are not supported + abyte0[63] = 0; + Log.i(TAG, "sendQueryResponse() writeGDS()"); + writeGDS(0, 0, abyte0); // now tell them about us + abyte0 = null; + } + + protected final boolean negotiate(byte abyte0[]) throws IOException { + int i = 0; + + // from server negotiations + if (abyte0[i] == IAC) { // -1 + while (i < abyte0.length && abyte0[i++] == -1) + + // while(i < abyte0.length && (abyte0[i] == -1 || abyte0[i++] == 0x20)) + switch (abyte0[i++]) { + // we will not worry about what it WONT do + case WONT: // -4 + default: + break; + + case DO: //-3 + + // not sure why but since moving to V5R2 we are receiving a + // DO with no option when connecting a second session with + // device name. Can not find the cause at all. If anybody + // is interested please debug this until then this works. + if (i < abyte0.length) { + switch (abyte0[i]) { + case TERMINAL_TYPE: // 24 + baosp.write(IAC); + baosp.write(WILL); + baosp.write(TERMINAL_TYPE); + writeByte(baosp.toByteArray()); + baosp.reset(); + break; + + case OPT_END_OF_RECORD: // 25 + baosp.write(IAC); + baosp.write(WILL); + baosp.write(OPT_END_OF_RECORD); + writeByte(baosp.toByteArray()); + baosp.reset(); + break; + + case TRANSMIT_BINARY: // 0 + baosp.write(IAC); + baosp.write(WILL); + baosp.write(TRANSMIT_BINARY); + writeByte(baosp.toByteArray()); + baosp.reset(); + break; + + case TIMING_MARK: // 6 rfc860 + // System.out.println("Timing Mark Received and notifying " + + // "the server that we will not do it"); + baosp.write(IAC); + baosp.write(WONT); + baosp.write(TIMING_MARK); + writeByte(baosp.toByteArray()); + baosp.reset(); + break; + + case NEW_ENVIRONMENT: // 39 rfc1572, rfc4777 + // allways send new environment vars ... + baosp.write(IAC); + baosp.write(WILL); + baosp.write(NEW_ENVIRONMENT); + writeByte(baosp.toByteArray()); + baosp.reset(); + break; + + default: // every thing else we will not do at this time + baosp.write(IAC); + baosp.write(WONT); + baosp.write(abyte0[i]); // either + writeByte(baosp.toByteArray()); + baosp.reset(); + break; + } + } + + i++; + break; + + case WILL: + switch (abyte0[i]) { + case OPT_END_OF_RECORD: // 25 + baosp.write(IAC); + baosp.write(DO); + baosp.write(OPT_END_OF_RECORD); + writeByte(baosp.toByteArray()); + baosp.reset(); + break; + + case TRANSMIT_BINARY: // '\0' + baosp.write(IAC); + baosp.write(DO); + baosp.write(TRANSMIT_BINARY); + writeByte(baosp.toByteArray()); + baosp.reset(); + break; + } + + i++; + break; + + case SB: // -6 + if (abyte0[i] == NEW_ENVIRONMENT && abyte0[i + 1] == 1) { + negNewEnvironment(); + + while (++i < abyte0.length && abyte0[i + 1] != IAC); + } + + if (abyte0[i] == TERMINAL_TYPE && abyte0[i + 1] == 1) { + baosp.write(IAC); + baosp.write(SB); + baosp.write(TERMINAL_TYPE); + baosp.write(QUAL_IS); + + if (!support132) + baosp.write("IBM-3179-2".getBytes()); + else + baosp.write("IBM-3477-FC".getBytes()); + + baosp.write(IAC); + baosp.write(SE); + writeByte(baosp.toByteArray()); + baosp.reset(); + i++; + } + + i++; + break; + } + + return true; + } + else { + return false; + } + } + + /** + * Negotiate new environment string for device name + * + * @throws IOException + */ + private void negNewEnvironment() throws IOException { + baosp.write(IAC); + baosp.write(SB); + baosp.write(NEW_ENVIRONMENT); + baosp.write(IS); + + // http://tools.ietf.org/html/rfc4777 + + if (kbdTypesCodePage != null) { + baosp.write(USERVAR); + baosp.write("KBDTYPE".getBytes()); + baosp.write(VALUE); + baosp.write(kbdTypesCodePage.kbdType.getBytes()); + baosp.write(USERVAR); + baosp.write("CODEPAGE".getBytes()); + baosp.write(VALUE); + baosp.write(kbdTypesCodePage.codepage.getBytes()); + baosp.write(USERVAR); + baosp.write("CHARSET".getBytes()); + baosp.write(VALUE); + baosp.write(kbdTypesCodePage.charset.getBytes()); + } + + if (devName != null) { + baosp.write(USERVAR); + baosp.write("DEVNAME".getBytes()); + baosp.write(VALUE); + baosp.write(negDeviceName().getBytes()); + } + + if (user != null) { + baosp.write(VAR); + baosp.write("USER".getBytes()); + baosp.write(VALUE); + baosp.write(user.getBytes()); + + if (password != null) { + baosp.write(USERVAR); + baosp.write("IBMRSEED".getBytes()); + baosp.write(VALUE); + baosp.write(NEGOTIATE_ESC); + baosp.write(0x0); + baosp.write(0x0); + baosp.write(0x0); + baosp.write(0x0); + baosp.write(0x0); + baosp.write(0x0); + baosp.write(0x0); + baosp.write(0x0); + baosp.write(USERVAR); + baosp.write("IBMSUBSPW".getBytes()); + baosp.write(VALUE); + baosp.write(password.getBytes()); + } + + if (library != null) { + baosp.write(USERVAR); + baosp.write("IBMCURLIB".getBytes()); + baosp.write(VALUE); + baosp.write(library.getBytes()); + } + + if (initialMenu != null) { + baosp.write(USERVAR); + baosp.write("IBMIMENU".getBytes()); + baosp.write(VALUE); + baosp.write(initialMenu.getBytes()); + } + + if (program != null) { + baosp.write(USERVAR); + baosp.write("IBMPROGRAM".getBytes()); + baosp.write(VALUE); + baosp.write(program.getBytes()); + } + } + + baosp.write(IAC); + baosp.write(SE); + writeByte(baosp.toByteArray()); + baosp.reset(); + } + + /** + * This will negotiate a device name with controller. if the sequence is + * less than zero then it will send the device name as specified. On each + * unsuccessful attempt a sequential number is appended until we find one or + * the controller says no way. + * + * @return String + */ + private String negDeviceName() { + if (devSeq++ == -1) { + devNameUsed = devName; + return devName; + } + else { + StringBuffer sb = new StringBuffer(devName + devSeq); + int ei = 1; + + while (sb.length() > 10) { + sb.setLength(0); + sb.append(devName.substring(0, devName.length() - ei++)); + sb.append(devSeq); + } + + devNameUsed = sb.toString(); + return devNameUsed; + } + } + + public final void setCodePage(String cp) { + codePage = CharMappings.getCodePage(cp); + cp = cp.toLowerCase(); + + for (KbdTypesCodePages kbdtyp : KbdTypesCodePages.values()) { + if (("cp" + kbdtyp.codepage).equals(cp) || kbdtyp.ccsid.equals(cp)) { + kbdTypesCodePage = kbdtyp; + break; + } + } + + Log.i(TAG, "Chose keyboard mapping " + kbdTypesCodePage.toString() + " for code page " + cp); + } + + public final ICodePage getCodePage() { + return codePage; + } + + public void signalBell() { + manager.playBeep(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/transport/SSL/SSLImplementation.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,213 @@ +package org.tn5250j.framework.transport.SSL; + +/* + * @(#)SSLImplementation.java + * @author Stephen M. Kennedy + * + * Copyright: Copyright (c) 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.net.Socket; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; + +import org.tn5250j.framework.transport.SSLInterface; +import android.util.Log; + + +/** + * <p> + * This class implements the SSLInterface and is used to create SSL socket + * instances. + * </p> + * + * @author Stephen M. Kennedy <skennedy@tenthpowertech.com> + * + */ +public class SSLImplementation implements SSLInterface, X509TrustManager { + private static final String TAG = "SSLImplementation"; + SSLContext sslContext = null; + KeyStore userks = null; + private String userKsPath; + private char[] userksPassword = "changeit".toCharArray(); + + TerminalBridge bridge = null; + TerminalManager manager = null; + String target = null; // destination:port + + KeyManagerFactory userkmf = null; + + TrustManagerFactory usertmf = null; + + TrustManager[] userTrustManagers = null; + + X509Certificate[] acceptedIssuers; + + public SSLImplementation(TerminalBridge bridge, TerminalManager manager) { + this.bridge = bridge; + this.manager = manager; + } + + public void init(String sslType, String homeDirectory) { + try { + Log.d(TAG, "Initializing User KeyStore"); + userKsPath = homeDirectory + File.separator + "keystore"; + File userKsFile = new File(userKsPath); + userks = KeyStore.getInstance(KeyStore.getDefaultType()); + userks.load(userKsFile.exists() ? new FileInputStream(userKsFile) + : null, userksPassword); + Log.d(TAG, "Initializing User Key Manager Factory"); + userkmf = KeyManagerFactory.getInstance(KeyManagerFactory + .getDefaultAlgorithm()); + userkmf.init(userks, userksPassword); + Log.d(TAG, "Initializing User Trust Manager Factory"); + usertmf = TrustManagerFactory.getInstance(TrustManagerFactory + .getDefaultAlgorithm()); + usertmf.init(userks); + userTrustManagers = usertmf.getTrustManagers(); + Log.d(TAG, "Initializing SSL Context"); + sslContext = SSLContext.getInstance(sslType); + sslContext.init(userkmf.getKeyManagers(), new TrustManager[] {this}, null); + } + catch (Exception ex) { + Log.e(TAG, "Error initializing SSL [" + ex.getMessage() + "]"); + } + } + + public Socket createSSLSocket(String destination, int port) { + if (sslContext == null) + throw new IllegalStateException("SSL Context Not Initialized"); + + SSLSocket socket = null; + + try { + target = destination + ":" + String.valueOf(port); + socket = (SSLSocket) sslContext.getSocketFactory().createSocket( + destination, port); + } + catch (Exception e) { + Log.e(TAG, "Error creating ssl socket [" + e.getMessage() + "]"); + } + + return socket; + } + + // X509TrustManager Methods + + /* + * (non-Javadoc) + * + * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() + */ + public X509Certificate[] getAcceptedIssuers() { + return acceptedIssuers; + } + + /* + * (non-Javadoc) + * + * @see + * javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert. + * X509Certificate[], java.lang.String) + */ + public void checkClientTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + throw new SecurityException("checkClientTrusted unsupported"); + } + + /* + * (non-Javadoc) + * + * @see + * javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert. + * X509Certificate[], java.lang.String) + */ + public void checkServerTrusted(X509Certificate[] chain, String type) + throws CertificateException { + try { + for (int i = 0; i < userTrustManagers.length; i++) { + if (userTrustManagers[i] instanceof X509TrustManager) { + X509TrustManager trustManager = (X509TrustManager) userTrustManagers[i]; + X509Certificate[] calist = trustManager + .getAcceptedIssuers(); + + if (calist.length > 0) { + trustManager.checkServerTrusted(chain, type); + } + else { + throw new CertificateException( + "Empty list of accepted issuers (a.k.a. root CA list)."); + } + } + } + + return; + } + catch (CertificateException ce) { + X509Certificate cert = chain[0]; + String certInfo = manager.res.getString(R.string.host_cert_version) + cert.getVersion() + "\r\n"; + certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_serial) + cert.getSerialNumber() + "\r\n"); + certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_algorithm) + cert.getSigAlgName() + "\r\n"); + certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_issuer) + cert.getIssuerDN().getName() + "\r\n"); + certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_from) + cert.getNotBefore() + "\r\n"); + certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_to) + cert.getNotAfter() + "\r\n"); + certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_dn) + cert.getSubjectDN().getName() + "\r\n"); + certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_publickey) + cert.getPublicKey().getFormat() + "\r\n"); + bridge.outputLine(manager.res.getString(R.string.host_authenticity_warning, target)); + bridge.outputLine(manager.res.getString(R.string.host_certificate, certInfo)); + Boolean result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_accept_certificate)); + + if ((result == null) || (!result.booleanValue())) { + throw new java.security.cert.CertificateException( + "Certificate Rejected"); + } + + result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_save_certificate)); + + if ((result != null) && (result.booleanValue())) { + try { + userks.setCertificateEntry(cert.getSubjectDN().getName(), + cert); + userks.store(new FileOutputStream(userKsPath), + userksPassword); + } + catch (Exception e) { + Log.e(TAG, "Error saving certificate [" + e.getMessage() + + "]"); + e.printStackTrace(); + } + } + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/transport/SSL/X509CertificateTrustManager.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,112 @@ +package org.tn5250j.framework.transport.SSL; + +/* + * @(#)X509CertificateTrustManager.java + * + * Copyright: Copyright (c) 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.cert.X509Certificate; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Arrays; + +import com.five_ten_sg.connectbot.R; +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; + + +/** + * This class is used to trust certificates exchanged during an SSL socket + * handshake. It allows the user to accept the certificate so that connections + * can be made without requiring the server to have a certificate signed by a + * CA (Verisign, Thawte, etc.). + * + * @author Stephen M. Kennedy <skennedy@tenthpowertech.com> + * @deprecated. no longer used. + * + */ +public class X509CertificateTrustManager implements X509TrustManager { + + KeyStore ks = null; + TrustManager[] trustManagers; + TerminalBridge bridge = null; + TerminalManager manager = null; + + public X509CertificateTrustManager(TrustManager[] managers, KeyStore keyStore, TerminalBridge bridge, TerminalManager manager) { + this.bridge = bridge; + this.manager = manager; + trustManagers = managers; + ks = keyStore; + } + + public void checkClientTrusted(X509Certificate[] chain, String type) throws CertificateException { + throw new SecurityException("checkClientTrusted unsupported"); + } + + + /** + * Checks the server certificate. If it isn't trusted by the trust manager + * passed to the constructor, then the user will be prompted to accept the + * certificate. + */ + public void checkServerTrusted(X509Certificate[] chain, String type) + throws CertificateException { + try { + for (int i = 0; i < trustManagers.length; i++) { + if (trustManagers[i] instanceof X509TrustManager) + ((X509TrustManager)trustManagers[i]).checkServerTrusted(chain, type); + } + + return; + } + catch (CertificateException ce) { + X509Certificate cert = chain[0]; + String certInfo = "Version: " + cert.getVersion() + "\n"; + certInfo = certInfo.concat("Serial Number: " + cert.getSerialNumber() + "\n"); + certInfo = certInfo.concat("Signature Algorithm: " + cert.getSigAlgName() + "\n"); + certInfo = certInfo.concat("Issuer: " + cert.getIssuerDN().getName() + "\n"); + certInfo = certInfo.concat("Valid From: " + cert.getNotBefore() + "\n"); + certInfo = certInfo.concat("Valid To: " + cert.getNotAfter() + "\n"); + certInfo = certInfo.concat("Subject DN: " + cert.getSubjectDN().getName() + "\n"); + certInfo = certInfo.concat("Public Key: " + cert.getPublicKey().getFormat() + "\n"); + bridge.outputLine(manager.res.getString(R.string.host_certificate, certInfo)); + Boolean result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_accept_certificate)); + + if ((result == null) || (!result.booleanValue())) { + throw new java.security.cert.CertificateException("Certificate Not Accepted"); + } + } + } + + public X509Certificate[] getAcceptedIssuers() { + ArrayList<X509Certificate> list = new ArrayList<X509Certificate>(10); + + for (int i = 0; i < trustManagers.length; i++) { + if (trustManagers[i] instanceof X509TrustManager) + list.addAll(Arrays.asList(((X509TrustManager)trustManagers[i]).getAcceptedIssuers())); + } + + X509Certificate[] acceptedIssuers = new X509Certificate[list.size()]; + acceptedIssuers = list.toArray(acceptedIssuers); + return acceptedIssuers; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/transport/SSLInterface.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,46 @@ +package org.tn5250j.framework.transport; + +/* + * @(#)SSLInterface.java + * + * Copyright: Copyright (c) 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +import java.net.Socket; + +public interface SSLInterface { + + /** + * Initialize the components required to create a new client socket + * when createSSLSocket is called. + * @param sslType The ssl socket type (NONE, SSLv2, SSLv3, TLS) + * @param homeDirectory location of the .tn5250j subdirectory containing + * the keystore + * @see org.tn5250j.framework.transport.SSLConstants + */ + public abstract void init(String sslType, String homeDirectory); + + /** + * Create a new socket + * @param destination + * @param port + * @return new socket, or null if none could be created. + */ + public abstract Socket createSSLSocket(String destination, int port); + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/org/tn5250j/framework/transport/SocketConnector.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,98 @@ + +/** + * @(#)SocketConnector.java + * @author Stephen M. Kennedy + * + * Copyright: Copyright (c) 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ +package org.tn5250j.framework.transport; + +import java.net.Socket; + +import com.five_ten_sg.connectbot.service.TerminalBridge; +import com.five_ten_sg.connectbot.service.TerminalManager; + +import org.tn5250j.framework.transport.SSL.SSLImplementation; +import org.tn5250j.TN5250jConstants; +import android.util.Log; + + +public class SocketConnector { + private static final String TAG = "SocketConnector"; + + /** + * Creates a new instance that creates a plain socket by default. + */ + public SocketConnector() { + } + + /** + * Create a new client Socket to the given destination, port and sslType of + * encryption. + * @param destination + * @param port + * @return a new client socket, or null if + */ + public Socket createSocket(String destination, int port, String sslType, String homeDirectory, TerminalBridge bridge, TerminalManager manager) { + Socket socket = null; + Exception ex = null; + + if (sslType == null || sslType.trim().length() == 0 || + sslType.toUpperCase().equals(TN5250jConstants.SSL_TYPE_NONE)) { + Log.i(TAG, "Creating Plain Socket"); + + try { + // Use Socket Constructor!!! SocketFactory for jdk 1.4 + socket = new Socket(destination, port); + } + catch (Exception e) { + ex = e; + } + } + else { //SSL SOCKET + Log.i(TAG, "Creating SSL [" + sslType + "] Socket"); + SSLInterface sslIf = null; + + try { + sslIf = (SSLInterface) new SSLImplementation(bridge, manager); + } + catch (Exception e) { + ex = new Exception("Failed to create SSLInterface Instance. " + + "Message is [" + e.getMessage() + "]"); + } + + if (sslIf != null) { + sslIf.init(sslType, homeDirectory); + socket = sslIf.createSSLSocket(destination, port); + } + } + + if (ex != null) { + Log.e(TAG, "exception", ex); + } + + if (socket == null) { + Log.w(TAG, "No socket was created"); + } + + return socket; + } + + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/jni/Android.mk Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1 @@ +include $(call all-subdir-makefiles)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/jni/Application.mk Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,2 @@ +# Build both ARMv5TE and x86-32 machine code. +APP_ABI := armeabi x86
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/jni/Exec/Android.mk Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,10 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := com_google_ase_Exec +LOCAL_CFLAGS := -Werror +LOCAL_SRC_FILES := com_google_ase_Exec.cpp +LOCAL_LDLIBS := -llog + +include $(BUILD_SHARED_LIBRARY)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/jni/Exec/com_google_ase_Exec.cpp Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "com_google_ase_Exec.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <termios.h> +#include <unistd.h> + +#include "android/log.h" + +#define LOG_TAG "Exec" +#define LOG(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) + +void JNU_ThrowByName(JNIEnv * env, const char *name, const char *msg) { + jclass clazz = env->FindClass(name); + if (clazz != NULL) { + env->ThrowNew(clazz, msg); + } + env->DeleteLocalRef(clazz); +} + +char *JNU_GetStringNativeChars(JNIEnv * env, jstring jstr) { + if (jstr == NULL) { + return NULL; + } + jbyteArray bytes = 0; + jthrowable exc; + char *result = 0; + if (env->EnsureLocalCapacity(2) < 0) { + return 0; /* out of memory error */ + } + jclass Class_java_lang_String = env->FindClass("java/lang/String"); + jmethodID MID_String_getBytes = env->GetMethodID(Class_java_lang_String, "getBytes", "()[B"); + bytes = (jbyteArray) env->CallObjectMethod(jstr, MID_String_getBytes); + exc = env->ExceptionOccurred(); + if (!exc) { + jint len = env->GetArrayLength(bytes); + result = (char *) malloc(len + 1); + if (result == 0) { + JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0); + env->DeleteLocalRef(bytes); + return 0; + } + env->GetByteArrayRegion(bytes, 0, len, (jbyte *) result); + result[len] = 0; /* NULL-terminate */ + } else { + env->DeleteLocalRef(exc); + } + env->DeleteLocalRef(bytes); + return result; +} + +int jniGetFDFromFileDescriptor(JNIEnv * env, jobject fileDescriptor) { + jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor"); + jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor, + "descriptor", "I"); + return env->GetIntField(fileDescriptor, descriptor); +} + +static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, int *pProcessId) { + char *devname; + int ptm; + pid_t pid; + + ptm = open("/dev/ptmx", O_RDWR); // | O_NOCTTY); + if (ptm < 0) { + LOG("[ cannot open /dev/ptmx - %s ]\n", strerror(errno)); + return -1; + } + fcntl(ptm, F_SETFD, FD_CLOEXEC); + + if (grantpt(ptm) || unlockpt(ptm) || ((devname = (char *) ptsname(ptm)) == 0)) { + LOG("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); + return -1; + } + + pid = fork(); + if (pid < 0) { + LOG("- fork failed: %s -\n", strerror(errno)); + return -1; + } + + if (pid == 0) { + int pts; + + setsid(); + + pts = open(devname, O_RDWR); + if (pts < 0) + exit(-1); + + dup2(pts, 0); + dup2(pts, 1); + dup2(pts, 2); + + close(ptm); + + execl(cmd, cmd, arg0, arg1, NULL); + exit(-1); + } else { + *pProcessId = (int) pid; + return ptm; + } +} + +JNIEXPORT jobject JNICALL Java_com_google_ase_Exec_createSubprocess(JNIEnv * env, jclass clazz, + jstring cmd, jstring arg0, + jstring arg1, + jintArray processIdArray) { + char *cmd_8 = JNU_GetStringNativeChars(env, cmd); + char *arg0_8 = JNU_GetStringNativeChars(env, arg0); + char *arg1_8 = JNU_GetStringNativeChars(env, arg1); + + int procId; + int ptm = create_subprocess(cmd_8, arg0_8, arg1_8, &procId); + + if (processIdArray) { + int procIdLen = env->GetArrayLength(processIdArray); + if (procIdLen > 0) { + jboolean isCopy; + int *pProcId = (int *) env->GetPrimitiveArrayCritical(processIdArray, &isCopy); + if (pProcId) { + *pProcId = procId; + env->ReleasePrimitiveArrayCritical(processIdArray, pProcId, 0); + } + } + } + + jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor"); + jmethodID init = env->GetMethodID(Class_java_io_FileDescriptor, + "<init>", "()V"); + jobject result = env->NewObject(Class_java_io_FileDescriptor, init); + + if (!result) { + LOG("Couldn't create a FileDescriptor."); + } else { + jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor, + "descriptor", "I"); + env->SetIntField(result, descriptor, ptm); + } + + return result; +} + +JNIEXPORT void Java_com_google_ase_Exec_setPtyWindowSize(JNIEnv * env, jclass clazz, + jobject fileDescriptor, jint row, jint col, + jint xpixel, jint ypixel) { + int fd; + struct winsize sz; + + fd = jniGetFDFromFileDescriptor(env, fileDescriptor); + + if (env->ExceptionOccurred() != NULL) { + return; + } + + sz.ws_row = row; + sz.ws_col = col; + sz.ws_xpixel = xpixel; + sz.ws_ypixel = ypixel; + + ioctl(fd, TIOCSWINSZ, &sz); +} + +JNIEXPORT jint Java_com_google_ase_Exec_waitFor(JNIEnv * env, jclass clazz, jint procId) { + int status; + waitpid(procId, &status, 0); + int result = 0; + if (WIFEXITED(status)) { + result = WEXITSTATUS(status); + } + return result; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/jni/Exec/com_google_ase_Exec.h Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,43 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class com_google_ase_Exec */ + +#ifndef _Included_com_google_ase_Exec +#define _Included_com_google_ase_Exec +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_google_ase_Exec + * Method: createSubprocess + * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[I)Ljava/io/FileDescriptor; + */ + JNIEXPORT jobject JNICALL Java_com_google_ase_Exec_createSubprocess + (JNIEnv *, jclass, jstring, jstring, jstring, jintArray); + +/* + * Class: com_google_ase_Exec + * Method: setPtyWindowSize + * Signature: (Ljava/io/FileDescriptor;IIII)V + */ + JNIEXPORT void JNICALL Java_com_google_ase_Exec_setPtyWindowSize + (JNIEnv *, jclass, jobject, jint, jint, jint, jint); + +/* + * Class: com_google_ase_Exec + * Method: waitFor + * Signature: (I)I + */ + JNIEXPORT jint JNICALL Java_com_google_ase_Exec_waitFor(JNIEnv *, jclass, jint); + +/* + * Class: com_google_ase_Exec + * Method: register + * Signature: ()I + */ + JNIEXPORT jint JNICALL Java_com_google_ase_Exec_register(JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/anim/fade_out_delayed.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:fromAlpha="1.0" + android:toAlpha="0.0" + android:duration="500" + android:startOffset="1000" + android:fillAfter="true" + />
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/anim/fade_stay_hidden.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:fromAlpha="0.0" + android:toAlpha="0.0" + android:duration="500" + android:fillAfter="true" + />
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/anim/keyboard_fade_in.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/accelerate_interpolator" + android:fromAlpha="0.0" + android:toAlpha="1.0" + android:duration="100" />
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/anim/keyboard_fade_out.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:anim/accelerate_interpolator" + android:fromAlpha="1.0" + android:toAlpha="0.0" + android:duration="100" />
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/anim/slide_left_in.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="300"/> + <!-- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> --> +</set>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/anim/slide_left_out.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="0" android:toXDelta="-100%p" android:duration="300"/> + <!-- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> --> +</set>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/anim/slide_right_in.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="-100%p" android:toXDelta="0" android:duration="300"/> + <!-- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> --> +</set>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/anim/slide_right_out.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromXDelta="0" android:toXDelta="100%p" android:duration="300"/> + <!-- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> --> +</set>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/color/blue.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_selected="true" android:color="#000" /> + <item android:state_focused="true" android:color="#000" /> + <item android:state_pressed="true" android:color="#000" /> + <item android:color="#88f" /> +</selector>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/color/green.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_selected="true" android:color="#000" /> + <item android:state_focused="true" android:color="#000" /> + <item android:state_pressed="true" android:color="#000" /> + <item android:color="#8f8" /> +</selector>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/color/red.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_selected="true" android:color="#000" /> + <item android:state_focused="true" android:color="#000" /> + <item android:state_pressed="true" android:color="#000" /> + <item android:color="#f00" /> +</selector>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/drawable/btn_close.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2008 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:state_pressed="false" android:state_focused="false" + android:drawable="@+drawable/btn_close_normal" /> + + <item android:state_pressed="true" + android:drawable="@+drawable/btn_close_pressed" /> + + <item android:state_focused="true" + android:drawable="@+drawable/btn_close_selected" /> +</selector>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/drawable/connected.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + + <item + android:state_checked="true" + android:drawable="@android:drawable/presence_online" /> + + <item + android:state_expanded="true" + android:drawable="@android:drawable/presence_busy" /> + + <item + android:drawable="@android:drawable/presence_invisible" /> + +</selector>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/drawable/pubkey.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<selector + xmlns:android="http://schemas.android.com/apk/res/android"> + + <item + android:state_checked="true" + android:drawable="@drawable/pubkey_unlocked" /> + + <item + android:drawable="@drawable/pubkey_locked" /> + +</selector> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout-land/item_host.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/content" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:padding="10dip" + > + + <ImageView + android:id="@android:id/icon" + android:src="@drawable/connected" + android:contentDescription="@string/image_description_connected" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:paddingTop="5dip" + /> + + <LinearLayout + android:orientation="horizontal" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + > + + <TextView + android:id="@android:id/text1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="end" + android:textAppearance="?android:attr/textAppearanceLarge" + /> + + <TextView + android:id="@android:id/text2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingLeft="10dip" + android:textAppearance="?android:attr/textAppearanceSmall" + /> + + + </LinearLayout> + +</RelativeLayout> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout-port/item_host.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/content" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:padding="10dip" + > + + <ImageView + android:id="@android:id/icon" + android:src="@drawable/connected" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:paddingTop="5dip" + android:contentDescription="@string/image_description_connected" + /> + + <TextView + android:id="@android:id/text1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingRight="20dip" + android:singleLine="true" + android:ellipsize="end" + android:textAppearance="?android:attr/textAppearanceLarge" + /> + + <TextView + android:id="@android:id/text2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:layout_below="@android:id/text1" + /> + + +</RelativeLayout> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/act_colors.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + <TextView + android:text="@string/colors_fg" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:id="@+id/fg_label" + android:paddingTop="12dp" + /> + + <Spinner + android:id="@+id/fg" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toRightOf="@+id/fg_label" + /> + + <Spinner + android:id="@+id/bg" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignTop="@+id/fg" + android:layout_alignParentRight="true" + /> + + <TextView + android:text="@string/color_bg" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:layout_toLeftOf="@+id/bg" + android:paddingTop="12dp" + /> + + <GridView + android:id="@+id/color_grid" + android:layout_height="fill_parent" + android:layout_width="fill_parent" + android:padding="10dp" + android:verticalSpacing="10dp" + android:horizontalSpacing="10dp" + android:numColumns="auto_fit" + android:columnWidth="60dp" + android:stretchMode="columnWidth" + android:gravity="center" + android:layout_below="@+id/fg" + android:stackFromBottom="true" android:minHeight="60dp"/> + +</RelativeLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/act_console.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,185 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > + + <TextView + android:id="@android:id/empty" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:text="@string/terminal_no_hosts_connected" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="center" + /> + + <ViewFlipper + android:id="@+id/console_flip" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + /> + + <RelativeLayout + android:id="@+id/console_password_group" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:padding="5dip" + android:background="#80000000" + android:fadingEdge="horizontal" + android:fadingEdgeLength="25dip" + android:visibility="gone" + > + + <TextView + android:id="@+id/console_password_instructions" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_width="fill_parent" + android:visibility="gone" + android:layout_marginBottom="5dip" + /> + + <EditText + android:id="@+id/console_password" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" + android:singleLine="true" + android:layout_below="@+id/console_password_instructions" + /> + + </RelativeLayout> + + <RelativeLayout + android:id="@+id/console_boolean_group" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:padding="5dip" + android:background="#80000000" + android:fadingEdge="horizontal" + android:fadingEdgeLength="25dip" + android:visibility="gone" + > + + <TextView + android:id="@+id/console_prompt" + android:layout_height="wrap_content" + android:layout_width="fill_parent" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <Button + android:id="@+id/console_prompt_no" + android:text="@string/button_no" + android:paddingTop="5dip" + android:paddingBottom="10dip" + android:paddingLeft="40dip" + android:paddingRight="40dip" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_below="@+id/console_prompt" + android:clickable="false" + /> + + <Button + android:id="@+id/console_prompt_yes" + android:text="@string/button_yes" + android:paddingTop="5dip" + android:paddingBottom="10dip" + android:paddingLeft="40dip" + android:paddingRight="40dip" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toLeftOf="@+id/console_prompt_no" + android:layout_below="@+id/console_prompt" + /> + + </RelativeLayout> + + <RelativeLayout + android:id="@+id/keyboard_group" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:padding="15dip" + android:visibility="gone"> + + <ImageView + android:id="@+id/button_input" + android:paddingRight="15dip" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toRightOf="@+id/button_sym" + android:layout_alignParentBottom="true" + android:src="@+drawable/button_input" + android:contentDescription="@string/image_description_line_input" + /> + + <ImageView + android:id="@+id/button_keyboard" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentRight="true" + android:src="@+drawable/button_keyboard" + android:contentDescription="@string/image_description_show_keyboard" + /> + + <ImageView + android:id="@+id/button_ctrl" + android:paddingRight="15dip" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_alignParentBottom="true" + android:src="@+drawable/button_ctrl" + android:contentDescription="@string/image_description_toggle_control_character" + /> + + <ImageView + android:id="@+id/button_esc" + android:paddingRight="15dip" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toRightOf="@+id/button_ctrl" + android:layout_alignParentBottom="true" + android:src="@+drawable/button_esc" + android:contentDescription="@string/image_description_send_escape_character" + /> + + <ImageView + android:id="@+id/button_sym" + android:paddingRight="15dip" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_toRightOf="@+id/button_esc" + android:src="@+drawable/button_sym" + android:contentDescription="@string/image_description_sym" + /> + + </RelativeLayout> + +</RelativeLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/act_generatepubkey.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="wrap_content" + android:scrollbars="vertical" + android:layout_width="fill_parent"> + + <TableLayout + android:orientation="vertical" + android:layout_height="wrap_content" + android:paddingLeft="10dip" + android:paddingRight="10dip" + android:scrollbars="vertical" + android:layout_width="fill_parent"> + + <TableRow> + <TextView + android:text="@string/prompt_nickname" + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <EditText + android:id="@+id/nickname" + android:hint="@string/prompt_nickname_hint_pubkey" + android:layout_height="wrap_content" + android:singleLine="true" + android:layout_weight="1" /> + </TableRow> + + <TableRow> + <TextView + android:text="@string/prompt_type" + android:paddingRight="10dip" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="bottom|right" + android:layout_gravity="center_vertical" /> + + <RadioGroup + android:id="@+id/key_type" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:checkedButton="@+id/rsa"> + + <RadioButton + android:id="@+id/rsa" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="RSA" /> + + <RadioButton + android:id="@+id/dsa" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="DSA" /> + + <RadioButton + android:id="@+id/ec" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="EC" /> + </RadioGroup> + </TableRow> + + <TableRow> + <TextView + android:text="@string/prompt_bits" + android:paddingRight="10dip" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="right|center_vertical" /> + + <EditText + android:id="@+id/bits" + android:inputType="number" + android:layout_height="wrap_content" + android:text="2048" + android:singleLine="true" + android:layout_weight="1" /> + </TableRow> + + <SeekBar + android:layout_height="wrap_content" + android:id="@+id/bits_slider" + android:layout_width="fill_parent" + android:paddingBottom="10dip" + android:max="3328" + android:progress="256" /> + + <TextView + android:text="@string/prompt_password_can_be_blank" + android:gravity="left" + android:layout_height="wrap_content" + android:layout_width="wrap_content" /> + + <TableRow> + <TextView + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text="@string/prompt_password" /> + + <EditText + android:id="@+id/password1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:inputType="textPassword" + android:singleLine="true" + android:layout_weight="1" /> + </TableRow> + + <TableRow> + <LinearLayout + android:paddingRight="10dip" + android:orientation="vertical" + android:gravity="right|center_vertical"> + + <TextView + android:gravity="right|bottom" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text="@string/prompt_password" /> + + <TextView + android:gravity="right|top" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="@string/prompt_again" /> + </LinearLayout> + + <EditText + android:id="@+id/password2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:inputType="textPassword" + android:singleLine="true" + android:layout_weight="1" /> + </TableRow> + + <CheckBox + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/unlock_at_startup" + android:text="@string/pubkey_load_on_start" /> + + <CheckBox + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/confirm_use" + android:text="@string/pubkey_confirm_use" /> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/save" + android:text="@string/pubkey_generate" + android:enabled="false" /> + </TableLayout> +</ScrollView>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/act_help.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + > + + <LinearLayout + android:id="@+id/topics" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal" + > + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/msg_version" + android:paddingTop="2dip" + android:textAppearance="?android:attr/textAppearanceSmall" + android:gravity="right" + android:paddingRight="2dip" + /> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/help_intro" + android:paddingTop="2dip" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="center_horizontal" + /> + + </LinearLayout> +</ScrollView>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/act_help_topic.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > + + <com.five_ten_sg.connectbot.util.HelpTopicView + android:id="@+id/topic_text" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + /> + +</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/act_hostlist.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > + + <LinearLayout + android:id="@+id/transport_box" + android:orientation="horizontal" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentLeft="true" + > + + <Spinner + android:id="@+id/transport_selection" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentLeft="true" + /> + + <EditText + android:id="@+id/front_quickconnect" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:hint="username@hostname:port" + android:layout_toRightOf="@+id/transport_selection" + android:layout_alignParentBottom="true" + android:inputType="textEmailAddress" + /> + </LinearLayout> + + <ListView + android:id="@android:id/list" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layout_above="@+id/transport_box" + /> + + <TextView + android:id="@android:id/empty" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:text="@string/list_host_empty" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="center" + android:layout_above="@+id/transport_box" + /> + +</RelativeLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/act_portforwardlist.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > + + <ListView android:id="@android:id/list" + android:layout_width="fill_parent" + android:layout_height="0dip" + android:layout_weight="1" + /> + + <TextView android:id="@android:id/empty" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:text="@string/portforward_list_empty" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="center" + /> +</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/act_pubkeylist.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > + + <ListView android:id="@android:id/list" + android:layout_width="fill_parent" + android:layout_height="0dip" + android:layout_weight="1" + /> + + <TextView android:id="@android:id/empty" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:text="@string/pubkey_list_empty" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="center" + /> +</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/act_wizard.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:gravity="right" + > + + <ViewFlipper + android:id="@+id/wizard_flipper" + android:layout_width="fill_parent" + android:layout_height="0dip" + android:layout_weight="1" + /> + + <LinearLayout + android:orientation="horizontal" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="5dip" + > + + <Button + android:id="@+id/action_prev" + android:layout_width="120dip" + android:layout_height="wrap_content" + android:drawableLeft="@drawable/ic_btn_back" + android:text="Cancel" + android:gravity="center" + /> + + <Button + android:id="@+id/action_next" + android:layout_width="120dip" + android:layout_height="wrap_content" + android:drawableRight="@drawable/ic_btn_next" + android:text="Agree" + android:gravity="center" + /> + + </LinearLayout> + +</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/dia_changepassword.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingLeft="10dip" + android:paddingRight="10dip" + > + + <TableRow android:id="@+id/old_password_prompt"> + <TextView + android:text="@string/prompt_old_password" + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_width="wrap_content" + /> + + <EditText + android:id="@+id/old_password" + android:layout_width="200dip" + android:layout_height="wrap_content" + android:singleLine="true" + android:inputType="textPassword" + /> + </TableRow> + + <TableRow> + <TextView + android:text="@string/prompt_password" + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_width="wrap_content" + /> + + <EditText + android:id="@+id/password1" + android:layout_width="200dip" + android:layout_height="wrap_content" + android:singleLine="true" + android:inputType="textPassword" + /> + </TableRow> + + <TableRow> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:gravity="right" + > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/prompt_password" + android:paddingRight="10dip" + android:gravity="right|bottom" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/prompt_again" + android:paddingRight="10dip" + android:gravity="right|top" + android:textAppearance="?android:attr/textAppearanceSmall" + /> + </LinearLayout> + + <EditText + android:id="@+id/password2" + android:layout_width="200dip" + android:layout_height="wrap_content" + android:singleLine="true" + android:inputType="textPassword" + /> + </TableRow> +</TableLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/dia_gatherentropy.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingLeft="10dip" + android:paddingRight="10dip" + > + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/pubkey_touch_hint" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="center"/> + + <com.five_ten_sg.connectbot.util.EntropyView + android:id="@+id/entropy" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="#666666ff" + android:layout_marginBottom="10dip" + android:layout_marginTop="10dip" + android:drawingCacheQuality="auto"/> +</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/dia_password.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="250dip" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="10dip" + > + + <EditText + android:id="@android:id/text1" + android:layout_width="250dip" + android:singleLine="true" + android:layout_height="wrap_content" + android:inputType="textPassword" + android:hint="Password" + /> + +</LinearLayout> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/dia_portforward.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="fill_parent" + android:layout_width="fill_parent" + android:scrollbars="vertical" + > + + <TableLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingLeft="10dip" + android:paddingRight="10dip" + > + + <TableRow> + <TextView + android:text="@string/prompt_nickname" + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <EditText + android:id="@+id/nickname" + android:hint="Internal Webserver" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:layout_weight="1" + /> + </TableRow> + + <TableRow> + <TextView + android:text="@string/prompt_type" + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <Spinner android:id="@+id/portforward_type" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:entries="@array/list_portforward_types" + android:prompt="@string/prompt_type" + android:layout_weight="1" + /> + </TableRow> + + <TableRow> + <TextView + android:text="@string/prompt_source_port" + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <EditText + android:id="@+id/portforward_source" + android:hint="8080" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:inputType="number" + /> + </TableRow> + + <TableRow> + <TextView + android:text="@string/prompt_destination" + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <EditText + android:id="@+id/portforward_destination" + android:hint="localhost:80" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:inputType="textEmailAddress" + /> + </TableRow> + </TableLayout> +</ScrollView>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/dia_resize.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingLeft="10dip" + android:paddingRight="10dip" + > + + <EditText + android:id="@+id/width" + android:layout_width="100dip" + android:layout_height="wrap_content" + android:singleLine="true" + android:inputType="number" + /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/dia_resize_x" + android:paddingLeft="10dip" + android:paddingRight="10dip" + android:gravity="right|bottom" + android:textAppearance="?android:attr/textAppearanceLarge" + /> + + + <EditText + android:id="@+id/height" + android:layout_width="100dip" + android:layout_height="wrap_content" + android:singleLine="true" + android:inputType="number" + /> +</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/file_dialog_main.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout android:id="@+id/relativeLayout01" + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + <LinearLayout android:id="@+id/fdLinearLayoutList" + android:orientation="vertical" android:layout_width="fill_parent" + android:layout_height="wrap_content" android:layout_alignParentBottom="true"> + + <LinearLayout android:id="@+id/fdLinearLayoutSelect" + android:orientation="vertical" android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingLeft="10dp" + android:paddingRight="10dp" android:paddingBottom="5dp"> + + <LinearLayout android:orientation="horizontal" + android:layout_width="fill_parent" android:layout_height="fill_parent"> + <Button android:id="@+id/fdButtonNew" android:layout_height="wrap_content" + android:layout_width="0dip" android:layout_weight=".3" + android:text="@string/nnew"></Button> + <Button android:id="@+id/fdButtonSelect" android:layout_height="wrap_content" + android:layout_width="0dip" android:layout_weight=".6" + android:text="@string/select"></Button> + <Button android:id="@+id/fdButtonCancel" android:layout_height="wrap_content" + android:layout_width="0dip" android:layout_weight=".3" + android:text="@string/cancel"></Button> + </LinearLayout> + </LinearLayout> + + <LinearLayout android:id="@+id/fdLinearLayoutCreate" + android:orientation="vertical" android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingLeft="10dp" + android:paddingRight="10dp" android:paddingBottom="5dp"> + <TextView android:id="@+id/textViewFilename" android:text="@string/file_name" + android:layout_width="fill_parent" android:layout_height="wrap_content" /> + <EditText android:text="" android:id="@+id/fdEditTextFile" android:inputType="text" + android:layout_width="fill_parent" android:layout_height="wrap_content"></EditText> + + <LinearLayout android:orientation="horizontal" + android:layout_width="fill_parent" android:layout_height="fill_parent"> + <Button android:id="@+id/fdButtonCancelCreate" android:layout_height="wrap_content" + android:layout_width="0dip" android:layout_weight=".3" + android:text="@string/cancel"></Button> + <Button android:id="@+id/fdButtonCreate" android:layout_height="wrap_content" + android:layout_width="0dip" android:layout_weight=".7" + android:text="@string/new_file"></Button> + </LinearLayout> + </LinearLayout> + + </LinearLayout> + + <LinearLayout android:orientation="vertical" + android:layout_width="fill_parent" android:layout_height="fill_parent" + android:layout_above="@+id/fdLinearLayoutList"> + <TextView android:id="@+id/path" android:layout_width="fill_parent" + android:layout_height="wrap_content" /> + <ListView android:id="@android:id/list" android:layout_width="fill_parent" + android:layout_height="fill_parent" /> + <TextView android:id="@android:id/empty" + android:layout_width="fill_parent" android:layout_height="fill_parent" + android:text="@string/no_data" /> + </LinearLayout> + + + + +</RelativeLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/file_dialog_row.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" android:layout_height="fill_parent"> + + <ImageView android:layout_alignParentLeft="true" android:id="@+id/fdrowimage" + android:layout_height="35dp" android:layout_width="wrap_content" + android:paddingRight="5dp" android:paddingLeft="3dp"></ImageView> + <TextView android:text="@+id/fdrowtext" android:layout_width="wrap_content" + android:id="@+id/fdrowtext" android:layout_toRightOf="@+id/fdrowimage" + android:layout_alignTop="@+id/fdrowimage" android:layout_alignBottom="@+id/fdrowimage" + android:gravity="center_vertical" android:layout_height="35dp" + android:textSize="23dp"></TextView> + +</RelativeLayout> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/item_portforward.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_height="wrap_content" + android:orientation="vertical" + android:gravity="left|center_vertical" + android:layout_width="fill_parent" + android:padding="10dip" + > + + <TextView + android:id="@android:id/text1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceLarge" + android:text="Tunnel Nickname" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + /> + + <TextView + android:id="@android:id/text2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="Local port 8080 to 192.168.1.1:80" + android:layout_below="@android:id/text1" + /> + +</RelativeLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/item_pubkey.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/content" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:padding="10dip"> + + <ImageView + android:id="@android:id/icon1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/pubkey" + android:contentDescription="@string/image_description_key_is_locked" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_marginLeft="10dip"/> + + <TextView + android:id="@android:id/text1" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceLarge" + android:text="Key Example" + android:layout_alignParentLeft="true" + android:bufferType="normal" android:layout_width="wrap_content" android:layout_toLeftOf="@android:id/icon1"/> + + <TextView + android:id="@android:id/text2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:text="DSA 1024-bit" + android:layout_below="@android:id/text1" + /> + +</RelativeLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/item_terminal.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > + + <TextView + android:id="@+id/terminal_overlay" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceLarge" + android:background="#aa000000" + android:padding="10dip" + android:layout_centerInParent="true" + /> + +</RelativeLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/string_picker.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- Copyright (C) 2008 The Android Open Source Project +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="304dp" + android:layout_height="match_parent" + android:background="@drawable/keyboard_popup_panel_trans_background"> + + <GridView + android:id="@+id/stringPicker" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:padding="4dp" + android:verticalSpacing="8dp" + android:horizontalSpacing="8dp" + android:gravity="start" + android:drawSelectorOnTop="false" + android:numColumns="4" + android:columnWidth="48dp" + android:fadingEdge="none" + android:layout_gravity="center_vertical" + android:listSelector="#0000" + /> + + <Button + android:id="@+id/cancel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/btn_close" + android:layout_gravity="center_vertical" + /> +</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/string_picker_button.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2008 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<Button xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:clickable="false" + android:focusable="false" + android:textAppearance="?android:attr/textAppearanceSmallInverse" + android:textColor="#FF000000" +/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/wiz_eula.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + > + + <LinearLayout + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="10dip" + > + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="510 ConnectBot is a simple, powerful, open-source Secure Shell (SSH) client for your Android device." + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingTop="10dip" + android:text="It can manage several SSH sessions, create secure tunnels, and copy/paste between other apps." + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingTop="10dip" + android:text="@string/copyright_info" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingTop="10dip" + android:autoLink="web" + android:text="@string/copyright_location" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingTop="10dip" + android:text="@string/msg_version" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + </LinearLayout> + +</ScrollView>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-af/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title_hosts_list">Gashere</string> + <string name="title_pubkey_list">Publieke Sleutels</string> + <string name="title_port_forwards_list">Poort aansturings</string> + <string name="title_host_editor">Redigeer Gasheer</string> + <string name="title_help">Hulp</string> + <string name="title_colors">Kleure</string> + <string name="resolve_connect">Verbind</string> + <string name="menu_insert">Voeg Gasheer by</string> + <string name="menu_delete">Verwyder Gasheer</string> + <string name="menu_preferences">Voorkeure</string> + <string name="help_about">Aangaande ConnectBot</string> + <string name="help_keyboard">Sleutelbord</string> + <string name="pubkey_generate">Genereer</string> + <string name="pubkey_import">Voer in</string> + <string name="pubkey_delete">Verwyder sleutel</string> + <string name="pubkey_gather_entropy">Versamel Ewekansigheid</string> + <string name="pubkey_touch_prompt">Raak hierdie boks om ewekansigheid te versamel: %1$d%% voltooi</string> + <string name="pubkey_touch_hint">Om ewekansigheid te verseker gedurende die sleutel generering, beweeg u vinger ewekansig oor die boks hieronder.</string> + <string name="pubkey_copy_private">Dupliseer privaat sleutel</string> + <string name="pubkey_copy_public">Dupliseer publieke sleutel</string> + <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> + <string name="pubkey_unknown_format">Onbekende formaat</string> + <string name="pubkey_change_password">Verander wagwoord</string> + <string name="pubkey_list_pick">Kies van /sdcard</string> + <string name="pubkey_unlock">Ontsluit sleutel</string> + <string name="pubkey_memory_load">Laai na geheue</string> + <string name="pubkey_confirm_use">Bevestig voor gebruik</string> + <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> + <string name="portforward_edit">Redigeer poort aansturing</string> + <string name="portforward_delete">Verwyder poort aanstuur</string> + <string name="prompt_nickname">Bynaam:</string> + <string name="prompt_source_port">Oorsprong poort:</string> + <string name="prompt_destination">Bestemming:</string> + <string name="prompt_old_password">Ou wagwoord:</string> + <string name="prompt_password">Wagwoord:</string> + <string name="prompt_type">Tipe:</string> + <string name="prompt_password_can_be_blank">Nota: wagwoord kan leeg gelos word</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-ar/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">عميل SSH مفتوح المصدر و بسيط وقوي</string> + <string name="title_hosts_list">المخدمات</string> + <string name="title_pubkey_list">المفاتيح العامة</string> + <string name="title_port_forwards_list">تحويلات المنافذ</string> + <string name="title_host_editor">تعديل مخدم</string> + <string name="title_help">مساعدة</string> + <string name="title_colors">الألوان</string> + <string name="resolve_connect">اتصل</string> + <string name="menu_insert">اضافة مخدم</string> + <string name="menu_delete">حذف مخدم</string> + <string name="menu_preferences">التفضيلات</string> + <string name="help_intro">الرجاء اختار من الاسفل من اجل معلومات اكثر عن هذا الموضوع</string> + <string name="help_about">حول البرنامج</string> + <string name="help_keyboard">لوحة المفاتيح</string> + <string name="pubkey_generate">توليد</string> + <string name="pubkey_import">استيراد</string> + <string name="pubkey_delete">حذف المفتاح</string> + <string name="pubkey_touch_hint">للتاكد من العشوائية خلال توليد المفتاح , حرك اصبعك بشكل عشوائي فوق المربع في الاسفل</string> + <string name="pubkey_generating">جاري توليد المفتاح</string> + <string name="pubkey_copy_private">نسخ مفتاح خاص</string> + <string name="pubkey_copy_public">نسخ مفتاح عام</string> + <string name="pubkey_list_empty">"حدد القائمة لانشاء او استيراد المفاتيح"</string> + <string name="pubkey_unknown_format">صيغة غير معروفة</string> + <string name="pubkey_change_password">تغيير كلمة المرور</string> + <string name="pubkey_list_pick">اختار من بطاقة الذاكرة</string> + <string name="pubkey_import_parse_problem">مشكلة في تفسير المفتاح الخاص المستورد</string> + <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> + <string name="button_yes">نعم</string> + <string name="button_no">ﻻ</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="no">ﻻ</string> + <string name="yes">نعم</string> + <string name="exceptions_submit_message">الظاهر بان البرنامج واجه مشكلة في اخر جلسة عمل. هل ترغب بارسال تقرير لمطورين البرنامج؟</string> + <string name="menu_colors_reset">إعادة ضبط</string> + <string name="app_is_running">البرنامج يعمل</string> + <string name="color_red">أحمر</string> + <string name="color_green">أخضر</string> + <string name="color_blue">أزرق</string> + <string name="color_gray">رمادي</string> + <string name="image_description_connected">متصل</string> + <string name="image_description_key_is_locked">المفتاح مقفل</string> + <string name="image_description_show_keyboard">عرض لوحة المفاتيح</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-be/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> + <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-bg/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Прост, мощен SSH клиент с отворен код</string> + <string name="title_hosts_list">Хостове</string> + <string name="title_pubkey_list">Публични ключове</string> + <string name="title_port_forwards_list">Пренасочване на портове</string> + <string name="title_host_editor">Редактиране на хост</string> + <string name="title_help">Помощ</string> + <string name="title_colors">Цветове</string> + <string name="resolve_connect">Свързване</string> + <string name="menu_insert">Добавяне на хост</string> + <string name="menu_delete">Изтрий хост</string> + <string name="menu_preferences">Предпочитания</string> + <string name="help_about">Относно ConnectBot</string> + <string name="help_keyboard">Клавиатура</string> + <string name="pubkey_generate">Генериране</string> + <string name="pubkey_import">Импортиране</string> + <string name="pubkey_delete">Клавиш Delete</string> + <string name="pubkey_copy_private">Копира частния ключ</string> + <string name="pubkey_copy_public">Копира публичния ключ</string> + <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> + <string name="pubkey_unknown_format">Непознат формат</string> + <string name="pubkey_change_password">Промени паролата</string> + <string name="pubkey_list_pick">Избери от /sdcard</string> + <string name="pubkey_import_parse_problem">Проблем при прочитането на импортирания частен ключ</string> + <string name="pubkey_unlock">Клавиш за отключване</string> + <string name="pubkey_memory_load">Зареди в паметта</string> + <string name="pubkey_memory_unload">Премахни от паметта</string> + <string name="pubkey_load_on_start">Зареди ключа при стартиране</string> + <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> + <string name="portforward_edit">Променете пренасочването на портове</string> + <string name="portforward_delete">Изтрийте пренасочването на портове</string> + <string name="prompt_nickname">Псевдоним:</string> + <string name="prompt_destination">Назначение:</string> + <string name="prompt_old_password">Стара парола</string> + <string name="prompt_password">Парола:</string> + <string name="prompt_again">(отново)</string> + <string name="prompt_type">Тип:</string> + <string name="prompt_password_can_be_blank">Бележка: паролата не може да е празна</string> + <string name="prompt_bits">Битове</string> + <string name="alert_passwords_do_not_match_msg">Паролите не съвпадат!</string> + <string name="alert_wrong_password_msg">Грешна парола!</string> + <string name="alert_sdcard_absent">SD картата не е поставена</string> + <string name="button_add">Добавяне</string> + <string name="button_change">Промяна</string> + <string name="button_generate">Генерирай ключ</string> + <string name="button_resize">Промяна на размера на екрана</string> + <string name="alert_disconnect_msg">Връзката изгубена</string> + <string name="list_keymode_none">Забраняване</string> + <string name="console_copy_done">Копирани %1$d байта в клипборда</string> + <string name="console_menu_close">Затваряне</string> + <string name="console_menu_copy">Копиране</string> + <string name="console_menu_paste">Поставяне</string> + <string name="console_menu_portforwards">Пренасочване на портове</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="list_host_disconnect">Прекъсване на връзката</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-ca/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Client SSH simple, potent i lliure</string> + <string name="service_desc">Manté les connexions SSH i les claus públiques</string> + <string name="title_hosts_list">Servidors</string> + <string name="title_pubkey_list">Claus Públiques</string> + <string name="title_port_forwards_list">Redirecció de Ports</string> + <string name="title_host_editor">Edició del Servidor</string> + <string name="title_help">Ajuda</string> + <string name="title_colors">Colors</string> + <string name="resolve_connect">Connecta</string> + <string name="resolve_entropy">Recull Entropia</string> + <string name="menu_insert">Afegeix servidor</string> + <string name="menu_delete">Elimina servidor</string> + <string name="menu_preferences">Preferències</string> + <string name="help_intro">Si us plau, esculli un tema per a més informació en aquest assumpte en particular</string> + <string name="help_about">Sobre ConnectBot</string> + <string name="help_keyboard">Teclat</string> + <string name="pubkey_generate">Genera</string> + <string name="pubkey_import">Importa</string> + <string name="pubkey_delete">Elimina la clau</string> + <string name="pubkey_gather_entropy">Recull Entropia</string> + <string name="pubkey_touch_prompt">Toca aquesta caixa per obtenir aleatorietat: %1$d%% completat</string> + <string name="pubkey_touch_hint">Per assegurar l\'aleatorietat durant la generació de la clau, mou el dit aleatoriament per sobre la caixa de sota.</string> + <string name="pubkey_generating">"Generant parell de claus…"</string> + <string name="pubkey_copy_private">Còpia la clau privada</string> + <string name="pubkey_copy_public">Còpia la clau pública</string> + <string name="pubkey_list_empty">Pulsa Menu per crear\no importar parells de claus.</string> + <string name="pubkey_unknown_format">Format desconegut</string> + <string name="pubkey_change_password">Canvia la contrasenya</string> + <string name="pubkey_list_pick">Obté de /sdcard</string> + <string name="pubkey_import_parse_problem">Problema analitzant les claus privades importades</string> + <string name="pubkey_unlock">Desbloqueja clau</string> + <string name="pubkey_failed_add">Contrasenya incorrecta per la clau \'%1$s\'. Autenticació fallada</string> + <string name="pubkey_memory_load">Carrega a la memòria</string> + <string name="pubkey_memory_unload">Descarrega de la memòria</string> + <string name="pubkey_load_on_start">Carrega la clau a l\'inici</string> + <string name="pubkey_confirm_use">Confirmar abans d\'usar</string> + <string name="portforward_list_empty">Pulsa Menu per crear\nredireccions de ports.</string> + <string name="portforward_edit">Edita redireccions de ports</string> + <string name="portforward_delete">Elimina redireccions de ports</string> + <string name="prompt_nickname">Sobrenom:</string> + <string name="prompt_nickname_hint_pubkey">La meva clau</string> + <string name="prompt_source_port">Port d\'origen:</string> + <string name="prompt_destination">Destí:</string> + <string name="prompt_old_password">Contrasenya anterior:</string> + <string name="prompt_password">Contrasenya:</string> + <string name="prompt_again">(altre cop)</string> + <string name="prompt_type">Tipus:</string> + <string name="prompt_password_can_be_blank">Nota: la contrasenya pot ser en blanc</string> + <string name="prompt_bits">Bits</string> + <string name="prompt_pubkey_password">Contrasenya per la clau \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Permet al servidor remot\nutilitzar la clau \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">ALERTA: LA IDENTIFICACIÓ DEL SERVIDOR REMOT HA CANVIAT!</string> + <string name="host_verification_failure_warning">ES POSSIBLE QUE ALGÚ ESTIGUI FENT ALGUNA COSA LLETGA!\nAlgú pot estar escoltant la teva comunicació (atac home-al-mig)!\nTambé és possible que simplement el servidor hagi canviat la clau.</string> + <string name="prompt_host_disconnected">Servidor desconnectat.\nTancar sessió?</string> + <string name="prompt_continue_connecting">Estàs segur que vols\ncontinuar connectant?</string> + <string name="host_authenticity_warning">La autenticació amb el servidor \'%1$s\' no es pot establir.</string> + <string name="host_fingerprint">Servidor %1$s empremta de la clau és %2$s</string> + <string name="alert_passwords_do_not_match_msg">Les contrasenyes no coincideixen!</string> + <string name="alert_wrong_password_msg">La contrasenya no és correcta.</string> + <string name="alert_key_corrupted_msg">Les claus privades semblen malmèses!</string> + <string name="alert_sdcard_absent">La targeta SD no es troba present!</string> + <string name="button_add">Afegeix</string> + <string name="button_change">Canvia</string> + <string name="button_generate">Genera clau</string> + <string name="button_resize">Redimensiona</string> + <string name="alert_disconnect_msg">Connexió perduda</string> + <string name="pref_emulation_category">Emulador del terminal</string> + <string name="pref_emulation_title">Mode d\'emulació</string> + <string name="pref_emulation_summary">Mode d\'emulació de terminal per l\'ús de connexions PTY</string> + <string name="pref_scrollback_title">Tamany de la història</string> + <string name="pref_scrollback_summary">Tamany de la memòria per mantenir la història de cada consola</string> + <string name="pref_ui_category">Interfície d\'usuari</string> + <string name="pref_rotation_title">Mode de rotació</string> + <string name="pref_rotation_summary">Com canvia la orientació quan el teclat s\'obre o es tanca</string> + <string name="pref_fullscreen_title">Pantalla completa</string> + <string name="pref_fullscreen_summary">Amaga la barra d\'estat en consola</string> + <string name="pref_memkeys_title">Recorda les claus en memòria</string> + <string name="pref_memkeys_summary">Manté les claus descarregadesen memòria fins que el servei finalitzi</string> + <string name="pref_update_title">Comprova actualització</string> + <string name="pref_update_summary">Escull la freqüència màxima de comprovació d\'actualitzacions de ConnectBot</string> + <string name="pref_conn_persist_title">Connexions persistents</string> + <string name="pref_conn_persist_summary">Manté les connexions mentre l\'aplicació és en segon pla</string> + <string name="pref_keymode_title">Drecera de carpetes</string> + <string name="pref_keymode_summary">Escull com usar Alt per \'/\' i Shift per Tab</string> + <string name="pref_camera_title">Drecera de càmera</string> + <string name="pref_camera_summary">Escull quina acció fer quan el botó de la càmera es clica</string> + <string name="pref_keepalive_title">Manté la pantalla encesa</string> + <string name="pref_keepalive_summary">Evita que la pantalla s\'apagui mentre s\'usa la consola</string> + <string name="pref_wifilock_title">Manté activa la Wi-Fi</string> + <string name="pref_wifilock_summary">Evita que la Wi-Fi s\'apagui mentre hi ha una sessió activa</string> + <string name="pref_bumpyarrows_title">Cursors vibrants</string> + <string name="pref_bumpyarrows_summary">Vibra quan s\'envien els cursors de direcció amb la rodeta; útil per connexions lentes</string> + <string name="pref_bell_category">So del Terminal</string> + <string name="pref_bell_title">So activat</string> + <string name="pref_bell_volume_title">Volum del so</string> + <string name="pref_bell_vibrate_title">Vibra en sonar</string> + <string name="pref_bell_notification_title">Notificacions en rerefons</string> + <string name="pref_bell_notification_summary">Envia notificacions quan un terminal actiu al rerefons envia una senyal de so.</string> + <string name="list_keymode_right">Utilitza les tecles de la dreta</string> + <string name="list_keymode_left">Utilitza les tecles de l\'esquerra</string> + <string name="list_keymode_none">Deshabilita</string> + <string name="list_pubkeyids_none">No usis claus</string> + <string name="list_pubkeyids_any">Fes servir qualsevol clau desbloquejada</string> + <string name="hostpref_nickname_title">Sobrenom</string> + <string name="hostpref_color_title">Color de la categoria</string> + <string name="hostpref_fontsize_title">Mida de la lletra (pt)</string> + <string name="hostpref_pubkeyid_title">Usa autenticació de claus públiques</string> + <string name="hostpref_authagent_title">Usa agent d\'autenticació SSH</string> + <string name="hostpref_postlogin_title">Automatització post-entrada</string> + <string name="hostpref_postlogin_summary">Comandes a executar en el servidor remot un cop autenticat.</string> + <string name="hostpref_compression_title">Compressió</string> + <string name="hostpref_compression_summary">Això pot ajudar per xarxes lentes</string> + <string name="hostpref_wantsession_title">Inicia una sessió de shell</string> + <string name="hostpref_wantsession_summary">Deshabilita aquesta preferència per només usar redireccionament de ports</string> + <string name="hostpref_stayconnected_title">Manté connectat</string> + <string name="hostpref_stayconnected_summary">Intenta reconnectar al servidor si es desconnecta</string> + <string name="hostpref_delkey_title">Tecla DEL</string> + <string name="hostpref_delkey_summary">El codi enviat al pulsar la tecla DEL</string> + <string name="hostpref_encoding_title">Codificació</string> + <string name="hostpref_encoding_summary">Codificació de caràcters per el servidor</string> + <string name="hostpref_connection_category">Paràmetres de connexió</string> + <string name="hostpref_username_title">Nom d\'usuari</string> + <string name="hostpref_hostname_title">Servidor</string> + <string name="hostpref_port_title">Port</string> + <string name="bind_never">Mai connectat</string> + <string name="bind_minutes">Fa %1$s minuts</string> + <string name="bind_hours">Fa %1$s hores</string> + <string name="bind_days">Fa %1$s dies</string> + <string name="console_copy_done">Copiats %1$d bytes al porta-retalls</string> + <string name="console_copy_start">Toca i arrosega\no fes servir les tecles de direcció\nper escollir l\'àrea a copiar</string> + <string name="console_menu_close">Tanca</string> + <string name="console_menu_copy">Copia</string> + <string name="console_menu_paste">Enganxa</string> + <string name="console_menu_portforwards">Redireccionament de ports</string> + <string name="console_menu_resize">Força el tamany</string> + <string name="console_menu_urlscan">Llistat de URL</string> + <string name="button_yes">Sí</string> + <string name="button_no">No</string> + <string name="portforward_local">Local</string> + <string name="portforward_remote">Remot</string> + <string name="portforward_dynamic">Dinàmic (SOCKS)</string> + <string name="portforward_pos">Crea redireccionament de ports</string> + <string name="portforward_done">Redireccionament creat correctament</string> + <string name="portforward_problem">Problemes creant el redireccionament de ports, potser s\'usen ports per sota del 1024 o el port és en ús actualment?</string> + <string name="portforward_menu_add">Afegeix redireccionament de ports</string> + <string name="hint_userhost">usuari\@servidor</string> + <string name="list_format_error">Usa el format %1$s</string> + <string name="format_username">Usuari</string> + <string name="format_hostname">servidor</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Gestiona Claus</string> + <string name="list_menu_sortcolor">Ordena per color</string> + <string name="list_menu_sortname">Ordena per nom</string> + <string name="list_menu_settings">Arrenjaments</string> + <string name="list_host_disconnect">Desconnecta</string> + <string name="list_host_edit">Edita el servidor</string> + <string name="list_host_portforwards">Edita el redireccionament de ports</string> + <string name="list_host_delete">Elimina servidors</string> + <string name="list_host_empty">Utilitza el quadre de connexió ràpida\nde sota per connectar al servidor</string> + <string name="list_rotation_default">Per defecte</string> + <string name="list_rotation_land">Força horitzontal</string> + <string name="list_rotation_port">Força vertical</string> + <string name="list_rotation_auto">Automàtic</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A llavors Espai</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Res</string> + <string name="list_delkey_backspace">Retrocés</string> + <string name="list_delkey_del">Suprimeix</string> + <string name="delete_message">Estas segur que vols esborrar \'%1$s\'?</string> + <string name="delete_pos">Sí, esborra</string> + <string name="delete_neg">Cancel·la</string> + <string name="wizard_agree">Accepto</string> + <string name="wizard_next">Següent</string> + <string name="wizard_back">Enrere</string> + <string name="terminal_no_hosts_connected">No hi ha servidors connectats actualment</string> + <string name="terminal_connecting">Connectant a %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">Clau de servidor \'%1$s\' verificada: %2$s</string> + <string name="terminal_failed">Verificació de la clau del servidor errònia.</string> + <string name="terminal_using_s2c_algorithm">Algoritme servidor-a-client: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algoritme client-a-servidor: %1$s %2$s</string> + <string name="terminal_using_algorithm">Usant algoritme: %1$s %2$s</string> + <string name="terminal_auth">Intentant autenticar</string> + <string name="terminal_auth_pass">Intentant autenticació de \'contrasenya\'</string> + <string name="terminal_auth_pass_fail">Autenticació amb \'contrasenya\' errònia</string> + <string name="terminal_auth_pubkey_any">Intentant autenticació amb \'claus públiques\' amb totes les claus en memòria</string> + <string name="terminal_auth_pubkey_invalid">La clau pública seleccionada és invàlida, intenta reseleccionar la clau en l\'editor del servidor</string> + <string name="terminal_auth_pubkey_specific">Intentant autenticació amb \'claus públiques\' amb una clau específica</string> + <string name="terminal_auth_pubkey_fail">Mètode d\'autenticació \'claus públiques\' amb clau \'%1$s\' fallit</string> + <string name="terminal_auth_ki">Intentant autenticació \'teclat-interactiu\'</string> + <string name="terminal_auth_ki_fail">Mètode d\'autenticació \'teclat-interactiu\' fallit.</string> + <string name="terminal_auth_fail">[El servidor no admet autenticació amb \'contrasenya\' o \'teclat-interactiu\'.]</string> + <string name="terminal_no_session">La sessió no s\'iniciarà degut a la preferencia de servidor.</string> + <string name="terminal_enable_portfoward">Activa el redireccionament de ports: %1$s</string> + <string name="local_shell_unavailable">Fallada! El shell local no està disponible en aquest telèfon.</string> + <string name="notification_text">%1$s necessita la teva atenció.</string> + <string name="no">No</string> + <string name="with_confirmation">Amb confirmació</string> + <string name="yes">Sí</string> + <string name="exceptions_submit_message">Sembla que ConnectBot ha tingut un problema l\'últim cop que s\'ha iniciat. Enviar la informació de l\'error als desenvolupadors de ConnectBot?</string> + <string name="menu_colors_reset">Reinicia</string> + <string name="app_is_running">El ConnectBot està en marxa</string> + <string name="color_red">vermell</string> + <string name="color_green">verd</string> + <string name="color_blue">blau</string> + <string name="color_gray">gris</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-cs/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,198 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Jednoduchý, všestranný, open-source SSH klient</string> + <string name="service_desc">Správa SSH spojení a nahraných klíčů</string> + <string name="title_hosts_list">Hostitelé</string> + <string name="title_pubkey_list">Veřejné klíče</string> + <string name="title_port_forwards_list">Přesměrování portu</string> + <string name="title_host_editor">Upravit hostitele</string> + <string name="title_help">Nápověda</string> + <string name="title_colors">Barvy</string> + <string name="resolve_connect">Připojit</string> + <string name="resolve_entropy">Získat entropii</string> + <string name="menu_insert">Přidat hostitele</string> + <string name="menu_delete">Smazat hostitele</string> + <string name="menu_preferences">Nastavení</string> + <string name="help_intro">Prosím, vyberte následující téma pro více informací na daný subjekt.</string> + <string name="help_about">O aplikaci ConnectBot</string> + <string name="help_keyboard">Klávesnice</string> + <string name="pubkey_generate">Vygenerovat</string> + <string name="pubkey_import">Importovat</string> + <string name="pubkey_delete">Smazat klíč</string> + <string name="pubkey_gather_entropy">Získávání entropie</string> + <string name="pubkey_touch_prompt">Dotkněte se plochy pro získání náhodnosti: %1$d%% hotovo</string> + <string name="pubkey_touch_hint">Pro zajištění náhodnosti během generování klíče pohybujte prstem náhodně po ploše níže.</string> + <string name="pubkey_generating">Generování páru klíčů...</string> + <string name="pubkey_copy_private">Kopírovat soukromý klíč</string> + <string name="pubkey_copy_public">Kopírovat veřejný klíč</string> + <string name="pubkey_list_empty">Zvolte \"Menu\" pro vytvoření\nnebo import párů klíčů.</string> + <string name="pubkey_unknown_format">Neznámý formát</string> + <string name="pubkey_change_password">Změnit heslo</string> + <string name="pubkey_list_pick">Vyberte z /sdcard</string> + <string name="pubkey_import_parse_problem">Problém s importem soukromého klíče</string> + <string name="pubkey_unlock">Odemknout klíč</string> + <string name="pubkey_failed_add">Špatné heslo pro klíč \'%1$s\'. Ověření selhalo.</string> + <string name="pubkey_memory_load">Nahrát do paměti</string> + <string name="pubkey_memory_unload">Odstranit z paměti</string> + <string name="pubkey_load_on_start">Nahrát klíč při startu</string> + <string name="pubkey_confirm_use">Potvrdit před použitím</string> + <string name="portforward_list_empty">Zvolte \"Menu\" pro vytvoření\npřesměrování portů.</string> + <string name="portforward_edit">Upravit přesměrování portů</string> + <string name="portforward_delete">Smazat přesměrování portů</string> + <string name="prompt_nickname">Přezdívka:</string> + <string name="prompt_nickname_hint_pubkey">Můj pracovní klíč</string> + <string name="prompt_source_port">Zdrojový port:</string> + <string name="prompt_destination">Cíl:</string> + <string name="prompt_old_password">Původní heslo:</string> + <string name="prompt_password">Heslo:</string> + <string name="prompt_again">(znovu)</string> + <string name="prompt_type">Typ:</string> + <string name="prompt_password_can_be_blank">Poznámka: heslo může být prázdné</string> + <string name="prompt_bits">Počet bitů:</string> + <string name="prompt_pubkey_password">Heslo pro klíč \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Povolit vzdálenému počítači\npoužít klíč \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">VAROVÁNÍ: IDENTIFIKACE VZDÁLENÉHO HOSTA SE ZMĚNILA!</string> + <string name="host_verification_failure_warning">JE MOŽNÉ ŽE NĚKDO PROVÁDÍ NĚCO NEKALÉHO!\nNěkdo vás může odposlouchávat (man-in-the-middle)!\nTaké je možné že se klíč počítače právě změnil.</string> + <string name="prompt_host_disconnected">Host se odpojil.\nUkončit sezení?</string> + <string name="prompt_continue_connecting">Opravdu chcete\npokračovat v připojování?</string> + <string name="host_authenticity_warning">Nelze ověřit autenticitu počítače \'%1$s\'.</string> + <string name="host_fingerprint">Otisk klíče počítače %1$s je %2$s</string> + <string name="alert_passwords_do_not_match_msg">Hesla se neshodují!</string> + <string name="alert_wrong_password_msg">Špatné heslo!</string> + <string name="alert_key_corrupted_msg">Soukromý klíč vypadá poškozeně!</string> + <string name="alert_sdcard_absent">Není vložena SD karta!</string> + <string name="button_add">Přidat</string> + <string name="button_change">Změnit</string> + <string name="button_generate">Generovat klíč</string> + <string name="button_resize">Změnit velikost</string> + <string name="alert_disconnect_msg">Spojení ztraceno</string> + <string name="pref_emulation_category">Emulace terminálu</string> + <string name="pref_emulation_title">Režim emulace</string> + <string name="pref_emulation_summary">Režim emulace terminálu použitý při PTY spojeních</string> + <string name="pref_scrollback_title">Velikost historie</string> + <string name="pref_scrollback_summary">Velikost historie uložená v paměti pro každou konzoli</string> + <string name="pref_ui_category">Uživatelské rozhraní</string> + <string name="pref_rotation_title">Režim rotace</string> + <string name="pref_rotation_summary">Jak změnit rotaci když se zobrazí / skryje klávesnice</string> + <string name="pref_fullscreen_title">Celá obrazovka</string> + <string name="pref_fullscreen_summary">Skrýt stavový řádek když je zobrazena konzole</string> + <string name="pref_memkeys_title">Uchovávat klíče v paměti</string> + <string name="pref_memkeys_summary">Ponechat odemčené klíče v paměti dokud není ukončena služba na pozadí</string> + <string name="pref_update_title">Kontrolovat aktualizace</string> + <string name="pref_update_summary">Nastavit maximální frekvenci pro kontrolu aktualizací ConnectBota</string> + <string name="pref_conn_persist_title">Trvalá spojení</string> + <string name="pref_conn_persist_summary">Vynutit spojení i v pozadí</string> + <string name="pref_keymode_title">Zkratky adresářů</string> + <string name="pref_keymode_summary">Volba použití kláves Alt pro znak \"/\" a Shift pro tabulátor</string> + <string name="pref_camera_title">Zkratka fotoaparátu</string> + <string name="pref_camera_summary">Vyberte kterou zkratku použít když je stisknuto tlačítko fotoaparátu</string> + <string name="pref_keepalive_title">Ponechat zapnutou obrazovku</string> + <string name="pref_keepalive_summary">Zabránit obrazovce ve vypnutí při práci v konzoli</string> + <string name="pref_wifilock_title">Ponechat Wi-Fi aktivní</string> + <string name="pref_wifilock_summary">Zabránit Wi-Fi ve vypnutí když je sezení aktivní</string> + <string name="pref_bumpyarrows_title">Hmatová odezva šipek</string> + <string name="pref_bumpyarrows_summary">Vibrovat při posílání kurzorových kláves z trackballu; užitečná pro špatná spojení</string> + <string name="pref_bell_category">Zvonek terminálu</string> + <string name="pref_bell_title">Zvukové upozornění</string> + <string name="pref_bell_volume_title">Hlasitost zvonku</string> + <string name="pref_bell_vibrate_title">Vibrovat při zvonku</string> + <string name="pref_bell_notification_title">Upozornění v pozadí</string> + <string name="pref_bell_notification_summary">Zobrazit upozornění když terminál běžící v pozadí zazvoní zvonkem</string> + <string name="list_keymode_right">Použít klávesy napravo</string> + <string name="list_keymode_left">Použít klávesy nalevo</string> + <string name="list_keymode_none">Vypnout</string> + <string name="list_pubkeyids_none">Nepoužívat klíče</string> + <string name="list_pubkeyids_any">Použít jakýkoliv odemčený klíč</string> + <string name="hostpref_nickname_title">Přezdívka</string> + <string name="hostpref_color_title">Barevná kategorie</string> + <string name="hostpref_fontsize_title">Velikost fontu (pt)</string> + <string name="hostpref_pubkeyid_title">Použít autentizaci veřejným klíčem</string> + <string name="hostpref_authagent_title">Použít SSH autorizačního agenta</string> + <string name="hostpref_postlogin_title">Automatizace po přihlášení</string> + <string name="hostpref_postlogin_summary">Příkazy které se spustí na vzdáleném serveru po přihlášení</string> + <string name="hostpref_compression_title">Komprese</string> + <string name="hostpref_compression_summary">Může pomoct na pomalejších sítích</string> + <string name="hostpref_wantsession_title">Spustit sezení shellu</string> + <string name="hostpref_wantsession_summary">Vypněte tuto možnost pokud pouze přesměrováváte porty</string> + <string name="hostpref_stayconnected_title">Zůstat připojený</string> + <string name="hostpref_stayconnected_summary">Zkusit se znovu připojit při odpojení</string> + <string name="hostpref_delkey_title">Klávesa DEL</string> + <string name="hostpref_delkey_summary">Kód klávesy odeslaný při stisku DEL</string> + <string name="hostpref_encoding_title">Kódování</string> + <string name="hostpref_encoding_summary">Kódování znaků na hostovi</string> + <string name="hostpref_connection_category">Nastavení připojení</string> + <string name="hostpref_username_title">Uživatelské jméno</string> + <string name="bind_never">Nikdy nepřipojen</string> + <string name="bind_minutes">Před %1$s minutami</string> + <string name="bind_hours">Před %1$s hodinami</string> + <string name="bind_days">Před %1$s dny</string> + <string name="console_copy_done">Zkopírováno %1$d bajtů do schránky</string> + <string name="console_copy_start">Stiskněte a táhněte\nnebo použijte směrový ovladač\npro výběr oblasti ke zkopírování</string> + <string name="console_menu_close">Zavřít</string> + <string name="console_menu_copy">Kopírovat</string> + <string name="console_menu_paste">Vložit</string> + <string name="console_menu_portforwards">Přesměrování portů</string> + <string name="console_menu_resize">Vynutit velikost</string> + <string name="console_menu_urlscan">Najít URL</string> + <string name="button_yes">Ano</string> + <string name="button_no">Ne</string> + <string name="portforward_local">Místní</string> + <string name="portforward_remote">Vzdálený</string> + <string name="portforward_dynamic">Dynamický (SOCKS)</string> + <string name="portforward_pos">Vytvořit přesměrování portu</string> + <string name="portforward_done">Přesměrování portu úspěšně vytvořeno</string> + <string name="portforward_menu_add">Přidat přesměrování portu</string> + <string name="hint_userhost">user\@hostname</string> + <string name="list_format_error">Použijte formát %1$s</string> + <string name="format_username">uživatelské jméno</string> + <string name="format_hostname">jméno hosta</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Spravovat veřejné klíče</string> + <string name="list_menu_sortcolor">Seřadit podle barvy</string> + <string name="list_menu_sortname">Seřadit podle jména</string> + <string name="list_menu_settings">Nastavení</string> + <string name="list_host_disconnect">Odpojit</string> + <string name="list_host_edit">Upravit hosta</string> + <string name="list_host_portforwards">Upravit přesměrování portů</string> + <string name="list_host_delete">Smazat hosta</string> + <string name="list_host_empty">Použijte pole rychlého připojení\nníže pro připojení k hostovi.</string> + <string name="list_rotation_default">Standardní</string> + <string name="list_rotation_land">Vynutit na šířku</string> + <string name="list_rotation_port">Vynutit na výšku</string> + <string name="list_rotation_auto">Automaticky</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A potom mezerník</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Nic</string> + <string name="list_delkey_backspace">Backspace</string> + <string name="list_delkey_del">Delete</string> + <string name="delete_message">Určitě chcete smazat \'%1$s\'?</string> + <string name="delete_pos">Ano, smazat</string> + <string name="delete_neg">Zrušit</string> + <string name="wizard_agree">Souhlasím</string> + <string name="wizard_next">Další</string> + <string name="wizard_back">Zpět</string> + <string name="terminal_no_hosts_connected">Žádný host není připojený</string> + <string name="terminal_connecting">Připojování k %1$s:%2$d přes %3$s</string> + <string name="terminal_failed">Selhalo ověření klíče hosta</string> + <string name="terminal_using_s2c_algorithm">Algoritmus server-klient: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algoritmus klient-server: %1$s %2$s</string> + <string name="terminal_using_algorithm">Použitý algoritmus: %1$s %2$s</string> + <string name="terminal_auth">Pokus o autentizaci</string> + <string name="terminal_auth_pubkey_invalid">Vybraný veřejný klič je neplatný, zkuste jej znovu vybrat při úpravě hosta</string> + <string name="terminal_no_session">Sezení nebude spuštěno kvůli nastavení hosta.</string> + <string name="terminal_enable_portfoward">Povolit přesměrování portu: %1$s</string> + <string name="local_shell_unavailable">Selhání! Místní shell není na tomto telefonu podporován</string> + <string name="notification_text">%1$s žádá pozornost.</string> + <string name="no">Ne</string> + <string name="with_confirmation">S potvrzením</string> + <string name="yes">Ano</string> + <string name="exceptions_submit_message">Vypadá to že měl ConnectBot problém když naposledy běžel. Odeslat hlášení o chybě vývojářům ConnectBota?</string> + <string name="menu_colors_reset">Obnovit</string> + <string name="app_is_running">ConnectBot běží</string> + <string name="color_red">červená</string> + <string name="color_green">zelená</string> + <string name="color_blue">modrá</string> + <string name="color_gray">šedá</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-da/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Enkel, kraftfuld, open source SSH klient</string> + <string name="service_desc">Opretholder SSH forbindelser og indlæste offentlige nøgler</string> + <string name="title_hosts_list">Værter</string> + <string name="title_pubkey_list">Offentlige nøgler</string> + <string name="title_port_forwards_list">Port-videresendelser</string> + <string name="title_host_editor">Rediger vært</string> + <string name="title_help">Hjælp</string> + <string name="title_colors">Farver</string> + <string name="resolve_connect">Tilslut</string> + <string name="resolve_entropy">Indsamler entropi</string> + <string name="menu_insert">Tilføj vært</string> + <string name="menu_delete">Fjern vært</string> + <string name="menu_preferences">Egenskaber</string> + <string name="help_intro">Vælg et emne nedenfor for yderligere information.</string> + <string name="help_about">Om ConnectBot</string> + <string name="help_keyboard">Tastatur</string> + <string name="pubkey_generate">Opret</string> + <string name="pubkey_import">Importér</string> + <string name="pubkey_delete">Slet nøgle</string> + <string name="pubkey_gather_entropy">Indsamler entropi</string> + <string name="pubkey_touch_prompt">Berør denne boks for at generere tilfældighed: %1$d%% færdig</string> + <string name="pubkey_touch_hint">For at garantere tilfældig data til oprettelse af nøglen, skal du flytte din finger tilfældigt indenfor boksen nedenfor.</string> + <string name="pubkey_generating">"Opretter nøglepar…"</string> + <string name="pubkey_copy_private">Kopier privat nøgle</string> + <string name="pubkey_copy_public">Kopier offentlig nøgle</string> + <string name="pubkey_list_empty">Tryk Menu for at oprette\nog importere nøglepar.</string> + <string name="pubkey_unknown_format">Ukendt format</string> + <string name="pubkey_change_password">Ændre adgangskode</string> + <string name="pubkey_list_pick">Vælg fra /sdcard</string> + <string name="pubkey_import_parse_problem">Fejl ved indlæsning af privat nøgle</string> + <string name="pubkey_unlock">Lås nøgle op</string> + <string name="pubkey_failed_add">Forkert adgangskode for nøglen \'%1$s\'. Autorisering mislykkedes.</string> + <string name="pubkey_memory_load">Indlæs i hukommelse</string> + <string name="pubkey_memory_unload">Fjern fra hukommelse</string> + <string name="pubkey_load_on_start">Indlæs nøgle ved start</string> + <string name="pubkey_confirm_use">Bekræft før brug</string> + <string name="portforward_list_empty">Tryk Menu for at oprette\nport-videresendelser.</string> + <string name="portforward_edit">Rediger port-videresendelse</string> + <string name="portforward_delete">Slet port-videresendelse</string> + <string name="prompt_nickname">Kaldenavn:</string> + <string name="prompt_nickname_hint_pubkey">Min arbejdsnøgle</string> + <string name="prompt_source_port">Kildeport:</string> + <string name="prompt_destination">Destination:</string> + <string name="prompt_old_password">Gammel adgangskode:</string> + <string name="prompt_password">Adgangskode:</string> + <string name="prompt_again">(igen)</string> + <string name="prompt_type">Type:</string> + <string name="prompt_password_can_be_blank">Bemærk: Adgangskoden kan være blank</string> + <string name="prompt_bits">Bit:</string> + <string name="prompt_pubkey_password">Adgangskode for nøglen \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Tillad fjernvært at\nbruge nøglen \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">ADVARSEL: FJERNVÆRTENS IDENTIFIKATION ER ÆNDRET!</string> + <string name="host_verification_failure_warning">DET ER MULIGT AT NOGEN FORETAGER SIG BESKIDTE HANDLINGER!\nDer er mulighed for at nogen aflytter dig (man-in-the-middle angreb)!\nDet er også muligt at værtens nøgle er blevet skiftet.</string> + <string name="prompt_host_disconnected">Værten har afbrudt forbindelsen.\nLuk session?</string> + <string name="prompt_continue_connecting">Er du sikker på at du ønsker\nat skabe forbindelse?</string> + <string name="host_authenticity_warning">Ægtheden for værten \'%1$s\' kan ikke påvises.</string> + <string name="host_fingerprint">%1$s nøgle fingeraftryk er %2$s</string> + <string name="alert_passwords_do_not_match_msg">Adgangskoderne er ikke ens!</string> + <string name="alert_wrong_password_msg">Forkert adgangskode!</string> + <string name="alert_key_corrupted_msg">Privat nøgle synes ødelagt!</string> + <string name="alert_sdcard_absent">SD-kort er ikke sat i!</string> + <string name="button_add">Tilføj</string> + <string name="button_change">Ændre</string> + <string name="button_generate">Opret nøgle</string> + <string name="button_resize">Ændre størrelse</string> + <string name="alert_disconnect_msg">Forbindelse tabt</string> + <string name="pref_emulation_category">Terminal emulering</string> + <string name="pref_emulation_title">Emulerings metode</string> + <string name="pref_emulation_summary">Terminal emulerings metode til brug ved PTY forbindelser</string> + <string name="pref_scrollback_title">Rul-tilbage buffer</string> + <string name="pref_scrollback_summary">Størrelsen af rul-tilbage bufferen for hver konsol</string> + <string name="pref_ui_category">Brugerflade</string> + <string name="pref_rotation_title">Rotations tilstand</string> + <string name="pref_rotation_summary">Hvordan skærmen roteres når keyboard skubbes ind/ud</string> + <string name="pref_fullscreen_title">Fuld skærm</string> + <string name="pref_fullscreen_summary">Skjul statusbar i konsol</string> + <string name="pref_memkeys_title">Husk nøgler i hukommelsen</string> + <string name="pref_memkeys_summary">Gem oplåste nøgler i hukommelsen indtil baggrunds servicen er afsluttet</string> + <string name="pref_update_title">Opdaterings tjek</string> + <string name="pref_update_summary">Maksimal tid mellem check for opdateringer til ConnectBot</string> + <string name="pref_conn_persist_title">Vedvarende forbindelser</string> + <string name="pref_conn_persist_summary">Tving forbindelser til at være aktive i baggrunden</string> + <string name="pref_keymode_title">Biblioteksgenveje</string> + <string name="pref_keymode_summary">Vælg hvordan Alt for \'/\' og Skift for Tabulater skal bruges</string> + <string name="pref_camera_title">Kamera genveje</string> + <string name="pref_camera_summary">Vælg genvej som kamera-knap skal aktivere</string> + <string name="pref_keepalive_title">Hold skærm tændt</string> + <string name="pref_keepalive_summary">Undgå skærm slukker når der arbejdes i en konsol</string> + <string name="pref_wifilock_title">Hold Wi-Fi aktiv</string> + <string name="pref_wifilock_summary">Undgå at Wi-Fi slår fra imens en session er aktiv</string> + <string name="pref_bumpyarrows_title">Vibrerende pile</string> + <string name="pref_bumpyarrows_summary">Vibrér når der afsendes piletaster fra trackballen; nyttig ved langsomme forbindelser</string> + <string name="pref_bell_category">Terminalklokke</string> + <string name="pref_bell_title">Hørbar klokke</string> + <string name="pref_bell_volume_title">Klokke volume</string> + <string name="pref_bell_vibrate_title">Vibrér når klokken ringer</string> + <string name="pref_bell_notification_title">Baggrundspåmindelser</string> + <string name="pref_bell_notification_summary">Send påmindelse når en terminal, der kører i baggrunden, ringer med klokken.</string> + <string name="list_keymode_right">Anvend taster på højre side</string> + <string name="list_keymode_left">Anvend taster på venstre side</string> + <string name="list_keymode_none">Slå fra</string> + <string name="list_pubkeyids_none">Brug ikke tasterne</string> + <string name="list_pubkeyids_any">Anvend enhver ulåst nøgle</string> + <string name="hostpref_nickname_title">Kaldenavn</string> + <string name="hostpref_color_title">Farvekategori</string> + <string name="hostpref_fontsize_title">Skriftstørrelse (pt)</string> + <string name="hostpref_pubkeyid_title">Brug offentlig nøgleautorisering</string> + <string name="hostpref_authagent_title">Brug SSH godkendelses klient</string> + <string name="hostpref_postlogin_title">Post-login automatik</string> + <string name="hostpref_postlogin_summary">Udfør kommandoer på fjernserveren efter autorisering</string> + <string name="hostpref_compression_title">Komprimering</string> + <string name="hostpref_compression_summary">Dette kan hjælpe på langsomme netværk</string> + <string name="hostpref_wantsession_title">Start konsol session</string> + <string name="hostpref_wantsession_summary">Deaktiver denne præference og brug kun port-videresendelser</string> + <string name="hostpref_stayconnected_title">Oprethold forbindelse</string> + <string name="hostpref_stayconnected_summary">Forbind igen hvis forbindelsen tabes</string> + <string name="hostpref_delkey_title">Slet tast</string> + <string name="hostpref_delkey_summary">Tast som sendes når slet tasten benyttes</string> + <string name="hostpref_encoding_title">Tekstkodning</string> + <string name="hostpref_encoding_summary">Tekstkodning for værten</string> + <string name="hostpref_connection_category">Forbindelsesindstillinger</string> + <string name="hostpref_username_title">Brugernavn</string> + <string name="hostpref_hostname_title">Vært</string> + <string name="hostpref_port_title">Port</string> + <string name="bind_never">Aldrig forbundet</string> + <string name="bind_minutes">%1$s minutter siden</string> + <string name="bind_hours">%1$s timer siden</string> + <string name="bind_days">%1$s dage siden</string> + <string name="console_copy_done">Kopier %1$d byte til udklipsholder</string> + <string name="console_copy_start">Berør og flyt\neller brug piletasterne\nfor at vælge område at kopiere</string> + <string name="console_menu_close">Luk</string> + <string name="console_menu_copy">Kopier</string> + <string name="console_menu_paste">Indsæt</string> + <string name="console_menu_portforwards">Port-videresendelser</string> + <string name="console_menu_resize">Tving størrelse</string> + <string name="console_menu_urlscan">URL skan</string> + <string name="button_yes">Ja</string> + <string name="button_no">Nej</string> + <string name="portforward_local">Lokal</string> + <string name="portforward_remote">Fjern</string> + <string name="portforward_dynamic">Dynamisk (SOCKS)</string> + <string name="portforward_pos">Opret port-videresendelse</string> + <string name="portforward_done">Port-videresendelse oprettet</string> + <string name="portforward_problem">Der opstod problemer ved oprettelsen af port-videresendelse. Måske bruger du en port lavere end 1025, eller en port som allerede er i brug.</string> + <string name="portforward_menu_add">Tilføj port-videresendelse</string> + <string name="hint_userhost">brugernavn\@vært</string> + <string name="list_format_error">Anvend formatet %1$s</string> + <string name="format_username">brugernavn</string> + <string name="format_hostname">værtsnavn</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Administrer offentlige nøgler</string> + <string name="list_menu_sortcolor">Sortér efter farve</string> + <string name="list_menu_sortname">Sortér efter navn</string> + <string name="list_menu_settings">Indstillinger</string> + <string name="list_host_disconnect">Afbryd forbindelse</string> + <string name="list_host_edit">Redigér vært</string> + <string name="list_host_portforwards">Redigér port-videresendelser</string> + <string name="list_host_delete">Slet vært</string> + <string name="list_host_empty">Anvend hurtig boksen nedenfor\nfor at oprette forbindelse\ntil en vært.</string> + <string name="list_rotation_default">Standard</string> + <string name="list_rotation_land">Fremtving liggende</string> + <string name="list_rotation_port">Fremtving stående</string> + <string name="list_rotation_auto">Automatisk</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A derefter mellemrum</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Ingen</string> + <string name="list_delkey_backspace">Slet tilbage</string> + <string name="list_delkey_del">Slet</string> + <string name="delete_message">Er du sikker på at du vil slette \'%1$s\'?</string> + <string name="delete_pos">Ja, slet</string> + <string name="delete_neg">Afbryd</string> + <string name="wizard_agree">Godkend</string> + <string name="wizard_next">Næste</string> + <string name="wizard_back">Tilbage</string> + <string name="terminal_no_hosts_connected">Ingen forbindelser aktive i øjeblikket</string> + <string name="terminal_connecting">Forbinder til %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">Verificeret vært \'%1$s\' nøgle: %2$s</string> + <string name="terminal_failed">Verifikation af værtsnøgle mislykkedes.</string> + <string name="terminal_using_s2c_algorithm">Server-til-klient algoritme: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Klient-til-server algoritme: %1$s %2$s</string> + <string name="terminal_using_algorithm">Bruger algoritme: %1$s %2$s</string> + <string name="terminal_auth">Forsøger at autorisere</string> + <string name="terminal_auth_pass">Forsøger adgangskode-autorisering</string> + <string name="terminal_auth_pass_fail">Autoriseringsmetoden adgangskode mislykkedes</string> + <string name="terminal_auth_pubkey_any">Forsøger \'publickey\'-autorisering med enhver offentlig nøgle i hukommelsen</string> + <string name="terminal_auth_pubkey_invalid">Valgte offentlige nøgle er ugyldig, prøv at vælge nøglen igen</string> + <string name="terminal_auth_pubkey_specific">Forsøger \'publickey\'-autorisering med valgte offentlige nøgle</string> + <string name="terminal_auth_pubkey_fail">Autentifikationsmetoden \'publickey\' med nøglen \'%1$s\' fejlede</string> + <string name="terminal_auth_ki">Forsøger \'keyboard-interactive\' autorisering</string> + <string name="terminal_auth_ki_fail">\'keyboard-interactive\'-autorisering fejlede</string> + <string name="terminal_auth_fail">[Din vært understøtter ikke \'password\' eller \'keyboard-interactive\' autorisering.]</string> + <string name="terminal_no_session">Sessionen kunne ikke startes pga. værtens preferencer</string> + <string name="terminal_enable_portfoward">Aktiver port-videresendelse: %1$s</string> + <string name="local_shell_unavailable">Fejl! Lokal konsol er ikke tilgængelig på denne telefon.</string> + <string name="notification_text">%1$s vil have din opmærksomhed.</string> + <string name="no">Nej</string> + <string name="with_confirmation">Med godkendelse</string> + <string name="yes">Ja</string> + <string name="exceptions_submit_message">ConnectBot havde tilsyneladende problemer sidste gang det blev brugt. Send fejlrapport til ConnectBot udviklerne?</string> + <string name="menu_colors_reset">Nulstil</string> + <string name="app_is_running">ConnectBot kører</string> + <string name="color_red">rød</string> + <string name="color_green">grøn</string> + <string name="color_blue">blå</string> + <string name="color_gray">grå</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-de/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,325 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Einfacher, mächtiger, open-source SSH client.</string> + <string name="service_desc">Hält SSH-Verbindungen und geladene öffentliche Schlüssel aufrecht</string> + <string name="auth_agent_service_desc">Handelt als SSH-Agent für andere Anwendungen am Gerät</string> + <string name="ssh_agent_permission_label">Im SSH-Agent gespeicherte Schlüssel verwenden</string> + <string name="ssh_agent_permission_desc">Erlaubt der Anwendung SSH-Transaktionen zu authentifizieren mit Ihren im ConnectBot gespeicherten Privatschlüsseln. + SEHR GEFÄHRLICH - kann von böswilligen Anwendungen mißbraucht werden.</string> + <string name="title_hosts_list">Hosts</string> + <string name="title_pubkey_list">Öffentliche Schlüssel</string> + <string name="title_port_forwards_list">Port-Weiterleitungen</string> + <string name="title_host_editor">Host bearbeiten</string> + <string name="title_help">Hilfe</string> + <string name="title_colors">Farben</string> + <string name="resolve_connect">Verbinden</string> + <string name="resolve_entropy">Sammle Entropie</string> + <string name="menu_insert">Host hinzufügen</string> + <string name="menu_delete">Host löschen</string> + <string name="menu_preferences">Einstellungen</string> + <string name="help_intro">Für mehr Informationen wählen Sie eine Überschrift!</string> + <string name="help_about">Über ConnectBot</string> + <string name="help_keyboard">Tastatur</string> + <string name="pubkey_generate">Erzeugen</string> + <string name="pubkey_import">Importieren</string> + <string name="pubkey_delete">Schlüssel löschen</string> + <string name="pubkey_gather_entropy">Sammle Entropie</string> + <string name="pubkey_touch_prompt">Berühren Sie diese Box, um Zufallszahlen zu erzeugen: %1$d%% fertig</string> + <string name="pubkey_touch_hint">Um eine gute Zufallsverteilung zu gewährleisten, bewegen Sie Ihren Finger zufällig über die Box unten!</string> + <string name="pubkey_generating">"Erzeuge Schlüsselpaar…"</string> + <string name="pubkey_copy_private">Privaten Schlüssel kopieren</string> + <string name="pubkey_copy_public">Öffentlichen Schlüssel kopieren</string> + <string name="pubkey_list_empty">\"Menu\" drücken, um Schlüsselpaare\nzu erzeugen oder zu importieren.</string> + <string name="pubkey_unknown_format">Unbekanntes Format</string> + <string name="pubkey_change_password">Passwort ändern</string> + <string name="pubkey_list_pick">Wähle von /sdcard</string> + <string name="pubkey_import_parse_problem">Fehler beim Parsen des importierten, geheimen Schlüssels</string> + <string name="pubkey_unlock">Schlüssel entsperren</string> + <string name="pubkey_failed_add">Falsches Passwort für Schlüssel \'%1$s\'. Legitimation fehlgeschlagen.</string> + <string name="pubkey_memory_load">In Speicher laden</string> + <string name="pubkey_memory_unload">Aus Speicher entfernen</string> + <string name="pubkey_load_on_start">Schlüssel beim Start laden</string> + <string name="pubkey_confirm_use">Bestätigen vor Benutzung</string> + <string name="portforward_list_empty">Auf \"Menu\" tippen um Port-\nWeiterleitungen zu erstellen.</string> + <string name="portforward_edit">Port-Weiterleitung bearbeiten.</string> + <string name="portforward_delete">Port-Weiterleitung löschen.</string> + <string name="prompt_nickname">Spitzname:</string> + <string name="prompt_nickname_hint_pubkey">Mein Schlüssel</string> + <string name="prompt_source_port">Quellport</string> + <string name="prompt_destination">Ziel:</string> + <string name="prompt_old_password">Altes Passwort:</string> + <string name="prompt_password">Passwort:</string> + <string name="prompt_again">(nochmal)</string> + <string name="prompt_type">Typ:</string> + <string name="prompt_password_can_be_blank">Hinweis: Passwort kann leer bleiben</string> + <string name="prompt_bits">Bits:</string> + <string name="prompt_pubkey_password">Passwort für Schlüssel \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Remote Host die Benutzung\ndes Schlüssels \'%1$s\' erlauben?</string> + <string name="host_verification_failure_warning_header">WARNUNG: IDENTIFIKATION DES ENTFERNTEN HOSTS HAT SICH GEÄNDERT!</string> + <string name="host_verification_failure_warning">MÖGLICHERWEISE TUT JEMAND ETWAS BÖSES!\nJemand könnte Sie jetzt gerade belauschen (man-in-the-middle attack)!\nEs ist auch möglich, dass nur der Host-Key geändert wurde.</string> + <string name="prompt_host_disconnected">Der Host hat die Verbindung beendet.\nSitzung schließen?</string> + <string name="prompt_continue_connecting">Sind Sie sicher, dass Sie\neine Verbindung herstellen wollen?</string> + <string name="host_authenticity_warning">Die Authentizität von Host \'%1$s\' kann nicht garantiert werden.</string> + <string name="host_fingerprint">Host %1$ss Schlüssel Fingerabdruck ist %2$s</string> + <string name="alert_passwords_do_not_match_msg">Passwörter stimmen nicht überein!</string> + <string name="alert_wrong_password_msg">Falsches Passwort!</string> + <string name="alert_key_corrupted_msg">Geheimer Schlüssel scheint korrupt!</string> + <string name="alert_sdcard_absent">SD-Karte nicht eingesteckt!</string> + <string name="button_add">Hinzufügen</string> + <string name="button_change">Ändern</string> + <string name="button_generate">Schlüssel erzeugen</string> + <string name="button_resize">Größe ändern</string> + <string name="button_resize_reset">Standardgröße</string> + <string name="alert_disconnect_msg">Die Verbindung wurde getrennt.</string> + <string name="pref_emulation_category">Terminalemulation</string> + <string name="pref_emulation_title">Emulationsmodus</string> + <string name="pref_emulation_summary">Terminalemulationsmodus für PTY Verbindungen</string> + <string name="pref_scrollback_title">Bildlaufpuffergröße</string> + <string name="pref_scrollback_summary">Größe des Bildlaufpuffers, der für jede Konsole im Speicher gehalten wird</string> + <string name="pref_ui_category">Benutzungsschnittstelle</string> + <string name="pref_rotation_title">Rotationsmodus</string> + <string name="pref_rotation_summary">Wie soll die Rotation beim Ein-/Ausklappen der Tastatur verändert werden</string> + <string name="pref_memkeys_title">Schlüssel im Speicher behalten</string> + <string name="pref_memkeys_summary">Entsperrte Schlüssel im Speicher halten, bis der Hintergrunddienst beendet wurde</string> + <string name="pref_update_title">Aktualisierungen suchen</string> + <string name="pref_update_summary">Die maximale Frequenz einstellen, mit der nach ConnectBot Aktualisierungen gesucht werden soll</string> + <string name="pref_conn_persist_title">Persistente Verbindungen</string> + <string name="pref_conn_persist_summary">Erhalte Verbindungen auch im Hintergrund</string> + <string name="pref_keymode_title">Verzeichniskürzel</string> + <string name="pref_keymode_summary">Einstellen, wie Alt für \'/\' und Hochstellen für \'Tab\' verwendet werden sollen</string> + <string name="pref_camera_title">Kamerataste</string> + <string name="pref_camera_summary">Aktion, die beim Drücken der Kamera-Taste ausgeführt wird</string> + <string name="pref_volup_title">Lauter-Taste</string> + <string name="pref_volup_summary">Aktion, die beim Drücken der Lauter-Taste ausgeführt wird</string> + <string name="pref_voldn_title">Leiser-Taste</string> + <string name="pref_voldn_summary">Aktion, die beim Drücken der Leiser-Taste ausgeführt wird</string> + <string name="pref_search_title">Suchtaste</string> + <string name="pref_search_summary">Aktion, die beim Drücken der Suchtaste ausgeführt wird</string> + <string name="pref_keepalive_title">Bildschirm anlassen</string> + <string name="pref_keepalive_summary">Verhindern, dass beim Arbeiten an der Konsole der Bildschirm abgeschaltet wird</string> + <string name="pref_wifilock_title">WLAN aktiviert lassen</string> + <string name="pref_wifilock_summary">Verhindern, dass während einer aktiven Sitzung WLAN deaktiviert wird</string> + <string name="pref_bumpyarrows_title">Vibrierende Pfeiltasten</string> + <string name="pref_bumpyarrows_summary">Vibirieren, wenn Pfeiltasten vom Trackball gesendet werden; nützlich bei laggenden Verbindungen</string> + <string name="pref_bell_category">Terminalglocke</string> + <string name="pref_bell_title">Hörbare Glocke</string> + <string name="pref_bell_volume_title">Glockenlautstärke</string> + <string name="pref_bell_vibrate_title">Bei Glocke vibrieren</string> + <string name="pref_bell_notification_title">Hintergrundnotiz</string> + <string name="pref_bell_notification_summary">Benachrichtigen, wenn ein im Hintergrund laufendendes Terminal eine Glocke erklingen lässt.</string> + <string name="list_keymode_right">Tasten rechts verwenden</string> + <string name="list_keymode_left">Tasten links verwenden</string> + <string name="list_keymode_none">Ausschalten</string> + <string name="list_pubkeyids_none">Keine Schlüssel verwenden</string> + <string name="list_pubkeyids_any">Beliebigen entsperrten Schlüssel verwenden</string> + <string name="hostpref_nickname_title">Nutzername</string> + <string name="hostpref_color_title">Farbkategorie</string> + <string name="hostpref_fontsize_title">Fontgröße (pt)</string> + <string name="hostpref_pubkeyid_title">Verwende pubkey Authentisierung</string> + <string name="hostpref_authagent_title">SSH auth agent benutzen?</string> + <string name="hostpref_postlogin_title">Post-Login Automatisierung</string> + <string name="hostpref_postlogin_summary">Befehle, die auf dem entfernten Host nach der Anmeldung gestartet werden sollen.</string> + <string name="hostpref_compression_title">Kompression</string> + <string name="hostpref_compression_summary">Dies könnte bei langsamen Netzwerken helfen</string> + <string name="hostpref_wantsession_title">Kommandozeilensitzung starten</string> + <string name="hostpref_wantsession_summary">Diese Einstellung abwählen, um ausschließlich Port-Weiterleitungen zu verwenden</string> + <string name="hostpref_stayconnected_title">Verbindung halten</string> + <string name="hostpref_stayconnected_summary">Verbindung bei Verbindungsabbruch wiederherstellen</string> + <string name="hostpref_delkey_title">DEL Taste</string> + <string name="hostpref_delkey_summary">Zu sendender Tastencode wenn DEL gedrückt wird</string> + <string name="hostpref_encoding_title">Zeichensatz</string> + <string name="hostpref_encoding_summary">Zeichen-Encoding für den Host</string> + <string name="hostpref_connection_category">Verbindungseinstellungen</string> + <string name="hostpref_username_title">Benutzername</string> + <string name="hostpref_hostname_title">Host</string> + <string name="hostpref_port_title">Port</string> + <string name="hostpref_x11_forwarding">"X11-Weiterleitung"</string> + <string name="hostpref_wantx11forward_title">"X11-Weiterleitung aktivieren"</string> + <string name="hostpref_wantx11forward_summary">"X11-Sitzungen an unten angegebenen Host und Port weiterleiten"</string> + <string name="hostpref_x11host_title">"Host für X11-Weiterleitung"</string> + <string name="hostpref_x11port_title">"Port für X11-Weiterleitung"</string> + <string name="bind_never">Nie verbunden</string> + <string name="bind_minutes">vor %1$s Minuten</string> + <string name="bind_hours">vor %1$s Stunden</string> + <string name="bind_days">vor %1$s Tagen</string> + <string name="console_copy_done">%1$d Byte in die Zwischenablage kopiert</string> + <string name="console_copy_start">Berühren und ziehen\noder Trackball verwenden\num zu kopierenden Bereich auszuwählen</string> + <string name="console_menu_close">Schließen</string> + <string name="console_menu_copy">Kopieren</string> + <string name="console_menu_paste">Einfügen</string> + <string name="console_menu_portforwards">Port-Weiterleitungen</string> + <string name="console_menu_resize">Größe erzwingen</string> + <string name="console_menu_urlscan">URL Scan</string> + <string name="console_menu_screencapture">Bildschirmfoto</string> + <string name="console_menu_download">"Datei herunterladen"</string> + <string name="console_menu_upload">"Datei hochladen"</string> + <string name="button_yes">Ja</string> + <string name="button_no">Nein</string> + <string name="portforward_local">Lokal</string> + <string name="portforward_remote">Entfernt</string> + <string name="portforward_dynamic">Dynamisch (SOCKS)</string> + <string name="portforward_pos">Port-Weiterleitung anlegen</string> + <string name="portforward_done">Port-Weiterleitung angelegt.</string> + <string name="portforward_problem">Konnte Port-Weiterleitung nicht anlegen. Verwenden Sie Ports kleiner als 1024, oder wird der Port bereits verwendet?</string> + <string name="portforward_menu_add">Port-Weiterleitung hinzufügen</string> + <string name="hint_userhost">benutzer\@host</string> + <string name="list_format_error">Benutze das Format %1$s</string> + <string name="format_username">Benutzer</string> + <string name="format_hostname">Host</string> + <string name="format_port">Port</string> + <string name="list_menu_pubkeys">Pubkeys verwalten</string> + <string name="list_menu_sortcolor">Nach Farbe sortieren</string> + <string name="list_menu_sortname">Nach Name sortieren</string> + <string name="list_menu_settings">Einstellungen</string> + <string name="list_host_disconnect">Verbindung trennen</string> + <string name="list_host_edit">Host editieren</string> + <string name="list_host_portforwards">Port-Weiterleitungen editieren</string> + <string name="list_host_delete">Host löschen</string> + <string name="list_host_empty">Benutzen Sie die quick-connect box\nunten um sich mit einem Host zu verbinden.</string> + <string name="list_rotation_default">Vorgabe</string> + <string name="list_rotation_land">Querformat erzwingen</string> + <string name="list_rotation_port">Hochformat erzwingen</string> + <string name="list_rotation_auto">Automatisch</string> + <string name="list_hwbutton_screen_capture">Screenshot</string> + <string name="list_hwbutton_ctrl">CTRL</string> + <string name="list_hwbutton_tab">Tab</string> + <string name="list_hwbutton_ctrlaspace">Strg+A dann Space</string> + <string name="list_hwbutton_ctrla">Strg+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Nichts</string> + <string name="list_delkey_backspace">Rücktaste</string> + <string name="list_delkey_del">Entfernen</string> + <string name="delete_message">Soll \'%1$s\' wirklich gelöscht werden?</string> + <string name="delete_pos">Ja, löschen</string> + <string name="delete_neg">Abbrechen</string> + <string name="wizard_agree">Zustimmung</string> + <string name="wizard_next">Weiter</string> + <string name="wizard_back">Zurück</string> + <string name="terminal_no_hosts_connected">Zur Zeit keine Hosts verbunden</string> + <string name="terminal_connecting">Verbinde mit %1$s:%2$d mittels %3$s</string> + <string name="terminal_sucess">Host \'%1$s\' Schlüssel: %2$s bestätigt</string> + <string name="terminal_failed">Überprüfung des Host-Schlüssels fehlgeschlagen.</string> + <string name="terminal_using_s2c_algorithm">Server zu Client Algorithmus: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Client zu Server Algorithmus: %1$s %2$s</string> + <string name="terminal_using_algorithm">Benutze Algorithmus: %1$s %2$s</string> + <string name="terminal_auth">Versuche zu authentisieren.</string> + <string name="terminal_auth_pass">Versuche Authentisierung mit Passwort.</string> + <string name="terminal_auth_pass_fail">Authentisierungsmethode \'Passwort\' fehlgeschlagen.</string> + <string name="terminal_auth_pubkey_any">Versuche Public Key Authentisierung mit allen öffentlichen Schlüsseln im Speicher</string> + <string name="terminal_auth_pubkey_invalid">Der ausgewählte öffentliche Schlüssel ist ungültig, versuchen Sie den Schlüssel im Host-Editor neu auszuwählen</string> + <string name="terminal_auth_pubkey_specific">Versuche Public Key Authentisierung mit einem bestimmten öffentlichen Schlüssel</string> + <string name="terminal_auth_pubkey_fail">Authentifizierungs Methode \'publickey\' mit Schlüssel \'%1$s\' fehlgeschlagen</string> + <string name="terminal_auth_ki">Versuche \'keyboard-interactive\' Authentisierung.</string> + <string name="terminal_auth_ki_fail">Authentisierungsmethode \'keyboard-interactive\' fehlgeschlagen</string> + <string name="terminal_auth_fail">[Ihr Host unterstützt weder \'password\' noch \'keyboard-interactive\' Authentisierung.]</string> + <string name="terminal_no_session">Sitzung wird wegen Host Präferenz nicht gestartet</string> + <string name="terminal_enable_portfoward">Aktiviere Port Forwarding: %1$s</string> + <string name="local_shell_unavailable">Fehler! Lokale Kommandozeile ist auf diesem Telefon nicht verfügbar.</string> + <string name="notification_text">%1$s will ihre Aufmerksamkeit.</string> + <string name="no">Nein</string> + <string name="with_confirmation">Mit Bestätigung</string> + <string name="yes">Ja</string> + <string name="exceptions_submit_message">Scheinbar hatte ConnectBot Probleme bei der letzten Benutzung. Fehlermeldung an die ConnectBot übermitteln?</string> + <string name="menu_colors_reset">Zurücksetzen</string> + <string name="app_is_running">ConnectBot läuft</string> + <string name="color_red">rot</string> + <string name="color_green">grün</string> + <string name="color_blue">blau</string> + <string name="color_gray">grau</string> + <string name="colors_fg">Schriftfarbe:</string> + <string name="color_bg">Hintergrundfarbe:</string> + <string name="image_description_connected">Verbunden.</string> + <string name="image_description_key_is_locked">Schlüssel ist gesperrt.</string> + <string name="image_description_toggle_control_character">Steuerzeichen umschalten</string> + <string name="image_description_send_escape_character">Escape-Zeichen senden.</string> + <string name="image_description_show_keyboard">Tastatur anzeigen.</string> + <string name="button_close">Schließen</string> + <string name="pref_custom_keymap_title">Angepasstes Tastaturlayout</string> + <string name="pref_custom_keymap_summary">Umleitung von bestimmten Tasten auf unterstützten Geräten</string> + <string name="pref_custom_keymap_full">vollständige Tastatur</string> + <string name="pref_custom_keymap_disabled">deaktiviert</string> + <string name="resize_error_title">Fehler bei Änderung der Bildschirmgröße</string> + <string name="resize_error_width_height">Länge und Breite müssen größer als 0 sein</string> + <string name="pref_screen_capture_category">Screenshot</string> + <string name="pref_screen_capture_folder">Pfad für Screenshots</string> + <string name="pref_screen_capture_folder_summary">Ordner für das Speichern von Screenshots</string> + <string name="pref_screen_capture_popup">Benachrichtigung beim Screenshot</string> + <string name="pref_screen_capture_popup_summary">Ein Pop-Up-Fenster nach Erstellung eines Screenshots anzeigen</string> + <string name="screen_capture">Screenshot</string> + <string name="screenshot_success_title">Screenshot erfolgreich</string> + <string name="screenshot_saved_as">Screenshot wurde gespeichert als</string> + <string name="screenshot_error_title">Fehler beim Screenshot</string> + <string name="screenshot_not_saved_as">Screenshot konnte nicht gespeichert werden als</string> + <string name="pref_picker_string">Inhalt des Sym-Fensters</string> + <string name="pref_picker_string_summary">Zeichenkette für das Zeichenwahl-Dialogfenster</string> + <string name="pref_picker_keep_open">Sym-Fenster offen halten</string> + <string name="pref_picker_keep_open_summary">Nur der Abbrechen-Knopf schließt das Zeichenwahl-Dialogfenster</string> + <string name="pref_file_transfer_category">Übertragung von Dateien</string> + <string name="pref_file_dialog_title">Dateiauswahl</string> + <string name="pref_file_dialog_summary">Formular zur Auswahl von Dateien und Verzeichnissen</string> + <string name="pref_file_dialog_builtin">eingebaut</string> + <string name="error_starting_app">Fehler beim Ausführen von %1$s</string> + <string name="file_chooser_select_file">Datei %1s auswählen</string> + <string name="select_for_download">fürs Herunterladen</string> + <string name="select_for_upload">fürs Hochladen</string> + <string name="select_for_key_import">für den Schlüssel-Import</string> + <string name="location">Position</string> + <string name="cant_read_folder">Fehler beim lesen des Verzeichnisses.</string> + <string name="nnew">Neu</string> + <string name="select">Auswählen</string> + <string name="file_name">Dateiname:</string> + <string name="cancel">Abbrechen</string> + <string name="save">Speichern</string> + <string name="new_file">Neue Datei</string> + <string name="no_data">Keine Daten</string> + <string name="pref_download_folder">Download-Verzeichnis</string> + <string name="pref_download_folder_summary">Pfad zum Speichern von heruntergeladenen Dateien</string> + <string name="pref_remote_upload_folder">Upload-Verzeichnis</string> + <string name="pref_remote_upload_folder_summary">Server-Pfad für das Hochladen von Dateien</string> + <string name="pref_upload_dest_prompt">Upload-Ziel abfragen</string> + <string name="pref_upload_dest_prompt_summary">Zielpfad für Dateiuploads abfragen</string> + <string name="pref_background_file_transfer">Hintergrundübertragung von Dateien</string> + <string name="pref_background_file_transfer_summary">Das Herunterladen und Hochladen von Dateien im Hintergrund ausführen</string> + <string name="transfer_downloading">"Herunterladen von Dateien…"</string> + <string name="transfer_downloading_file">Lade herunter: %1$s</string> + <string name="transfer_download_complete">Herunterladen abgeschlossen</string> + <string name="transfer_download_failed">Fehler beim Herunterladen: %1$s</string> + <string name="transfer_select_remote_download_title">Datei(en) herunterladen</string> + <string name="transfer_select_remote_download_desc">Pfade der herunterzuladenden entfernten Dateien eintragen (zeilenweise)</string> + <string name="transfer_select_remote_upload_dest_title">Zielpfad für Upload</string> + <string name="transfer_select_remote_upload_dest_desc">Gewünschter Server-Pfad für:</string> + <string name="transfer_button_download">Herunterladen</string> + <string name="transfer_button_upload">Hochladen</string> + <string name="transfer_uploading">"Hochladen von Dateien…"</string> + <string name="transfer_uploading_file">Lade hoch: %1$s</string> + <string name="transfer_upload_complete">Hochladen abgeschlossen</string> + <string name="transfer_upload_failed">Fehler beim Hochladen:%1$s</string> + <string name="pubkey_export_private">"Privaten Schlüssel exportieren"</string> + <string name="pubkey_export_public">"Öffentlichen Schlüssel exportieren"</string> + <string name="pubkey_public_save_as">Öffentlichen Schlüssel speichern</string> + <string name="pubkey_public_save_as_desc">Dateiname (volständiger Pfad) zum Speichern des öffentlichen Schlüssels</string> + <string name="pubkey_private_save_as">Privaten Schlüssel speichern</string> + <string name="pubkey_private_save_as_desc">Dateiname (volständiger Pfad) zum Speichern des privaten Schlüssels</string> + <string name="pubkey_public_export_success">Öffentlicher Schlüssel gespeichert als %1$s</string> + <string name="pubkey_public_export_problem">Fehler beim Export des öffentlichen Schlüssels</string> + <string name="pubkey_private_export_success">Privater Schlüssel gespeichert als %1$s</string> + <string name="pubkey_private_export_problem">Fehler beim Export des privaten Schlüssels</string> + <string name="pref_debug_category">Entwickler-Einstellungen</string> + <string name="pref_debug_keycodes">Tastencodes anzeigen</string> + <string name="pref_debug_keycodes_summary">Codes der im Terminal gedrückten Tasten anzeigen</string> + <string name="keycode_pressed">Code der gedrückten Taste</string> + <string name="pref_extended_longpress">Erweitertes Longpress-Menu</string> + <string name="pref_extended_longpress_summary">Eingabeoptionen im Tap-And-Hold-Menü anzeigen</string> + <string name="longpress_select_action">Aktion auswählen</string> + <string name="longpress_enable_full_screen_mode">Vollbildmodus aktivieren</string> + <string name="longpress_disable_full_screen_mode">Vollbildmodus deaktivieren</string> + <string name="longpress_change_font_size">Fontgröße ändern</string> + <string name="longpress_arrows_dialog">Pfeiltaste</string> + <string name="longpress_fkeys_dialog">Funktionstasten</string> + <string name="longpress_ctrl_dialog">CTRL+?</string> + <string name="longpress_sym_dialog">Zeichenwahl</string> + <string name="pref_ctrl_string">Inhalt des Ctrl-Fensters</string> + <string name="pref_ctrl_string_summary">Zeichenkette für die CTRL+? kombination</string> + <string name="fullscreen">Vollbild</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-el/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title_help">Βοήθεια</string> + <string name="title_colors">Χρώματα</string> + <string name="resolve_connect">Σύνδεση</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-en-rCA/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title_colors">Colours</string> + <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> + <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> + <string name="hostpref_color_title">Colour category</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="list_menu_sortcolor">Sort by colour</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-en-rGB/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * Copyright 2011 Darren Salt + * + * This file is derived from res/values/strings.xml + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="title_colors">"Colours"</string> + <string name="hostpref_color_title">"Colour category"</string> + <string name="list_menu_sortcolor">"Sort by colour"</string> + <string name="color_gray">"grey"</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-es/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,212 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Cliente de SSH sencillo, potente y open-source</string> + <string name="service_desc">Mantiene conexiones SSH y las claves públicas guardadas</string> + <string name="title_hosts_list">Máquinas</string> + <string name="title_pubkey_list">Claves Publicas</string> + <string name="title_port_forwards_list">Traducciones de puerto</string> + <string name="title_host_editor">Editar equipo remoto</string> + <string name="title_help">Ayuda</string> + <string name="title_colors">Colores</string> + <string name="resolve_connect">Conectar</string> + <string name="resolve_entropy">Recolectar entropía</string> + <string name="menu_insert">Añadir equipo remoto</string> + <string name="menu_delete">Eliminar máquina</string> + <string name="menu_preferences">Configuración</string> + <string name="help_intro">Por favor seleccione un tema a continuación para más información sobre una materia en particular.</string> + <string name="help_about">Acerca de ConnectBot</string> + <string name="help_keyboard">Teclado</string> + <string name="pubkey_generate">Generar</string> + <string name="pubkey_import">Importar</string> + <string name="pubkey_delete">Eliminar clave</string> + <string name="pubkey_gather_entropy">Haciendo acopio de entropía</string> + <string name="pubkey_touch_prompt">Toque esta caja para conseguir aleatoriedad: %1$d%% hecho</string> + <string name="pubkey_touch_hint">Para poder conseguir aleatoriedad durante la generacion de la clave, mueva su dedo aleatoriamente sobre la caja a continuación.</string> + <string name="pubkey_generating">Generar llavero de claves</string> + <string name="pubkey_copy_private">Copiar clave privada</string> + <string name="pubkey_copy_public">Copiar clave pública</string> + <string name="pubkey_list_empty">Presione menu para crear\nó importar un llavero de claves</string> + <string name="pubkey_unknown_format">Formato desconocido</string> + <string name="pubkey_change_password">Cambiar contraseña</string> + <string name="pubkey_list_pick">Escoger desde la tarjeta sd</string> + <string name="pubkey_import_parse_problem">Problema analizando clave privada importada</string> + <string name="pubkey_unlock">Desbloquear clave</string> + <string name="pubkey_failed_add">Contraseña incorrecta para la clave \'%1$s\'. Autenticación fallida.</string> + <string name="pubkey_memory_load">Cargar en memoria</string> + <string name="pubkey_memory_unload">Descargar de memoria</string> + <string name="pubkey_load_on_start">Cargar clave al inicio</string> + <string name="pubkey_confirm_use">Confirme antes de usar</string> + <string name="portforward_list_empty">Presione Menu para crear\nó importar redireccionamientos.</string> + <string name="portforward_edit">Editar redireccionamiento de puerto</string> + <string name="portforward_delete">Eliminar redireccionamiento de puerto</string> + <string name="prompt_nickname">Nombre de usuario:</string> + <string name="prompt_nickname_hint_pubkey">Mi clave de trabajo</string> + <string name="prompt_source_port">Puerto fuente:</string> + <string name="prompt_destination">Destino:</string> + <string name="prompt_old_password">Contraseña antigua:</string> + <string name="prompt_password">Contraseña:</string> + <string name="prompt_again">(de nuevo)</string> + <string name="prompt_type">Tipo:</string> + <string name="prompt_password_can_be_blank">Nota: la contraseña puede ser dejada en blanco</string> + <string name="prompt_bits">Bits:</string> + <string name="prompt_pubkey_password">Contraseña para clave \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">¿Autorizar maquina remota\nde usar clave \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">ATENCIÓN: ¡LA IDENTIFICACIÓN DE LA MAQUINA REMOTA HA CAMBIADO!</string> + <string name="host_verification_failure_warning">¡ES POSIBLE QUE ALGUIEN ESTE HACIENDO ALGO INAPROPIADO!\nAlguien puede estar interviniendo en estos momentos (ataque man-in-the-middle)!\nTambién es posible que la clave haya sido cambiada.</string> + <string name="prompt_host_disconnected">La máquina ha sido desconectada.\n¿Desea cerrar sesión?</string> + <string name="prompt_continue_connecting">¿Esta seguro de que desea\nseguir conectándose?</string> + <string name="host_authenticity_warning">La autenticidad de la máquina \'%1$s\' no puede ser establecida.</string> + <string name="host_fingerprint">La clave huella de la maquina %1$s es %2$s</string> + <string name="alert_passwords_do_not_match_msg">¡Las contraseñas no coinciden!</string> + <string name="alert_wrong_password_msg">¡Contraseña errónea!</string> + <string name="alert_key_corrupted_msg">¡La clave privada parece corrupta!</string> + <string name="alert_sdcard_absent">¡Tarjeta SD no insertada!</string> + <string name="button_add">Añadir</string> + <string name="button_change">Modificar</string> + <string name="button_generate">Generar clave</string> + <string name="button_resize">Redimensionar</string> + <string name="alert_disconnect_msg">Conexión perdida</string> + <string name="pref_emulation_category">Emulación del terminal</string> + <string name="pref_emulation_title">Modo emulación</string> + <string name="pref_emulation_summary">Modo emulación para usar en conexiones PTY</string> + <string name="pref_scrollback_title">Tamaño de navegación</string> + <string name="pref_scrollback_summary">Tamaño de búfer que quedara en memoria para cada consola.</string> + <string name="pref_ui_category">Interfaz de usuario</string> + <string name="pref_rotation_title">Modo de rotación</string> + <string name="pref_rotation_summary">Como cambiar la rotación cuando se abra el teclado.</string> + <string name="pref_fullscreen_title">Pantalla completa</string> + <string name="pref_fullscreen_summary">Esconder barra de estatus cuando este en consola</string> + <string name="pref_memkeys_title">Recordar claves en memoria</string> + <string name="pref_memkeys_summary">Recordar claves en memoria hasta que el servicio en segundo plano termine</string> + <string name="pref_update_title">Revisar por actualizaciones</string> + <string name="pref_update_summary">Establecer la frequencia maxima para revisar actualizaciones de ConnectBot</string> + <string name="pref_conn_persist_title">Conexiones persistentes</string> + <string name="pref_conn_persist_summary">Mantener conexiones activas en segundo plano</string> + <string name="pref_keymode_title">Secuencia de teclas para directorios</string> + <string name="pref_keymode_summary">Especifique como usar Alt para \'/\' y Shit para Tab</string> + <string name="pref_camera_title">Boton de la Cámara</string> + <string name="pref_camera_summary">Especifique que secuencia de teclas activar cuando presione el botón de la cámara</string> + <string name="pref_keepalive_title">Mantener pantalla activa</string> + <string name="pref_keepalive_summary">Prevenir que se apague la pantalla cuando se este trabajando en consola</string> + <string name="pref_wifilock_title">Mantener la red inálambrica activa</string> + <string name="pref_wifilock_summary">Prevenir que la red inálambrica se apague mientras haya una conexión activa</string> + <string name="pref_bumpyarrows_title">Cursor con vibración</string> + <string name="pref_bumpyarrows_summary">Vibrar al recibir las teclas del cursor desde el trackball; útil para conexiones con retardos</string> + <string name="pref_bell_category">Timbre del terminal</string> + <string name="pref_bell_title">Timbre audible</string> + <string name="pref_bell_volume_title">Volúmen del timbre</string> + <string name="pref_bell_vibrate_title">Vibrar con el timbre</string> + <string name="pref_bell_notification_title">Notificaciones de fondo</string> + <string name="pref_bell_notification_summary">Activar notificacion cuando algun terminal corriendo en el fondo active un timbre</string> + <string name="list_keymode_right">Usar teclas del lado derecho</string> + <string name="list_keymode_left">Usar teclas del lado izquierdo</string> + <string name="list_keymode_none">Desactivar</string> + <string name="list_pubkeyids_none">No usar teclas</string> + <string name="list_pubkeyids_any">Utilizar cualquier clave desbloqueada</string> + <string name="hostpref_nickname_title">Apodo</string> + <string name="hostpref_color_title">Categoria de colores</string> + <string name="hostpref_fontsize_title">Tamaño de la fuente (pt)</string> + <string name="hostpref_pubkeyid_title">Usar clave de autenticación pública</string> + <string name="hostpref_authagent_title">Utilizar agente de autenticación SSH</string> + <string name="hostpref_postlogin_title">Inicio de sesión después de la automatización</string> + <string name="hostpref_postlogin_summary">Comandos para ejecutar en el servidor remoto, una vez autenticado</string> + <string name="hostpref_compression_title">Compresión</string> + <string name="hostpref_compression_summary">Esto puede ayudar con las redes más lentas</string> + <string name="hostpref_wantsession_title">Inciar sesión en shell</string> + <string name="hostpref_wantsession_summary">Desactive esta preferencia para usar sólo reenvíos por puerto</string> + <string name="hostpref_stayconnected_title">Mantenerse conectado</string> + <string name="hostpref_stayconnected_summary">Intentar reconectar al equipo si se desconecta</string> + <string name="hostpref_delkey_title">Tecla DEL</string> + <string name="hostpref_delkey_summary">El código clave que se envía cuando se pulsa tecla DEL</string> + <string name="hostpref_encoding_title">Codificando</string> + <string name="hostpref_encoding_summary">Codificación de caracteres para la maquina</string> + <string name="hostpref_connection_category">Opciones de Conexión</string> + <string name="hostpref_username_title">Nombre de usuario</string> + <string name="hostpref_hostname_title">Host (equipo anfitrión)</string> + <string name="hostpref_port_title">Puerto</string> + <string name="bind_never">Nunca fué conectado</string> + <string name="bind_minutes">Hace %1$s minutos</string> + <string name="bind_hours">Hace %1$s horas</string> + <string name="bind_days">Hace %1$s días</string> + <string name="console_copy_done">%1$d bytes copiados al portapaleles</string> + <string name="console_copy_start">Toque y arrastre\no use la almohadilla direccional\npara seleccionar la zona a copiar</string> + <string name="console_menu_close">Cerrar</string> + <string name="console_menu_copy">Copiar</string> + <string name="console_menu_paste">Pegar</string> + <string name="console_menu_portforwards">Traducciones de puerto</string> + <string name="console_menu_resize">Forzar un tamaño</string> + <string name="console_menu_urlscan">Escaneo de direcciones</string> + <string name="button_yes">Sí</string> + <string name="button_no">Denegar</string> + <string name="portforward_local">Local</string> + <string name="portforward_remote">Remoto</string> + <string name="portforward_dynamic">Dinámicos (SOCKS)</string> + <string name="portforward_pos">Crear reenvio de puerto</string> + <string name="portforward_done">Creacion satisfactoria del reenvio de puerto</string> + <string name="portforward_problem">Problema al crear el puerto de reenvio, tal vez usted está usando puertos menores de 1024 o el puerto ya está siendo utilizado?</string> + <string name="portforward_menu_add">Añadir redirección de puertos</string> + <string name="hint_userhost">usuario\@equipo</string> + <string name="list_format_error">Usar formato %1$s</string> + <string name="format_username">Usuario</string> + <string name="format_hostname">nombre del host</string> + <string name="format_port">puerto</string> + <string name="list_menu_pubkeys">Administrar clave públicas</string> + <string name="list_menu_sortcolor">Ordenar por color</string> + <string name="list_menu_sortname">Ordenar por nombre</string> + <string name="list_menu_settings">Configuración</string> + <string name="list_host_disconnect">Desconectar</string> + <string name="list_host_edit">Editar equipo</string> + <string name="list_host_portforwards">Editar redirección de puertos</string> + <string name="list_host_delete">Eliminar equipo</string> + <string name="list_host_empty">Usar la casilla de conexión rápida\na continuación para conectarse a una máquina</string> + <string name="list_rotation_default">Predeterminado</string> + <string name="list_rotation_land">Forzar paisaje</string> + <string name="list_rotation_port">Forzar retrato</string> + <string name="list_rotation_auto">Automático</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A después espacio</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Ninguno</string> + <string name="list_delkey_backspace">Borrar</string> + <string name="list_delkey_del">Eliminar</string> + <string name="delete_message">¿Está seguro de que quiere eliminar \'%1$s\'?</string> + <string name="delete_pos">Sí, eliminar</string> + <string name="delete_neg">Cancelar</string> + <string name="wizard_agree">De acuerdo</string> + <string name="wizard_next">Siguiente</string> + <string name="wizard_back">Atrás</string> + <string name="terminal_no_hosts_connected">No hay equipos conectados ahora</string> + <string name="terminal_connecting">Canectando a %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">Host (equipo anfitrion) \'%1$s\' clave: %2$s verifiado.</string> + <string name="terminal_failed">Verificación del host (equipo anfitrion) fallida</string> + <string name="terminal_using_s2c_algorithm">Algoritmo servidor-cliente: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algoritmo cliente-servidor: %1$s %2$s</string> + <string name="terminal_using_algorithm">Algoritmo que se esta usando: %1$s %2$s</string> + <string name="terminal_auth">Intentando autenticar</string> + <string name="terminal_auth_pass">Intentando autenticación de la contraseña</string> + <string name="terminal_auth_pass_fail">Método de autenticación \'password\' fallido</string> + <string name="terminal_auth_pubkey_any">Intentando autenticacion de la clave pública usando las claves públicas en memoria</string> + <string name="terminal_auth_pubkey_invalid">La clave pública selecciona es invalida, intenta reseleccional la clave en el editor de host (equipo anfitrion)</string> + <string name="terminal_auth_pubkey_specific">Intentar autenticación de la clave pública con una clave pública determinada</string> + <string name="terminal_auth_pubkey_fail">El método de autenticación \'publickey\' con clave \'%1$s\' ha fallado.</string> + <string name="terminal_auth_ki">Intentando autenticación \'interactiva por teclado\'</string> + <string name="terminal_auth_ki_fail">El método de autenticación \'interactiva por teclado\' ha fallado</string> + <string name="terminal_auth_fail">[Su equipo no soporta el método de autenticación por \'contraseña\' o por \'interacción por teclado\'.]</string> + <string name="terminal_no_session">La sesión no se iniciará debido a las preferencias del equipo.</string> + <string name="terminal_enable_portfoward">Activar redirección de puerto: %1$s</string> + <string name="local_shell_unavailable">¡Fallo! Su intérprete de órdenes local no está disponible en este teléfono.</string> + <string name="notification_text">%1$s requiere de tu atención.</string> + <string name="no">Denegar</string> + <string name="with_confirmation">Con confirmación</string> + <string name="yes">Sí</string> + <string name="exceptions_submit_message">Parece que ConnectBot tuvo un problema en su última ejecución. Enviar reporte de error a los desarrolladores de ConnectBot?</string> + <string name="menu_colors_reset">Restablecer</string> + <string name="app_is_running">ConnectBot está ejecutándose</string> + <string name="color_red">rojo</string> + <string name="color_green">verde</string> + <string name="color_blue">azul</string> + <string name="color_gray">gris</string> + <string name="image_description_connected">Conectado</string> + <string name="image_description_show_keyboard">Mostrar teclado.</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-eu/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,215 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">SSH bezero soil, ahaltsu eta librea</string> + <string name="service_desc">SSH konexio eta kargatutako gako publikoak mantentzen ditu</string> + <string name="title_hosts_list">Ostalariak</string> + <string name="title_pubkey_list">Gako publikoak</string> + <string name="title_port_forwards_list">Ataka birbidalketak</string> + <string name="title_host_editor">Editatu ostalaria</string> + <string name="title_help">Laguntza</string> + <string name="title_colors">Koloreak</string> + <string name="resolve_connect">Konektatu</string> + <string name="resolve_entropy">Bildu entropia</string> + <string name="menu_insert">Gehitu ostalaria</string> + <string name="menu_delete">Ezabatu ostalaria</string> + <string name="menu_preferences">Hobespenak</string> + <string name="help_intro">Mesedez, hautatu beheko gaietako bat informazio gehiago nahi izanez gero.</string> + <string name="help_about">ConnectBot-i buruz</string> + <string name="help_keyboard">Teklatua</string> + <string name="pubkey_generate">Sortu</string> + <string name="pubkey_import">Inportatu</string> + <string name="pubkey_delete">Ezabatu gakoa</string> + <string name="pubkey_gather_entropy">Entropia biltzen</string> + <string name="pubkey_touch_prompt">Ukitu kaxa hau ausazkotasuna lortzeko: %1$d%% eginda</string> + <string name="pubkey_touch_hint">Gakoa sortzeko beharrezko den ausazkotasuna lortzeko, mugitu hatza ausaz azpiko kaxaren gainean.</string> + <string name="pubkey_generating">"Gako parea sortzen…"</string> + <string name="pubkey_copy_private">Kopiatu gako pribatua</string> + <string name="pubkey_copy_public">Kopiatu gako publikoa</string> + <string name="pubkey_list_empty">Sakatu \"Menu\" gako pareak\nsortu edo inportatzeko</string> + <string name="pubkey_unknown_format">Formatu ezezaguna</string> + <string name="pubkey_change_password">Aldatu pasahitza</string> + <string name="pubkey_list_pick">Hautatu /sdcard-etik</string> + <string name="pubkey_import_parse_problem">Arazoa inportatutako gako pribatua aztertzean</string> + <string name="pubkey_unlock">Desblokeatu gakoa</string> + <string name="pubkey_failed_add">Pasahitz okerra \'%1$s\' gakoarentzat. Autentifikazioak huts egin du.</string> + <string name="pubkey_memory_load">Kargatu memoriara</string> + <string name="pubkey_memory_unload">Deskargatu memoriatik</string> + <string name="pubkey_load_on_start">Kargatu gakoa abiaraztean</string> + <string name="pubkey_confirm_use">Baieztatu erabili aurretik</string> + <string name="portforward_list_empty">Sakatu \"Menua\" ataka\nbirbidalketak sortzeko.</string> + <string name="portforward_edit">Editatu ataka birbidalketa</string> + <string name="portforward_delete">Ezabatu ataka birbidalketa</string> + <string name="prompt_nickname">Goitizena:</string> + <string name="prompt_nickname_hint_pubkey">Nire laneko gakoa</string> + <string name="prompt_source_port">Iturburuko ataka:</string> + <string name="prompt_destination">Helburua:</string> + <string name="prompt_old_password">Pasahitz zaharra:</string> + <string name="prompt_password">Pasahitza:</string> + <string name="prompt_again">(berriro)</string> + <string name="prompt_type">Mota:</string> + <string name="prompt_password_can_be_blank">Oharra: pasahitza hutsik utz daiteke</string> + <string name="prompt_bits">Bitak:</string> + <string name="prompt_pubkey_password">\'%1$s\' gakoaren pasahitza</string> + <string name="prompt_allow_agent_to_use_key">Urruneko ostalariak \'%1$s\'\ngakoa erabil dezan onartu?</string> + <string name="host_verification_failure_warning_header">KONTUZ: URRUNEKO OSTALARIAREN IDENTIFIKAZIOA ALDATU DA!</string> + <string name="host_verification_failure_warning">POSIBLE DA NORBAIT ZERBAIT MALTZURRA EGITEN ARITZEA!\nNorbait ezkutuan entzuten aritu daiteke(man-in-the-middle erasoa)!\nBeste aukera ostalariaren gakoa aldatu izana da.</string> + <string name="prompt_host_disconnected">Ostalaria deskonektatu egin da.\nSaioa itxi nahi duzu?</string> + <string name="prompt_continue_connecting">Ziur zaude konektatzen\njarraitu nahi duzula?</string> + <string name="host_authenticity_warning">\'%1$s\' ostalariaren autentifikazioa ezin da ziurtatu.</string> + <string name="host_fingerprint">%1$s ostalariaren hatz-marka %2$s da</string> + <string name="alert_passwords_do_not_match_msg">Pasahitzak ez datoz bat!</string> + <string name="alert_wrong_password_msg">Pasahitz okerra!</string> + <string name="alert_key_corrupted_msg">Gako pribatua hondatuta dagoela dirudi!</string> + <string name="alert_sdcard_absent">Ez da aurkitu SD txartelik!</string> + <string name="button_add">Gehitu</string> + <string name="button_change">Aldatu</string> + <string name="button_generate">Sortu gakoa</string> + <string name="button_resize">Aldatu tamaina</string> + <string name="alert_disconnect_msg">Konexioa galdu da</string> + <string name="pref_emulation_category">Terminal emulatzailea</string> + <string name="pref_emulation_title">Emulazio modua</string> + <string name="pref_emulation_summary">PTY konexioetarako terminal emulazio modua</string> + <string name="pref_scrollback_title">Korritze-barraren tamaina</string> + <string name="pref_scrollback_summary">Kontsola bakoitzarentzat memorian gordeko den korritze-barraren buffer tamaina.</string> + <string name="pref_ui_category">Erabiltzaile-interfazea</string> + <string name="pref_rotation_title">Biratze modua</string> + <string name="pref_rotation_summary">Nola aldatu biratzea teklatua bistaratzean/izkutatzean.</string> + <string name="pref_fullscreen_title">Pantaila osoa</string> + <string name="pref_fullscreen_summary">Ezkutatu egoera-barra kontsola erabiltzean</string> + <string name="pref_memkeys_title">Gorde gakoak memorian</string> + <string name="pref_memkeys_summary">Gogoratu desblokeatutako gakoak memorian zerbitzua amaitu arte</string> + <string name="pref_update_title">Eguneraketak begiratu</string> + <string name="pref_update_summary">ConnectBot-en eguneraketarik dagoen begiratzeko maiztasun maximoa finkatu</string> + <string name="pref_conn_persist_title">Konexio iraunkorrak</string> + <string name="pref_conn_persist_summary">Behartu konexioak aktibo mantentzera atzeko planoko daudenean</string> + <string name="pref_keymode_title">Direktorien laster-teklak</string> + <string name="pref_keymode_summary">Zehaztu nola erabili Alt \'/\'-entzat eta Shift Tab-entzat</string> + <string name="pref_camera_title">Kameraren laster-tekla</string> + <string name="pref_camera_summary">Zehaztu kameraren botoia sakatzean aktibatu nahi duzun laster-tekla</string> + <string name="pref_keepalive_title">Mantendu pantaila aktibo</string> + <string name="pref_keepalive_summary">Galarazi pantaila itzaltzea kontsola moduan lanean aritzean</string> + <string name="pref_wifilock_title">Mantendu WiFi-a aktibo</string> + <string name="pref_wifilock_summary">Galarazi WiFi-a itzaltzea saio aktibo bat dagoen bitartean</string> + <string name="pref_bumpyarrows_title">Bibraziodun geziak</string> + <string name="pref_bumpyarrows_summary">Bibratu trackball bidez erakusle-geziak bidaltzean; atzerapendun konexioentzat egokia</string> + <string name="pref_bell_category">Terminalaren txirrina</string> + <string name="pref_bell_title">Txirrin entzungarria</string> + <string name="pref_bell_volume_title">Txirrinaren bolumena</string> + <string name="pref_bell_vibrate_title">Bibratu txirrinarekin</string> + <string name="pref_bell_notification_title">Atzeko planoko jakinerazpenak</string> + <string name="pref_bell_notification_summary">Bidali jakinerazpena atzeko planoan dagoen terminal batek txirrina jotzean.</string> + <string name="list_keymode_right">Erabili eskuinaldeko teklak</string> + <string name="list_keymode_left">Erabili ezkerraldeko teklak</string> + <string name="list_keymode_none">Desgaitu</string> + <string name="list_pubkeyids_none">Ez erabili gakorik</string> + <string name="list_pubkeyids_any">Erabili desblokeatutako edozein gako</string> + <string name="hostpref_nickname_title">Goitizena</string> + <string name="hostpref_color_title">Kolore kategoria</string> + <string name="hostpref_fontsize_title">Letra-tamaina (pt)</string> + <string name="hostpref_pubkeyid_title">Erabili gako publiko bidezko autentifikazioa</string> + <string name="hostpref_authagent_title">Erabili SSH autentifikazio-eragilea</string> + <string name="hostpref_postlogin_title">Saio hasiera ondoko automatizazioa</string> + <string name="hostpref_postlogin_summary">Autentifikatu ondoren urruneko zerbitzarian exekutatu beharreko komandoak</string> + <string name="hostpref_compression_title">Konpresioa</string> + <string name="hostpref_compression_summary">Hau lagungarri izan daiteke konexio mantsoekin</string> + <string name="hostpref_wantsession_title">Hasi shell saioa</string> + <string name="hostpref_wantsession_summary">Desgaitu aukera hau ataka birbidalketak bakarrik erabiltzeko</string> + <string name="hostpref_stayconnected_title">Konektatuta mantendu</string> + <string name="hostpref_stayconnected_summary">Saiatu ostalarira birkonektatzen deskonektatzean</string> + <string name="hostpref_delkey_title">DEL tekla</string> + <string name="hostpref_delkey_summary">DEL tekla sakatzean bidaltzen den tekla-kodea</string> + <string name="hostpref_encoding_title">Kodeketa</string> + <string name="hostpref_encoding_summary">Ostalariarentzako karaktere kodeketa</string> + <string name="hostpref_connection_category">Konexio hobespenak</string> + <string name="hostpref_username_title">Erabiltzaile-izena</string> + <string name="hostpref_hostname_title">Ostalaria</string> + <string name="hostpref_port_title">Ataka</string> + <string name="bind_never">Inoiz ez da konexiorik ezarri</string> + <string name="bind_minutes">Duela %1$s minutu</string> + <string name="bind_hours">Duela %1$s ordu</string> + <string name="bind_days">Duela %1$s egun</string> + <string name="console_copy_done">%1$d byte kopiatuta arbelera</string> + <string name="console_copy_start">Ukitu eta arrastatu\nedo erabili norabide kuxina\nkopiatu beharreko eremua hautatzeko</string> + <string name="console_menu_close">Itxi</string> + <string name="console_menu_copy">Kopiatu</string> + <string name="console_menu_paste">Itsatsi</string> + <string name="console_menu_portforwards">Ataka birbidalketak</string> + <string name="console_menu_resize">Behartu tamaina</string> + <string name="console_menu_urlscan">URL eskaneatzea</string> + <string name="button_yes">Bai</string> + <string name="button_no">Ez</string> + <string name="portforward_local">Lokala</string> + <string name="portforward_remote">Urrunekoa</string> + <string name="portforward_dynamic">Dinamikoa (SOCKS)</string> + <string name="portforward_pos">Sortu ataka birbidalketa</string> + <string name="portforward_done">Ataka birbidalketa ongi sortu da</string> + <string name="portforward_problem">Arazoa ataka birbidalketa sortzean, behar bada erabilitako ataka 1024 baino txikiagoa da edo dagoeneko erabiltzen den ataka bat da?</string> + <string name="portforward_menu_add">Gehitu ataka birbidalketa</string> + <string name="hint_userhost">erabiltzailea\@ostalaria</string> + <string name="list_format_error">Erabili %1$s formatua</string> + <string name="format_username">erabiltzaile-izena</string> + <string name="format_hostname">ostalaria</string> + <string name="format_port">ataka</string> + <string name="list_menu_pubkeys">Kudeatu gako publikoak</string> + <string name="list_menu_sortcolor">Antolatu kolorearen arabera</string> + <string name="list_menu_sortname">Antolatu izenaren arabera</string> + <string name="list_menu_settings">Ezarpenak</string> + <string name="list_host_disconnect">Deskonektatu</string> + <string name="list_host_edit">Editatu ostalaria</string> + <string name="list_host_portforwards">Editatu ataka birbidalketak</string> + <string name="list_host_delete">Ezabatu ostalaria</string> + <string name="list_host_empty">Erabili azpiko konexio-azkarreko kaxa\nostalari batetara konektatzeko</string> + <string name="list_rotation_default">Lehenetsia</string> + <string name="list_rotation_land">Behartu horizontala</string> + <string name="list_rotation_port">Behartu bertikala</string> + <string name="list_rotation_auto">Automatikoa</string> + <string name="list_hwbutton_ctrlaspace">Ktrl+A ondoren zuriunea</string> + <string name="list_hwbutton_ctrla">Ktrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Ezer ez</string> + <string name="list_delkey_backspace">Atzera tekla</string> + <string name="list_delkey_del">Ezabatu</string> + <string name="delete_message">Ziur zaude \'%1$s\' ezabatu nahi duzula?</string> + <string name="delete_pos">Bai, ezabatu</string> + <string name="delete_neg">Utzi</string> + <string name="wizard_agree">Ados</string> + <string name="wizard_next">Hurrengoa</string> + <string name="wizard_back">Atzera</string> + <string name="terminal_no_hosts_connected">Ez dago ostalaririk konektatuta une honetan</string> + <string name="terminal_connecting">%1$s:%2$d-ra konektatzen %3$s bidez</string> + <string name="terminal_sucess">Egiaztatutako ostalaria \'%1$s\' gakoa: %2$s</string> + <string name="terminal_failed">Ostalariaren gakoaren egiaztapenak huts egin du</string> + <string name="terminal_using_s2c_algorithm">Zerbitzari-bezero algoritmoa: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Bezero-zerbitzari algoritmoa: %1$s %2$s</string> + <string name="terminal_using_algorithm">Uneko algoritmoa: %1$s %2$s</string> + <string name="terminal_auth">Autentifikatzen saiatzen</string> + <string name="terminal_auth_pass">\'Pasahitz bidez\' autentifikatzen saiatzen</string> + <string name="terminal_auth_pass_fail">\'Pasahitz bidezko\' autentifikatzeak huts egin du</string> + <string name="terminal_auth_pubkey_any">\'Gako publiko bidezko\' autentifikatze saiakera memoriako gako publikoak erabiliz</string> + <string name="terminal_auth_pubkey_invalid">Hautatutako gako publikoa baliogabea da, saiatu berriz hautatzen ostalari editorean</string> + <string name="terminal_auth_pubkey_specific">Saiatu \'gako publiko bidez\' autentifikatzen gako publiko zehatz batekin</string> + <string name="terminal_auth_pubkey_fail">\'%1$s\' gakoa erabiliz egindako \'gako publiko bidezko\' autenfikazioak huts egin du</string> + <string name="terminal_auth_ki">\'Teklatu bidezko autentifikazio elkarreragilea\' saiatzen</string> + <string name="terminal_auth_ki_fail">\'Teklatu bidezko autentifikazio elkarreragileak\' huts egin du</string> + <string name="terminal_auth_fail">[Zure ostalariak ez du onartzen \'pasahitz bidezko\' edo \'teklatu bidezko autentifikazio elkarreragilerik\'.]</string> + <string name="terminal_no_session">Saiorik ez da hasiko ostalariaren hobespenak direla eta.</string> + <string name="terminal_enable_portfoward">Gaitu ataka birbidalketa: %1$s</string> + <string name="local_shell_unavailable">Errorea! Shell lokala ez dago eskuragarri telefono honetan.</string> + <string name="notification_text">%1$s-k zure arreta behar du.</string> + <string name="no">Ez</string> + <string name="with_confirmation">Berrespenarekin</string> + <string name="yes">Bai</string> + <string name="exceptions_submit_message">Dirudienez ConnectBot-ek arazo bat izan zuen azken exekuzioan. ConnectBot-en garatzaileei errore-txostena bidali?</string> + <string name="menu_colors_reset">Berrezarri</string> + <string name="app_is_running">ConnectBot martxan dago</string> + <string name="color_red">gorria</string> + <string name="color_green">berdea</string> + <string name="color_blue">urdina</string> + <string name="color_gray">grisa</string> + <string name="image_description_connected">Konektatuta.</string> + <string name="image_description_key_is_locked">Gakoa blokeatuta dago.</string> + <string name="image_description_toggle_control_character">Txandakatu kontrol karakterea.</string> + <string name="image_description_send_escape_character">Bidali ihes karakterea.</string> + <string name="image_description_show_keyboard">Erakutsi teklatua.</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-fa/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-fi/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,212 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Yksinkertainen ja tehokas avoimen lähdekoodin SSH-asiakasohjelma.</string> + <string name="service_desc">Ylläpitää SSH-yhteydet ja ladatut julkiset avaimet</string> + <string name="title_hosts_list">Palvelimet</string> + <string name="title_pubkey_list">Julkiset avaimet</string> + <string name="title_port_forwards_list">Porttiohjaukset</string> + <string name="title_host_editor">Muokaa palvelinta</string> + <string name="title_help">Ohje</string> + <string name="title_colors">Värit</string> + <string name="resolve_connect">Yhdistä</string> + <string name="resolve_entropy">Satunnaisdatan keräys</string> + <string name="menu_insert">Lisää palvelin</string> + <string name="menu_delete">Poista palvelin</string> + <string name="menu_preferences">Asetukset</string> + <string name="help_intro">Valitse alta aihe, josta haluat lisätietoja.</string> + <string name="help_about">Tietoja ConnectBotista</string> + <string name="help_keyboard">Näppäimistö</string> + <string name="pubkey_generate">Luo</string> + <string name="pubkey_import">Tuo</string> + <string name="pubkey_delete">Poista avain</string> + <string name="pubkey_gather_entropy">Kerätään satunnaisdataa</string> + <string name="pubkey_touch_prompt">Kosketa tätä laatikkoa kerätäksesi satunnaisdataa: %1$d%% valmiina</string> + <string name="pubkey_touch_hint">Liikuta sormeasi alla olevan laatikon kohdalla sattumanvaraisesti varmistaaksesi avaimen luonnin satunnaisuuden.</string> + <string name="pubkey_generating">"Luodaan avainparia…"</string> + <string name="pubkey_copy_private">Kopio yksityinen avain</string> + <string name="pubkey_copy_public">Kopioi julkinen avain</string> + <string name="pubkey_list_empty">Paina valikkopainiketta\nluodaksesi tai tuodaksesi\navainpareja.</string> + <string name="pubkey_unknown_format">Tuntematon tyyppi</string> + <string name="pubkey_change_password">Vaihda salasana</string> + <string name="pubkey_list_pick">Hae sijainnista /sdcard</string> + <string name="pubkey_import_parse_problem">Ongelma käsiteltäessä tuotua avainparia</string> + <string name="pubkey_unlock">Poista avaimen lukitus</string> + <string name="pubkey_failed_add">Väärä salasana avaimelle \'%1$s\'. Tunnistus epäonnistui.</string> + <string name="pubkey_memory_load">Lataa muistiin</string> + <string name="pubkey_memory_unload">Poista muistista</string> + <string name="pubkey_load_on_start">Lataa avain käynnistyksen yhteydessä</string> + <string name="pubkey_confirm_use">Vahvista ennen käyttöä</string> + <string name="portforward_list_empty">Paina valikkopainiketta\nluodaksesi porttiohjauksia.</string> + <string name="portforward_edit">Muokkaa porttiohjausta</string> + <string name="portforward_delete">Poista porttiohjaus</string> + <string name="prompt_nickname">Lempinimi:</string> + <string name="prompt_nickname_hint_pubkey">Työavain</string> + <string name="prompt_source_port">Lähdeportti:</string> + <string name="prompt_destination">Kohde:</string> + <string name="prompt_old_password">Vanha salasana:</string> + <string name="prompt_password">Salasana:</string> + <string name="prompt_again">(uudelleen)</string> + <string name="prompt_type">Tyyppi:</string> + <string name="prompt_password_can_be_blank">Huomio: salasana voi olla sisältämättä merkkejä</string> + <string name="prompt_bits">Bittejä:</string> + <string name="prompt_pubkey_password">Salasana avaimelle \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Hyväksy etäyhteys:\nkäytä avainta \'%1$s\'</string> + <string name="host_verification_failure_warning_header">VAROITUS: ETÄPÄÄN KONEEN TUNNISTE ON MUUTTUNUT!</string> + <string name="host_verification_failure_warning">JOKU SAATTAA OLLA TEKEMÄSSÄ PAHOJAAN!\nOn mahdollista, että yhteyttäsi salakuunnellaan (niin kutsuttu man-in-the-middle -hyökkäys)!\nOn toki myös mahdollista, että palvelimen avainta vain on muutettu.</string> + <string name="prompt_host_disconnected">Palvelin katkaisi yhteyden.\nSuljetaanko istunto?</string> + <string name="prompt_continue_connecting">Haluatko varmasti\njatkaa yhdistämistä?</string> + <string name="host_authenticity_warning">Palvelimen \'%1$s\' aitoutta ei voida varmentaa</string> + <string name="host_fingerprint">Palvelimen %1$s avaimen sormenjälki: %2$s</string> + <string name="alert_passwords_do_not_match_msg">Salasanat eivät täsmää!</string> + <string name="alert_wrong_password_msg">Väärä salasana!</string> + <string name="alert_key_corrupted_msg">Yksityinen avain vaikuttaa korruptoituneelta.</string> + <string name="alert_sdcard_absent">Laitteessa ei ole muistikorttia!</string> + <string name="button_add">Lisää</string> + <string name="button_change">Muokkaa</string> + <string name="button_generate">Luo avain</string> + <string name="button_resize">Muuta kokoa</string> + <string name="alert_disconnect_msg">Yhteys katkesi</string> + <string name="pref_emulation_category">Pääte-emulaattori</string> + <string name="pref_emulation_title">Emulointitila</string> + <string name="pref_emulation_summary">PTY-yhteyksissä käytettävä emulointitila</string> + <string name="pref_scrollback_title">Vierityspuskurin koko</string> + <string name="pref_scrollback_summary">Konsolikohtainen koko vierityspuskurille, jossa pidetään konsolin historiaa</string> + <string name="pref_ui_category">Käyttöliittymä</string> + <string name="pref_rotation_title">Näytön pyöritys</string> + <string name="pref_rotation_summary">Miten näyttöä pyöritetään kun näppäimistö tulee näkyviin/poistuu näkyvistä</string> + <string name="pref_fullscreen_title">Kokoruutu</string> + <string name="pref_fullscreen_summary">Piilota ilmoitusalue konsolikäytössä</string> + <string name="pref_memkeys_title">Pidä avaimet muistissa</string> + <string name="pref_memkeys_summary">Pitää avatut avaimet muistissa kunnes taustapalvelu suljetaan</string> + <string name="pref_update_title">Päivitysten tarkistus</string> + <string name="pref_update_summary">Kuinka usein ConnectBot enintään tarkistaa päivitykset</string> + <string name="pref_conn_persist_title">Ylläpidä yhteys</string> + <string name="pref_conn_persist_summary">Pakottaa yhteyden pysymään aktiivisena ohjelman ollessa taustalla</string> + <string name="pref_keymode_title">Pikanäppäimet</string> + <string name="pref_camera_title">Kamera-pikanäppäin</string> + <string name="pref_camera_summary">Valitse kamerapainikkeesta suoritettava toiminto</string> + <string name="pref_keepalive_title">Pidä näyttö päällä</string> + <string name="pref_keepalive_summary">Estää näytön sammumisen työskenneltäessä konsolissa</string> + <string name="pref_wifilock_title">Pidä Wi-Fi-yhteys päällä</string> + <string name="pref_wifilock_summary">Estää Wi-Fi-yhteyden katkaisemisen kun istunto on aktiivinen</string> + <string name="pref_bumpyarrows_title">Värinä nuolista</string> + <string name="pref_bumpyarrows_summary">Värinäefekti aina kun nuolinäppäinten painalluksia lähetetään palvelimelle. Kätevä hitaille yhteyksille.</string> + <string name="pref_bell_category">Päätteen kello</string> + <string name="pref_bell_title">Kellon äänet käytössä</string> + <string name="pref_bell_volume_title">Kellon äänenvoimakkuus</string> + <string name="pref_bell_vibrate_title">Värinäefekti kellosta</string> + <string name="pref_bell_notification_title">Taustailmoitukset</string> + <string name="pref_bell_notification_summary">Näyttää ilmoituksen kun taustalla olevassa päätteessä soitetaan kelloa.</string> + <string name="list_keymode_right">Käytä oikean reunan erikoispainikkeita</string> + <string name="list_keymode_left">Käytä vasemman reunan erikoispainikkeita</string> + <string name="list_keymode_none">Pois käytöstä</string> + <string name="list_pubkeyids_none">Älä käytä avaimia</string> + <string name="list_pubkeyids_any">Käytä mitä tahansa avattua avainta</string> + <string name="hostpref_nickname_title">Lempinimi</string> + <string name="hostpref_color_title">Väri</string> + <string name="hostpref_fontsize_title">Kirjasimen koko (pistettä)</string> + <string name="hostpref_pubkeyid_title">Kirjaudu avainparilla</string> + <string name="hostpref_authagent_title">Käytä SSH-kirjautumisagenttia</string> + <string name="hostpref_postlogin_title">Kirjautumisen jälkeiset automaattiset toimenpiteet</string> + <string name="hostpref_postlogin_summary">Palvelimella kirjautumisen jälkeen ajettavat komennot</string> + <string name="hostpref_compression_title">Pakkaus</string> + <string name="hostpref_compression_summary">Tämä voi helpottaa hitaiden yhteyksien käyttämistä</string> + <string name="hostpref_wantsession_title">Käynnistä komentorivi-istunto</string> + <string name="hostpref_wantsession_summary">Ota tämä pois käytöstä jos käytät vain porttiohjausta</string> + <string name="hostpref_stayconnected_title">Pysy yhteydessä</string> + <string name="hostpref_stayconnected_summary">Yritä yhdistää palvelimeen uudelleen yhteyden katkeamisen jälkeen</string> + <string name="hostpref_delkey_title">Del-näppäin</string> + <string name="hostpref_delkey_summary">Del-näppäintä painettaessa lähetettävä näppäinkoodi</string> + <string name="hostpref_encoding_title">Merkistökoodaus</string> + <string name="hostpref_encoding_summary">Palvelimella käytettävä merkistökoodaus</string> + <string name="hostpref_connection_category">Yhteysasetukset</string> + <string name="hostpref_username_title">Käyttäjätunnus</string> + <string name="hostpref_hostname_title">Palvelin</string> + <string name="hostpref_port_title">Portti</string> + <string name="bind_never">Ei koskaan yhdistetty</string> + <string name="bind_minutes">%1$s minuuttia sitten</string> + <string name="bind_hours">%1$s tuntia sitten</string> + <string name="bind_days">%1$s päivää sitten</string> + <string name="console_copy_done">%1$d tavua kopioitu leikepöydälle</string> + <string name="console_copy_start">Maalaa koskettamalla\ntai käytä nuolinäppäimiä\nvalitaksesi kopioitavan alueen</string> + <string name="console_menu_close">Sulje</string> + <string name="console_menu_copy">Kopioi</string> + <string name="console_menu_paste">Liitä</string> + <string name="console_menu_portforwards">Porttiohjaukset</string> + <string name="console_menu_resize">Pakota koko</string> + <string name="console_menu_urlscan">URL-haku</string> + <string name="button_yes">Kyllä</string> + <string name="button_no">Ei</string> + <string name="portforward_local">Paikallinen</string> + <string name="portforward_remote">Etä</string> + <string name="portforward_dynamic">Dynaaminen (SOCKS)</string> + <string name="portforward_pos">Luo porttiohjaus</string> + <string name="portforward_done">Porttiohjaus luotu onnistuneesti</string> + <string name="portforward_problem">Ongelma luotaessa porttiohjausta. Ehkä käytät porttia joka on alle 1024 tai portti on jo käytössä?</string> + <string name="portforward_menu_add">Lisää porttiohjaus</string> + <string name="hint_userhost">tunnus\@palvelin</string> + <string name="list_format_error">Käytä muotoa %1$s</string> + <string name="format_username">käyttäjätunnus</string> + <string name="format_hostname">palvelin</string> + <string name="format_port">portti</string> + <string name="list_menu_pubkeys">Hallitse avaimia</string> + <string name="list_menu_sortcolor">Lajittele värin mukaan</string> + <string name="list_menu_sortname">Lajittele nimen mukaan</string> + <string name="list_menu_settings">Asetukset</string> + <string name="list_host_disconnect">Katkaise</string> + <string name="list_host_edit">Muokkaa palvelinta</string> + <string name="list_host_portforwards">Muokkaa porttiohjauksia</string> + <string name="list_host_delete">Poista palvelin</string> + <string name="list_host_empty">Käytä alla olevaa tekstikenttää\nyhdistääksesei palvelimeen.</string> + <string name="list_rotation_default">Oletus</string> + <string name="list_rotation_land">Pakota vaakatasoon</string> + <string name="list_rotation_port">Pakota pystysuuntaan</string> + <string name="list_rotation_auto">Automaattinen</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A ja välilyönti</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Ei mitään</string> + <string name="list_delkey_backspace">Askelpalautin</string> + <string name="list_delkey_del">Delete</string> + <string name="delete_message">Oletko varma että haluat poistaa: \'%1$s\'?</string> + <string name="delete_pos">Kyllä, poista</string> + <string name="delete_neg">Peru</string> + <string name="wizard_agree">Hyväksy</string> + <string name="wizard_next">Seuraava</string> + <string name="wizard_back">Edellinen</string> + <string name="terminal_no_hosts_connected">Yhteenkään palvelimeen ei ole yhdistetty</string> + <string name="terminal_connecting">Muodostetaan %3$s-yhteys palvelimeen %1$s:%2$d</string> + <string name="terminal_sucess">Varmennettiin palvelin \'%1$s\' avain: %2$s</string> + <string name="terminal_failed">Palvelimen avaimen varmistaminen epäonnistui</string> + <string name="terminal_using_s2c_algorithm">Salausalgoritmi palvelimelta asiakkaalle: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Salausalgoritmi asiakkaalta palvelimelle: %1$s %2$s</string> + <string name="terminal_using_algorithm">Käytetään salausalgoritmia %1$s %2$s</string> + <string name="terminal_auth">Kirjaudutaan</string> + <string name="terminal_auth_pass">Yritetään \'salasana\' tunnistusta</string> + <string name="terminal_auth_pass_fail">Varmennusmenetelmä \'password\' epäonnistui</string> + <string name="terminal_auth_pubkey_any">Yritetään \'publickey\' varmennusta millä tahansa muistissa olevalla julkisella avaimella</string> + <string name="terminal_auth_pubkey_invalid">Valittu julkinen avain ei kelpaa, kokeile valita toinen avain palvelimen asetuksista</string> + <string name="terminal_auth_pubkey_specific">Yritetään \'publickey\' varmennusta tietyllä julkisella avaimella</string> + <string name="terminal_auth_pubkey_fail">Varmennusmenetelmä \'publickey\' avaimella \'%1$s\' epäonnistui</string> + <string name="terminal_auth_ki">Yritetään \'keyboard-interactive\' varmennusta</string> + <string name="terminal_auth_ki_fail">Varmennusmenetelmä \'keyboard-interactive\' epäonnistui</string> + <string name="terminal_auth_fail">[Palvelin ei tue \'password\' tai \'keyboard-interactive\' varmennusmenetelmiä.]</string> + <string name="terminal_no_session">Istuntoa ei aloiteta palvelimen asetuksista johtuen</string> + <string name="terminal_enable_portfoward">Ota käyttöön porttiohjaus %1$s</string> + <string name="local_shell_unavailable">Virhe! Paikallista komentoriviä ei ole käytettävissä</string> + <string name="notification_text">%1$s kaipaa huomiotasi.</string> + <string name="no">Ei</string> + <string name="with_confirmation">Kysy varmistus</string> + <string name="yes">Kyllä</string> + <string name="exceptions_submit_message">ConnectBotilla vaikutti olevan ongelmia kun sitä käytettiin edellisen kerran. Lähetetäänkö virheraportti ohjelman kehittäjille?</string> + <string name="menu_colors_reset">Palauta</string> + <string name="app_is_running">ConnectBot on käynnissä</string> + <string name="color_red">punainen</string> + <string name="color_green">vihreä</string> + <string name="color_blue">sininen</string> + <string name="color_gray">harmaa</string> + <string name="image_description_connected">Yhdistetty.</string> + <string name="image_description_send_escape_character">Lähetä escape.</string> + <string name="image_description_show_keyboard">Näytä näppäimistö</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-fr/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Un client SSH simple, open-source et puissant.</string> + <string name="service_desc">Maintient les connexions SSH et les clefs publiques chargées</string> + <string name="title_hosts_list">Serveurs</string> + <string name="title_pubkey_list">Clés publiques</string> + <string name="title_port_forwards_list">Redirections de ports</string> + <string name="title_host_editor">Modifier le serveur</string> + <string name="title_help">Aide</string> + <string name="title_colors">Couleurs</string> + <string name="resolve_connect">Connexion</string> + <string name="resolve_entropy">Générer de l\'entropie</string> + <string name="menu_insert">Ajouter un serveur</string> + <string name="menu_delete">Supprimer le serveur</string> + <string name="menu_preferences">Préférences</string> + <string name="help_intro">Sélectionnez un sujet ci-dessous pour plus d\'informations.</string> + <string name="help_about">À propos de ConnectBot</string> + <string name="help_keyboard">Clavier</string> + <string name="pubkey_generate">Générer</string> + <string name="pubkey_import">Importer</string> + <string name="pubkey_delete">Supprimer la clé</string> + <string name="pubkey_gather_entropy">Génération d\'entropie</string> + <string name="pubkey_touch_prompt">Touchez cette boîte pour générer de l\'entropie : %1$d%% effectué</string> + <string name="pubkey_touch_hint">Afin d\'assurer la qualité des nombres aléatoires utilisés pendant la génération de la clé, merci de bouger votre doigt de façon aléatoire sur la boîte ci-dessous.</string> + <string name="pubkey_generating">"Génération de la paire de clés en cours…"</string> + <string name="pubkey_copy_private">Copier la clé privée</string> + <string name="pubkey_copy_public">Copier la clé publique</string> + <string name="pubkey_list_empty">Cliquer sur le Menu pour créer\nou importer des paires de clés.</string> + <string name="pubkey_unknown_format">Format inconnu</string> + <string name="pubkey_change_password">Changer le mot de passe</string> + <string name="pubkey_list_pick">Récupérer depuis /sdcard</string> + <string name="pubkey_import_parse_problem">Problème lors du parsage de la clé privée importée</string> + <string name="pubkey_unlock">Déverrouiller la clé</string> + <string name="pubkey_failed_add">Mot de passe incorrect pour la clé \'%1$s\'. L\'authentification a échoué.</string> + <string name="pubkey_memory_load">Charger en mémoire</string> + <string name="pubkey_memory_unload">Décharger de la mémoire</string> + <string name="pubkey_load_on_start">Charger la clé au démarrage</string> + <string name="pubkey_confirm_use">Confirmer avant utilisation</string> + <string name="portforward_list_empty">Appuyez sur Menu pour créer\ndes redirections de port.</string> + <string name="portforward_edit">Éditer la redirection de port</string> + <string name="portforward_delete">Effacer la redirection de port</string> + <string name="prompt_nickname">Pseudonyme :</string> + <string name="prompt_nickname_hint_pubkey">Ma clé de travail</string> + <string name="prompt_source_port">Port source :</string> + <string name="prompt_destination">Destination :</string> + <string name="prompt_old_password">Ancien mot de passe :</string> + <string name="prompt_password">Mot de passe :</string> + <string name="prompt_again">(encore)</string> + <string name="prompt_type">Type :</string> + <string name="prompt_password_can_be_blank">Note : le mot de passe peut être vide</string> + <string name="prompt_bits">Bits :</string> + <string name="prompt_pubkey_password">Mot de passe pour la clé \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Autoriser l\'hôte distant à\nutiliser la clé \'%1$s\' ?</string> + <string name="host_verification_failure_warning_header">ATTENTION : L\'IDENTIFICATION DE L\'HÔTE DISTANT A CHANGÉ !</string> + <string name="host_verification_failure_warning">IL EST POSSIBLE QUE QUELQU\'UN FASSE QUELQUE CHOSE DE NUISIBLE !\nQuelqu\'un pourrait vous écouter en ce moment (attaque de l\'homme du milieu) !\nIl est aussi possible que la clé du serveur ait juste changée.</string> + <string name="prompt_host_disconnected">L\'hôte s\'est déconnecté.\nFermer la session ?</string> + <string name="prompt_continue_connecting">Êtes-vous sûr de vouloir\ncontinuer à vous connecter ?</string> + <string name="host_authenticity_warning">L\'authenticité du serveur \'%1$s\' ne peut être établie</string> + <string name="host_fingerprint">L\'empreinte de la clé du serveur %1$s est %2$s</string> + <string name="alert_passwords_do_not_match_msg">Les mots de passe sont différents !</string> + <string name="alert_wrong_password_msg">Mauvais mot de passe !</string> + <string name="alert_key_corrupted_msg">La clé privé semble corrompue !</string> + <string name="alert_sdcard_absent">Pas de carte SD dans le lecteur !</string> + <string name="button_add">Ajouter</string> + <string name="button_change">Changer</string> + <string name="button_generate">Générer une clé</string> + <string name="button_resize">Retailler</string> + <string name="alert_disconnect_msg">Connexion perdue</string> + <string name="pref_emulation_category">Émulation du mode terminal</string> + <string name="pref_emulation_title">Mode d\'émulation</string> + <string name="pref_emulation_summary">Mode d\'émulation de terminal à utiliser pour les connexions PTY</string> + <string name="pref_scrollback_title">Taille de l\'historique</string> + <string name="pref_scrollback_summary">Taille de l\'historique à garder en mémoire pour chaque console</string> + <string name="pref_ui_category">Interface utilisateur</string> + <string name="pref_rotation_title">Mode de rotation</string> + <string name="pref_rotation_summary">Comment changer l\'orientation de l\'écran suivant si le clavier est déplié</string> + <string name="pref_fullscreen_title">Plein écran</string> + <string name="pref_fullscreen_summary">Cacher la barre de notifications lorsque la console est active</string> + <string name="pref_memkeys_title">Garder les clés en mémoire</string> + <string name="pref_memkeys_summary">Garder les clés débloquées en mémoire tant que le service tourne en arrière-plan</string> + <string name="pref_update_title">Vérifier les mises à jour</string> + <string name="pref_update_summary">Régler la fréquence de vérification pour les mises à jour de ConnectBot</string> + <string name="pref_conn_persist_title">Connexions persistantes</string> + <string name="pref_conn_persist_summary">Forcer les connexions à rester connectées en arrière-plan</string> + <string name="pref_keymode_title">Raccourcis de navigation</string> + <string name="pref_keymode_summary">Définir quel couple de touches Alt et Shift utiliser pour \'/\' et Tab</string> + <string name="pref_camera_title">Raccourci du bouton Appareil photo</string> + <string name="pref_camera_summary">Sélectionnez le raccourci à exécuter quand le bouton caméra est pressé</string> + <string name="pref_keepalive_title">Garder l\'écran allumé</string> + <string name="pref_keepalive_summary">Empêcher la mise en veille de l\'écran pendant une session console</string> + <string name="pref_wifilock_title">Garder le Wi-Fi actif</string> + <string name="pref_wifilock_summary">Empêcher la désactivation du Wi-Fi quand une session est active</string> + <string name="pref_bumpyarrows_title">Flêches vibrantes</string> + <string name="pref_bumpyarrows_summary">Vibrer lors de l\'envoi d\'une touche directionnelle à partir du trackball ; intéressant pour les connexions lentes</string> + <string name="pref_bell_category">Cloche du terminal</string> + <string name="pref_bell_title">Alerte sonore</string> + <string name="pref_bell_volume_title">Volume de l\'alerte</string> + <string name="pref_bell_vibrate_title">Vibrer en cas d\'alerte</string> + <string name="pref_bell_notification_title">Notifications en arrière-plan</string> + <string name="pref_bell_notification_summary">Envoyer une notification lorsqu\'un terminal en arrière-plan génère une alerte</string> + <string name="list_keymode_right">Utiliser les touches du côté droit du clavier</string> + <string name="list_keymode_left">Utiliser les touches du côté gauche du clavier</string> + <string name="list_keymode_none">Désactivé</string> + <string name="list_pubkeyids_none">Ne pas utiliser les clés publiques</string> + <string name="list_pubkeyids_any">Utiliser une clé pour l\'authentification</string> + <string name="hostpref_nickname_title">Surnom</string> + <string name="hostpref_color_title">Catégorie de couleur</string> + <string name="hostpref_fontsize_title">Taille de police (pt)</string> + <string name="hostpref_pubkeyid_title">Utiliser l\'authentification par clé publique</string> + <string name="hostpref_authagent_title">Utiliser l\'agent d\'authentification SSH</string> + <string name="hostpref_postlogin_title">Commande à exécuter automatiquement après l\'authentification</string> + <string name="hostpref_postlogin_summary">Commandes à lancer sur le serveur distant après s\'être authentifié</string> + <string name="hostpref_compression_title">Compression</string> + <string name="hostpref_compression_summary">Cela peut aider pour les réseaux lents</string> + <string name="hostpref_wantsession_title">Démarrer une session en ligne de commande</string> + <string name="hostpref_wantsession_summary">Décochez cette case pour n\'utiliser que les redirections de port</string> + <string name="hostpref_stayconnected_title">Rester connecté</string> + <string name="hostpref_stayconnected_summary">Essayer de se reconnecter à l\'hôte si on est déconnecté</string> + <string name="hostpref_delkey_title">Touche SUPPR</string> + <string name="hostpref_delkey_summary">Le code de touche envoyé quand la touche SUPPR est appuyée.</string> + <string name="hostpref_encoding_title">Encodage</string> + <string name="hostpref_encoding_summary">Jeu de caractères à utiliser pour le serveur</string> + <string name="hostpref_connection_category">Paramètres de connexion</string> + <string name="hostpref_username_title">Nom d\'utilisateur</string> + <string name="hostpref_hostname_title">Serveur</string> + <string name="hostpref_port_title">Port</string> + <string name="bind_never">Jamais connecté</string> + <string name="bind_minutes">Il y a %1$s minutes</string> + <string name="bind_hours">Il y a %1$s heures</string> + <string name="bind_days">Il y a %1$s jours</string> + <string name="console_copy_done">%1$d octets copiés dans le presse-papier</string> + <string name="console_copy_start">Touchez et tirez, ou utilisez\nles touches directionnelles\npour sélectionner la région\nà copier</string> + <string name="console_menu_close">Fermer</string> + <string name="console_menu_copy">Copier</string> + <string name="console_menu_paste">Coller</string> + <string name="console_menu_portforwards">Redirections de port</string> + <string name="console_menu_resize">Forcer la taille</string> + <string name="console_menu_urlscan">Lister les URL</string> + <string name="button_yes">Oui</string> + <string name="button_no">Non</string> + <string name="portforward_local">Local</string> + <string name="portforward_remote">Distant</string> + <string name="portforward_dynamic">Dynamique (SOCKS)</string> + <string name="portforward_pos">Créer la redirection de port</string> + <string name="portforward_done">Redirection de port créée avec succès</string> + <string name="portforward_problem">Problème de création de la redirection de port, peut-être utilisez-vous un port sous le 1024 ou un déjà utilisé ?</string> + <string name="portforward_menu_add">Ajouter une redirection de port</string> + <string name="hint_userhost">utilisateur\@serveur</string> + <string name="list_format_error">Utilisez le format \"%1$s\"</string> + <string name="format_username">utilisateur</string> + <string name="format_hostname">nom d\'hôte</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Gérer les clés publiques</string> + <string name="list_menu_sortcolor">Trier par couleur</string> + <string name="list_menu_sortname">Trier par nom</string> + <string name="list_menu_settings">Réglages</string> + <string name="list_host_disconnect">Déconnexion</string> + <string name="list_host_edit">Éditer le serveur</string> + <string name="list_host_portforwards">Éditer les redirections de port</string> + <string name="list_host_delete">Effacer le serveur</string> + <string name="list_host_empty">Utilisez la boîte de connexion rapide en bas\npour vous connecter à un serveur</string> + <string name="list_rotation_default">Par défaut</string> + <string name="list_rotation_land">Forcer le mode paysage</string> + <string name="list_rotation_port">Forcer le mode portrait</string> + <string name="list_rotation_auto">Automatique</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A puis Espace</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Échap</string> + <string name="list_hwbutton_esc_a">Echap+A</string> + <string name="list_hwbutton_none">Aucun</string> + <string name="list_delkey_backspace">Retour arrière</string> + <string name="list_delkey_del">Supprimer</string> + <string name="delete_message">Êtes-vous sûr de vouloir supprimer \'%1$s\' ?</string> + <string name="delete_pos">Oui, supprimer</string> + <string name="delete_neg">Annuler</string> + <string name="wizard_agree">Accepter</string> + <string name="wizard_next">Suivant</string> + <string name="wizard_back">Précédent</string> + <string name="terminal_no_hosts_connected">Aucun hôte actuellement connecté</string> + <string name="terminal_connecting">Connexion à %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">Clé de vérification de l\'hôte \'%1$s\' : %2$s</string> + <string name="terminal_failed">Authentification par clé échouée</string> + <string name="terminal_using_s2c_algorithm">Algorithme serveur vers client : %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algorithme client vers serveur : %1$s %2$s</string> + <string name="terminal_using_algorithm">Utilisation de l\'algorithme de chiffrement : %1$s %2$s</string> + <string name="terminal_auth">Tentative d\'authentification</string> + <string name="terminal_auth_pass">Tentative d\'authentification par mot de passe</string> + <string name="terminal_auth_pass_fail">L\'authentification par mot de passe a échoué</string> + <string name="terminal_auth_pubkey_any">Tentative d\'authentification avec une clé publique en mémoire</string> + <string name="terminal_auth_pubkey_invalid">La clé publique sélectionnée est invalide, essayez de sélectionner une clé dans les préférences de l\'hôte</string> + <string name="terminal_auth_pubkey_specific">Tentative d\'authentification par clé publique avec une clé publique spécifique</string> + <string name="terminal_auth_pubkey_fail">La méthode d\'authentification par clé publique avec la clé \'%1$s\' a échoué.</string> + <string name="terminal_auth_ki">Tentative d\'authentification par clavier</string> + <string name="terminal_auth_ki_fail">La méthode d\'authentification par clavier a échouée</string> + <string name="terminal_auth_fail">[L\'hôte ne supporte pas l\'authentification par mot de passe ou par clavier.]</string> + <string name="terminal_no_session">La session ne sera pas démarrée à cause des préférences de l\'hôte.</string> + <string name="terminal_enable_portfoward">Activer la redirection de port : %1$s</string> + <string name="local_shell_unavailable">Échec ! Le shell local est indisponible pour ce téléphone.</string> + <string name="notification_text">%1$s requiert votre attention.</string> + <string name="no">Non</string> + <string name="with_confirmation">Après confirmation</string> + <string name="yes">Oui</string> + <string name="exceptions_submit_message">Il semblerait que ConnectBot ait eu un problème lors de sa dernière utilisation. Voulez-vous envoyer un rapport d\'erreur aux développeurs de ConnectBot ?</string> + <string name="menu_colors_reset">Réinitialiser</string> + <string name="app_is_running">ConnectBot est en cours</string> + <string name="color_red">rouge</string> + <string name="color_green">vert</string> + <string name="color_blue">bleu</string> + <string name="color_gray">gris</string> + <string name="colors_fg">PP :</string> + <string name="color_bg">AP :</string> + <string name="image_description_connected">Connecté</string> + <string name="image_description_key_is_locked">Clef verrouillée</string> + <string name="image_description_toggle_control_character">Activer/désactiver le caractère \"contrôle\"</string> + <string name="image_description_send_escape_character">Envoyer \"échap\"</string> + <string name="image_description_show_keyboard">Afficher le clavier.</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-gl/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Cliente SSH simple, potente e open-source</string> + <string name="title_hosts_list">Servidores</string> + <string name="title_pubkey_list">Chaves públicas</string> + <string name="title_port_forwards_list">Redirección de portos</string> + <string name="title_host_editor">Editar servidor</string> + <string name="title_help">Axuda</string> + <string name="title_colors">Cores</string> + <string name="resolve_connect">Conectar</string> + <string name="resolve_entropy">Xerar entropía</string> + <string name="menu_insert">Engadir un servidor</string> + <string name="menu_delete">Borrar servidor</string> + <string name="menu_preferences">Preferencias</string> + <string name="help_intro">Seleccione un apartado dos seguintes para máis información dun tema particular</string> + <string name="help_about">Acerca de ConnectBot</string> + <string name="help_keyboard">Teclado</string> + <string name="pubkey_generate">Xerar</string> + <string name="pubkey_import">Importar</string> + <string name="pubkey_delete">Borrar a chave</string> + <string name="pubkey_gather_entropy">Xerando Entropía</string> + <string name="pubkey_touch_prompt">Toca esta casiña para xerar aleatoriedade: %1$d%% feito</string> + <string name="pubkey_touch_hint">Para garantir aleatoriedade durante a xeración da chave, mova o dedo aleatoriamente na casiña a continuación</string> + <string name="pubkey_generating">"Xerando par de chaves…"</string> + <string name="pubkey_copy_private">Copiar chave privada</string> + <string name="pubkey_copy_public">Copiar chave pública</string> + <string name="pubkey_list_empty">Pulse Menu para crear\nou importar pares de chaves</string> + <string name="pubkey_unknown_format">Formato descoñecido</string> + <string name="pubkey_change_password">Cambiar o contrasinal</string> + <string name="pubkey_list_pick">Seleccionar da /sdcard</string> + <string name="pubkey_import_parse_problem">Problema analisando a chave privada importada</string> + <string name="pubkey_unlock">Desbloquear chave</string> + <string name="pubkey_memory_load">Cargar en memoria</string> + <string name="pubkey_memory_unload">Descargar de memoria</string> + <string name="pubkey_load_on_start">Cargar chave ao iniciar</string> + <string name="pubkey_confirm_use">Confirmar antes de usar</string> + <string name="portforward_list_empty">Pulsar Menu para crear\nredireccións de portos</string> + <string name="portforward_edit">Editar redirección de porto</string> + <string name="portforward_delete">Borrar redirección de porto</string> + <string name="prompt_nickname">Seudónimo:</string> + <string name="prompt_nickname_hint_pubkey">A miña chave do traballo</string> + <string name="prompt_source_port">Porto orixe:</string> + <string name="prompt_destination">Destino:</string> + <string name="prompt_old_password">Contrasinal antigo:</string> + <string name="prompt_password">Contrasinal:</string> + <string name="prompt_again">(de novo)</string> + <string name="prompt_type">Tipo:</string> + <string name="prompt_password_can_be_blank">Nota: o contrasinal pode quedar baleiro</string> + <string name="host_verification_failure_warning_header">¡ATENCIÓN: A IDENTIFICACIÓN DO EQUIPO REMOTO CAMBIOU!</string> + <string name="host_verification_failure_warning">¡É POSIBLE QUE HAXA ALGUÉN FACENDO ALGO INAXEITADO!\n¡Alguén podería estar intervindo neste momento (cun ataque man-in-the-middle)!\nTamén é posible que a chave do equipo simplemente cambiara.</string> + <string name="prompt_host_disconnected">O equipo desconectouse.\n¿Pechar a sesión?</string> + <string name="prompt_continue_connecting">Seguro que quere\ncontinuar conectándose?</string> + <string name="alert_passwords_do_not_match_msg">¡Non coinciden os contrasinais!</string> + <string name="alert_wrong_password_msg">¡Contrasinal incorrecto!</string> + <string name="alert_key_corrupted_msg">¡A chave privada parece corrupta!</string> + <string name="alert_sdcard_absent">¡A tarxeta SD non está inserida!</string> + <string name="button_add">Engadir</string> + <string name="button_change">Modificar</string> + <string name="button_generate">Xerar chave</string> + <string name="button_resize">Redimensionar</string> + <string name="alert_disconnect_msg">Conexión Perdida</string> + <string name="pref_emulation_category">Emulación de terminal</string> + <string name="pref_emulation_title">Modo de emulación</string> + <string name="pref_emulation_summary">Modo de emulación de terminal para usar en conexións PTY</string> + <string name="pref_scrollback_title">Tamaño de navegación</string> + <string name="pref_scrollback_summary">Tamaño de búfer que quedará en memoria para cada consola</string> + <string name="pref_ui_category">Interface de usuario</string> + <string name="pref_rotation_title">Modo de rotación</string> + <string name="pref_rotation_summary">Como cambiar a rotación ao abrir/pechar o teclado</string> + <string name="pref_fullscreen_title">Pantalla completa</string> + <string name="pref_fullscreen_summary">Esconder a barra de estado cando estea na consola</string> + <string name="pref_memkeys_title">Recordar chaves en memoria</string> + <string name="pref_memkeys_summary">Manter chaves desbloqueadas en memoria ata que o servicio de backend teña terminado</string> + <string name="pref_update_title">Comprobar actualizacións</string> + <string name="pref_update_summary">Establecer a frecuencia máxima para comprobar as actualizacións de ConnectBot</string> + <string name="pref_conn_persist_title">Conexións persistentes</string> + <string name="pref_conn_persist_summary">Manter conexións activas en segundo plano</string> + <string name="pref_keymode_title">Atallos de teclado para directorios</string> + <string name="pref_camera_title">Atallo de teclado para a cámara</string> + <string name="pref_keepalive_title">Manter pantalla activa</string> + <string name="pref_keepalive_summary">Evitar que a pantalla se apague ao traballar nunha consola</string> + <string name="pref_wifilock_title">Manter a Wi-Fi activa</string> + <string name="pref_wifilock_summary">Evitar que a Wi-Fi se apague mentres a sesión está activa</string> + <string name="pref_bumpyarrows_summary">Vibrar ao enviar teclas de dirección dende o trackball; útil para conexións con retardos</string> + <string name="pref_bell_category">Timbre do terminal</string> + <string name="pref_bell_title">Timbre audible</string> + <string name="pref_bell_volume_title">Volume do timbre</string> + <string name="pref_bell_vibrate_title">Vibrar co timbre</string> + <string name="pref_bell_notification_title">Notificacións en segundo plano</string> + <string name="list_keymode_none">Deshabilitar</string> + <string name="list_pubkeyids_none">Non usar chaves</string> + <string name="list_pubkeyids_any">Usar calquera chave desbloqueada</string> + <string name="hostpref_fontsize_title">Tamaño da fonte (pt)</string> + <string name="hostpref_postlogin_summary">Comandos a executar no servidor remoto unha vez autenticado</string> + <string name="hostpref_compression_title">Compresión</string> + <string name="hostpref_compression_summary">Esto podería axudar en redes lentas</string> + <string name="hostpref_wantsession_title">Comezar sesión de shell</string> + <string name="hostpref_encoding_title">Codificación</string> + <string name="hostpref_encoding_summary">Codificación de caracteres para a máquina remota</string> + <string name="hostpref_connection_category">Configuracion da conexión</string> + <string name="hostpref_username_title">Nome de usuario</string> + <string name="hostpref_hostname_title">Máquina</string> + <string name="hostpref_port_title">Porto</string> + <string name="bind_never">Nunca conectado</string> + <string name="bind_minutes">Hai %1$s minutos</string> + <string name="bind_hours">Hai %1$s horas</string> + <string name="bind_days">Hai %1$s días</string> + <string name="console_copy_done">Copiados %1$d bytes ao portapapeis</string> + <string name="console_copy_start">Tocar e arrastrar\nou usar o cursor direccional\npara seleccionar a área a copiar</string> + <string name="console_menu_close">Pechar</string> + <string name="console_menu_copy">Copiar</string> + <string name="console_menu_paste">Pegar</string> + <string name="console_menu_portforwards">Redirección de portos</string> + <string name="console_menu_resize">Forzar tamaño</string> + <string name="console_menu_urlscan">Escanear URLs</string> + <string name="portforward_remote">Remoto</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-he/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">לקוח SSH פשוט, עצמתי ובקוד פתוח.</string> + <string name="service_desc">מתפעל חיבורי SSH ומפתחות ציבוריים שנטענים</string> + <string name="title_hosts_list">מארחים</string> + <string name="title_pubkey_list">מפתחות ציבוריים</string> + <string name="title_port_forwards_list">הפניית פתחות</string> + <string name="title_host_editor">עריכת מארח</string> + <string name="title_help">עזרה</string> + <string name="title_colors">צבעים</string> + <string name="resolve_connect">התחברות</string> + <string name="resolve_entropy">נאסף גיבוב</string> + <string name="menu_insert">הוספת מארח</string> + <string name="menu_delete">מחיקת מארח</string> + <string name="menu_preferences">העדפות</string> + <string name="help_intro">נא לבחור נושא להלן לקבל פרטים נוספים בנוגע לנושא מסוים.</string> + <string name="help_about">על אודות ConnectBot</string> + <string name="help_keyboard">מקלדת</string> + <string name="pubkey_generate">יצירה</string> + <string name="pubkey_import">יבוא</string> + <string name="pubkey_delete">מחיקת מפתח</string> + <string name="pubkey_gather_entropy">נאסף גיבוב</string> + <string name="pubkey_touch_prompt">יש לגעת בתיבה זו כדי לאסוף נתונים אקראיים: %1$d%% הושלמו</string> + <string name="pubkey_touch_hint">כדי להבטיח את האקראיות במהלך יצירת המפתח, עליך להעביר את האצבע באקראיות על התיבה שלהלן.</string> + <string name="pubkey_generating">צמד המפתחות נוצר...</string> + <string name="pubkey_copy_private">העתקת המפתח הפרטי</string> + <string name="pubkey_copy_public">העתקת המפתח הציבורי</string> + <string name="pubkey_list_empty">יש לגעת ב„תפריט“ כדי ליצור\nאו לייבא צמדי מפתחות.</string> + <string name="pubkey_unknown_format">מבנה בלתי ידוע</string> + <string name="pubkey_change_password">החלפת הססמה</string> + <string name="pubkey_list_pick">בחירה מ־/sdcard</string> + <string name="pubkey_import_parse_problem">אירעה תקלה בעת ניתוח המפתח הפרטי שייובא</string> + <string name="pubkey_unlock">שחרור המפתח</string> + <string name="pubkey_failed_add">הססמה עבור המפתח \'%1$s\' שגויה. האימות נכשל.</string> + <string name="pubkey_memory_load">טעינה לזיכרון</string> + <string name="pubkey_memory_unload">פריקה מהזיכרון</string> + <string name="pubkey_load_on_start">טעינת המפתח עם ההפעלה</string> + <string name="pubkey_confirm_use">לאמת לפני השימוש</string> + <string name="portforward_list_empty">יש לגעת ב„תפריט“ כדי ליצור\nהפניית פתחות.</string> + <string name="portforward_edit">עריכת הפניית הפתחות</string> + <string name="portforward_delete">מחיקת הפניית הפתחות</string> + <string name="prompt_nickname">כינוי:</string> + <string name="prompt_nickname_hint_pubkey">המפתח בעבודה שלי</string> + <string name="prompt_source_port">פתחת המקור:</string> + <string name="prompt_destination">יעד:</string> + <string name="prompt_old_password">ססמה ישנה:</string> + <string name="prompt_password">ססמה:</string> + <string name="prompt_again">(שוב)</string> + <string name="prompt_type">סוג:</string> + <string name="prompt_password_can_be_blank">הערה: הססמה יכולה להישאר ריקה</string> + <string name="prompt_bits">סיביות:</string> + <string name="prompt_pubkey_password">ססמה עבור המפתח \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">האם לאפשר למארח המרוחק\nלהשתמש במפתח \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">אזהרה: זיהוי המארח המרוחק השתנה!</string> + <string name="host_verification_failure_warning">יתכן שמישהו עושה טריק מלוכלך!\nיכול להיות שמישהו מנסה לצוטט לך ברגעים אלה (מתקפת סוכן אמצע)!\nיכול גם להיות שמפתח המארח הוחלף.</string> + <string name="prompt_host_disconnected">המארח התנתק.\nלסגור את החלון?</string> + <string name="prompt_continue_connecting">האם אכן\nלהמשיך בהליך החיבור?</string> + <string name="host_authenticity_warning">לא ניתן לאמת את אותנטיות המארח\'%1$s\'.</string> + <string name="host_fingerprint">טביעת האצבע של המפתח שלהמארח %1$s היא %2$s</string> + <string name="alert_passwords_do_not_match_msg">הססמאות אינן תואמות!</string> + <string name="alert_wrong_password_msg">ססמה שגויה!</string> + <string name="alert_key_corrupted_msg">המפתח הפרטי נראה פגום!</string> + <string name="alert_sdcard_absent">לא הוכנס כרטיס SD!</string> + <string name="button_add">הוספה</string> + <string name="button_change">החלפה</string> + <string name="button_generate">יצירת מפתח</string> + <string name="button_resize">שינוי גודל</string> + <string name="alert_disconnect_msg">החיבור אבד</string> + <string name="pref_emulation_category">הדמיית מסוף</string> + <string name="pref_emulation_title">מצב הדמיה</string> + <string name="pref_emulation_summary">מצב הדמיית מסוף לשימוש בחיבורי PTY</string> + <string name="pref_scrollback_title">גודל גלילה אחורה</string> + <string name="pref_scrollback_summary">גודל מטמון הגלילה שיישאר בזיכרון בכל מסוף</string> + <string name="pref_ui_category">מנשק משתמש</string> + <string name="pref_rotation_title">מצב סיבוב</string> + <string name="pref_rotation_summary">כיצד לשנות את הסיבוב כאשר המקלדת עולה/יורדת</string> + <string name="pref_fullscreen_title">מסך מלא</string> + <string name="pref_fullscreen_summary">להסתיר את שורת המצב בעת השימוש במסוף</string> + <string name="pref_memkeys_title">לשמור את המפתחות בזיכרון</string> + <string name="pref_memkeys_summary">להשאיר את המפתחות לאחר השחרור בזיכרון עד ששירות המנגנון מושבת</string> + <string name="pref_update_title">בדיקת עדכון</string> + <string name="pref_update_summary">הגדרת התדירות המרבית לבדיקת עדכונים של ConnectBot</string> + <string name="pref_conn_persist_title">חיבורים עיקשים</string> + <string name="pref_conn_persist_summary">לשמור על החיבורים פעילים ברקע</string> + <string name="pref_keymode_title">קיצורי ספריות</string> + <string name="pref_keymode_summary">ניתן לבחור כיצד להשתמש ב־Alt לטובת \'/\' וב־Shift לטובת Tab</string> + <string name="pref_camera_title">קיצור דרך מצלמה</string> + <string name="pref_camera_summary">ניתן לבחור איזה קיצור דרך יופעל בעת לחיצה על לחצן המצלמה</string> + <string name="pref_keepalive_title">להשאיר את המסך פעיל</string> + <string name="pref_keepalive_summary">למנוע את כיבוי המסך בעת העבודה עם המסוף</string> + <string name="pref_wifilock_title">להשאיר את הרשת האלחוטית פעילה</string> + <string name="pref_wifilock_summary">למנוע את כיבוי מתאם הרשת האלחוטית כאשר ישנו חלון פעיל</string> + <string name="pref_bumpyarrows_title">חצים עם רטט</string> + <string name="pref_bumpyarrows_summary">המכשיר ירטוט בעת שליחת מקשי חצים מכדור הגלילה; שימוש לחיבורים אטיים</string> + <string name="pref_bell_category">פעמון מסוף</string> + <string name="pref_bell_title">פעמון עם צליל</string> + <string name="pref_bell_volume_title">עצמת הפעמון</string> + <string name="pref_bell_vibrate_title">רטט עם הפעמון</string> + <string name="pref_bell_notification_title">התרעות ברקע</string> + <string name="pref_bell_notification_summary">שליחת התרעה כאשר מסוף שפעיל ברקע מצלצל בפעמון.</string> + <string name="list_keymode_right">שימוש במקשים מימין</string> + <string name="list_keymode_left">שימוש במקשים משמאל</string> + <string name="list_keymode_none">נטרול</string> + <string name="list_pubkeyids_none">לא להשתמש במפתחות</string> + <string name="list_pubkeyids_any">שימוש במפתח כלשהו שאינו נעול</string> + <string name="hostpref_nickname_title">כינוי</string> + <string name="hostpref_color_title">קטגוריית הצבע</string> + <string name="hostpref_fontsize_title">גודל הגופן (נק׳)</string> + <string name="hostpref_pubkeyid_title">שימוש באימות מפתח ציבורי</string> + <string name="hostpref_authagent_title">שימוש בסוכן אימות SSH</string> + <string name="hostpref_postlogin_title">אוטומציה שלאחר הכניסה</string> + <string name="hostpref_postlogin_summary">פקודות להפעלה בשרת המרוחק לאחר האימות</string> + <string name="hostpref_compression_title">דחיסה</string> + <string name="hostpref_compression_summary">אפשרות זו עשויה להועיל במקרה של רשתות אטיות</string> + <string name="hostpref_wantsession_title">הפעלת חלון מעטפת</string> + <string name="hostpref_wantsession_summary">ניתן לנטרל אפשרות זו כדי להשתמש בהפניית פתחות בלבד</string> + <string name="hostpref_stayconnected_title">להשאיר את החיבור פעיל</string> + <string name="hostpref_stayconnected_summary">לנסות להתחבר שוב למארח לאחר ניתוק</string> + <string name="hostpref_delkey_title">מקש DEL</string> + <string name="hostpref_delkey_summary">קוד המקש בעת לחיצה על מקש ה־DEL</string> + <string name="hostpref_encoding_title">קידוד</string> + <string name="hostpref_encoding_summary">קידוד תווים בצד המארח</string> + <string name="hostpref_connection_category">הגדרות חיבור</string> + <string name="hostpref_username_title">שם משתמש</string> + <string name="hostpref_hostname_title">מארח</string> + <string name="hostpref_port_title">פתחה</string> + <string name="bind_never">לא חובר מעולם</string> + <string name="bind_minutes">לפני %1$s דקות</string> + <string name="bind_hours">לפני %1$s שעות</string> + <string name="bind_days">לפני %1$s ימים</string> + <string name="console_copy_done">הועתקו %1$d בתים ללוח הגזירים</string> + <string name="console_copy_start">יש לגעת ולגרור\nאו להשתמש בלוח כיוונים\nכדי לבחור אזור להעתקה</string> + <string name="console_menu_close">סגירה</string> + <string name="console_menu_copy">העתקה</string> + <string name="console_menu_paste">הדבקה</string> + <string name="console_menu_portforwards">הפניית פתחות</string> + <string name="console_menu_resize">אילוץ גודל</string> + <string name="console_menu_urlscan">סריקת כתובות</string> + <string name="button_yes">כן</string> + <string name="button_no">לא</string> + <string name="portforward_local">מקומי</string> + <string name="portforward_remote">מרוחק</string> + <string name="portforward_dynamic">דינמי (SOCKS)</string> + <string name="portforward_pos">יצירת הפניית פתחות</string> + <string name="portforward_done">הפניית הפתחות נוצרה בהצלחה</string> + <string name="portforward_problem">אירעה שגיאה ביצירת הפניית פתחות, יתכן שניסית להשתמש בפתחות מתחת ל־1024 או שהפתחה כבר בשימוש?</string> + <string name="portforward_menu_add">הוספת הפניית פתחות</string> + <string name="hint_userhost">user\@hostname</string> + <string name="list_format_error">יש להשתמש בצורה „%1$s“</string> + <string name="format_username">username</string> + <string name="format_hostname">hostname</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">ניהול מפתחות ציבוריים</string> + <string name="list_menu_sortcolor">סידור לפי צבע</string> + <string name="list_menu_sortname">סידור לפי שם</string> + <string name="list_menu_settings">הגדרות</string> + <string name="list_host_disconnect">ניתוק</string> + <string name="list_host_edit">עריכת מארח</string> + <string name="list_host_portforwards">עריכת הפניית פתחות</string> + <string name="list_host_delete">מחיקת מארח</string> + <string name="list_host_empty">יש להשתמש בתיבת ההתחברות המהירה\nשלהלן כדי להתחבר למארח.</string> + <string name="list_rotation_default">בררת מחדל</string> + <string name="list_rotation_land">אילוץ מצב אופקי</string> + <string name="list_rotation_port">אילוץ מצב אנכי</string> + <string name="list_rotation_auto">אוטומטי</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A ואז רווח</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">ללא</string> + <string name="list_delkey_backspace">Backspace</string> + <string name="list_delkey_del">Delete</string> + <string name="delete_message">האם אכן למחוק את \'%1$s\'?</string> + <string name="delete_pos">כן, למחוק</string> + <string name="delete_neg">ביטול</string> + <string name="wizard_agree">מוסכם</string> + <string name="wizard_next">הבא</string> + <string name="wizard_back">הקודם</string> + <string name="terminal_no_hosts_connected">אין מארחים מחוברים כרגע</string> + <string name="terminal_connecting">מתבצעת התחברות אל %1$s:%2$d דרך %3$s</string> + <string name="terminal_sucess">מפתח של המארח המאומת \'%1$s\': %2$s</string> + <string name="terminal_failed">אימות מפתח המארח נכשל.</string> + <string name="terminal_using_s2c_algorithm">אלגוריתם שרת ללקוח: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">אלגוריתם לקוח לשרת: %1$s %2$s</string> + <string name="terminal_using_algorithm">אלגוריתם בשימוש: %1$s %2$s</string> + <string name="terminal_auth">מתבצע ניסיון אימות</string> + <string name="terminal_auth_pass">מתבצע ניסיון לאימות \'ססמה\'</string> + <string name="terminal_auth_pass_fail">שיטת האימות \'ססמה\' נכשלה</string> + <string name="terminal_auth_pubkey_any">מתבצע ניסיון לאימות \'מפתח ציבורי\' עם מפתחות ציבוריים כלשהם מהזיכרון</string> + <string name="terminal_auth_pubkey_invalid">המפתח הציבורי שנבחר שגוי, כדאי לנסות לבחור מחדש מפתח בעורך המארחים</string> + <string name="terminal_auth_pubkey_specific">מתבצע ניסיון לאימות \'מפתח ציבורי\' עם מפתח ציבורי מסוים</string> + <string name="terminal_auth_pubkey_fail">שיטת האימות \'מפתח ציבורי\' עם המפתח \'%1$s\' נכשלה</string> + <string name="terminal_auth_ki">מתבצע ניסיון לאימות \'פעילות-מקלדת\'</string> + <string name="terminal_auth_ki_fail">שיטת האימות \'פעילות-מקלדת\' נכשלה</string> + <string name="terminal_auth_fail">[המארח שלך אינו תומך באימות \'ססמה\' או \'פעילות-מקלדת\'.]</string> + <string name="terminal_no_session">ההפעלה לא תתחיל עקב העדפות המארח.</string> + <string name="terminal_enable_portfoward">הפעלת הפניית פתחות: %1$s</string> + <string name="local_shell_unavailable">תקלה! המעטפת המקומית אינה זמינה במכשיר זה.</string> + <string name="notification_text">ל־%1$s נדרשת תשומת הלב שלך.</string> + <string name="no">לא</string> + <string name="with_confirmation">עם אימות</string> + <string name="yes">כן</string> + <string name="exceptions_submit_message">מתברר כי חלה תקלה ב־ConnectBot במהלך ההפעלה האחרונה. האם לשלוח את הדיווח למפתחים של ConnectBot?</string> + <string name="menu_colors_reset">איפוס</string> + <string name="app_is_running">ConnectBot פעיל</string> + <string name="color_red">אדום</string> + <string name="color_green">ירוק</string> + <string name="color_blue">כחול</string> + <string name="color_gray">אפור</string> + <string name="colors_fg">קדמה:</string> + <string name="color_bg">רקע:</string> + <string name="image_description_connected">יש חיבור.</string> + <string name="image_description_key_is_locked">המפתח נעול.</string> + <string name="image_description_toggle_control_character">החלפת מצב תווי בקרה.</string> + <string name="image_description_send_escape_character">שליחת תו סליקה.</string> + <string name="image_description_show_keyboard">הצגת מקלדת.</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-hr/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Jednostavan, moćan, open.source SSH klijent.</string> + <string name="service_desc">Pamti SSH konekcije i učitane javne ključeve</string> + <string name="title_hosts_list">Računala</string> + <string name="title_pubkey_list">Javni ključevi</string> + <string name="title_port_forwards_list">Port forwards</string> + <string name="title_host_editor">Uredi Računalo</string> + <string name="title_help">Pomoć</string> + <string name="title_colors">Boje</string> + <string name="resolve_connect">Spoji se</string> + <string name="resolve_entropy">Očitaj Entropiju</string> + <string name="menu_insert">Dodaj računalo</string> + <string name="menu_delete">Obriši računalo</string> + <string name="menu_preferences">Postavke</string> + <string name="help_intro">Molim Vas za više informacija odaberite temu ispod.</string> + <string name="help_about">O ConnectBot-u</string> + <string name="help_keyboard">Tipkovnica</string> + <string name="pubkey_generate">Stvori</string> + <string name="pubkey_import">Uvoz</string> + <string name="pubkey_delete">Obriši ključ</string> + <string name="pubkey_gather_entropy">Sakupljanje Entropije</string> + <string name="pubkey_touch_prompt">Dotakni ovaj prozor za prikupljanje slučajnosti: %1$d%% gotovo</string> + <string name="pubkey_touch_hint">Da bi osigurali slučajnost, pomičite prst u različitim smjerovima unutar prozora dolje.</string> + <string name="pubkey_generating">Izrada para ključeva</string> + <string name="pubkey_copy_private">Kopiraj privatni ključ</string> + <string name="pubkey_copy_public">Kopiraj javni ključ</string> + <string name="pubkey_list_empty">Dotakni \"Meni\" za izradu\nili uvoz parova ključeva</string> + <string name="pubkey_unknown_format">Nepoznati format</string> + <string name="pubkey_change_password">Promijeni zaporku</string> + <string name="pubkey_list_pick">Odaberi iz /sdcard</string> + <string name="pubkey_import_parse_problem">Problem prilikom tumačenja uvezenog privatnog ključa</string> + <string name="pubkey_unlock">Otključaj ključ</string> + <string name="pubkey_failed_add">Pogrešna zaporka za ključ \'%1$s\'. Neuspješna autentikacija.</string> + <string name="pubkey_memory_load">Učitaj u memoriju</string> + <string name="pubkey_memory_unload">Isprazni iz memorije</string> + <string name="pubkey_load_on_start">Učitaj kluč na početku</string> + <string name="pubkey_confirm_use">Potvrda prije upotrebe</string> + <string name="portforward_list_empty">Dotakni \"Meni\" za izradu\nport forward</string> + <string name="portforward_edit">Uredi port forward</string> + <string name="portforward_delete">Obriši port forward</string> + <string name="prompt_nickname">Nadimak:</string> + <string name="prompt_nickname_hint_pubkey">Moj poslovni ključ</string> + <string name="prompt_source_port">Source port:</string> + <string name="prompt_destination">Destination:</string> + <string name="prompt_old_password">Stara zaporka:</string> + <string name="prompt_password">Zaporka</string> + <string name="prompt_again">(ponovo)</string> + <string name="prompt_type">Type:</string> + <string name="prompt_password_can_be_blank">Uputa: zaporka može biti prazna</string> + <string name="prompt_bits">Bits:</string> + <string name="prompt_pubkey_password">Zaporka za ključ \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Dopusti udaljenom računalu da\nkoristi ključ \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">UPOZORENJE: IDENTIFIKACIJA UDALJENOG RAČUNALA SE PROMIJENILA!</string> + <string name="host_verification_failure_warning">MOGUĆE JE DA NETKO RADI NEŠTO JAKO OPASNO!\nNetko vas možda prisluškuje upravo sada (man-in-the-middle attack!)\nTakođer je moguće da se ključ računala upravo promijenio.</string> + <string name="prompt_host_disconnected">Računalo se odspojilo.\nZatvori sesiju?</string> + <string name="prompt_continue_connecting">Jeste li sigurni da želite\nnastaviti sa spajanjem?</string> + <string name="host_authenticity_warning">Autentičnost računala \'%1$s\' se ne može provjeriti.</string> + <string name="host_fingerprint">%1$s ključ računala je %2$s</string> + <string name="alert_passwords_do_not_match_msg">Zaporke nisu iste!</string> + <string name="alert_wrong_password_msg">Kriva zaporka!</string> + <string name="alert_key_corrupted_msg">Privatni ključ je oštećen!</string> + <string name="alert_sdcard_absent">SD kartica nije umetnuta!</string> + <string name="button_add">Dodaj</string> + <string name="button_change">Promijeni</string> + <string name="button_generate">Izradi ključ</string> + <string name="button_resize">Promijeni veličinu</string> + <string name="alert_disconnect_msg">Veza prekinuta</string> + <string name="pref_emulation_category">Emulacija Terminala</string> + <string name="pref_emulation_title">Način emulacije</string> + <string name="pref_emulation_summary">Način emulacije terminala korišten za PTY veze</string> + <string name="pref_scrollback_title">Veličina ScrollBack-a</string> + <string name="pref_scrollback_summary">Veličina ScrollBack-a koja se čuva u memoriji za svaku konzolu</string> + <string name="pref_ui_category">Korisničko sučelje</string> + <string name="pref_rotation_title">Način rotacije</string> + <string name="pref_rotation_summary">Kako promijeniti rotaciju kada se tipkovnica pojavi/nestane</string> + <string name="pref_fullscreen_title">Cijeli zaslon</string> + <string name="pref_fullscreen_summary">Sakrij statusnu liniju u konzoli</string> + <string name="pref_memkeys_title">Zapamti ključeve u memoriji</string> + <string name="pref_memkeys_summary">Čuvaj otključane ključeve u memoriji dok se ne zatvori pozadinski servis</string> + <string name="pref_update_title">Provjera nadogradnji</string> + <string name="pref_update_summary">Odredi učestalost za provjeru ConnectBot nadogradnji</string> + <string name="pref_conn_persist_title">Održavaj konekcije</string> + <string name="pref_conn_persist_summary">Prisili konekcije da ostanu spojene u pozadini</string> + <string name="pref_keymode_title">Prečaci direktorija</string> + <string name="pref_keymode_summary">Izaberi kako koristiti Alt kao \'/\' i Shift kao Tab</string> + <string name="pref_camera_title">Prečac kamere</string> + <string name="pref_camera_summary">Izaberi koji prečac pokrenuti kada se stisne dugme kamere</string> + <string name="pref_keepalive_title">Održi zaslon budnim</string> + <string name="pref_keepalive_summary">Spriječi gašenje zaslona dok se koristi konzola</string> + <string name="pref_wifilock_title">Održi Wi-Fi aktivnim</string> + <string name="pref_wifilock_summary">Spriječi gašenje Wi-Fi-a dok je aktivna sesija</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-hu/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,327 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Egyszerű, hatékony, nyílt-forráskódú SSH kliens.</string> + <string name="service_desc">Fenntartja az SSH kapcsolatokat és a betöltött nyilvános kulcsokat</string> + <string name="auth_agent_service_desc">ssh-agent szolgáltatás más Android Appokhoz a telefonon</string> + <string name="ssh_agent_permission_label">Tárolt SSH kulcsok használata</string> + <string name="ssh_agent_permission_desc">Engedélyezi az privát kulcsok használatát SSH tranzakciókhoz. NAGYON VESZÉLYES, ha kártékony alkalmazás is hozzáfér.</string> + <string name="title_hosts_list">Kiszolgálók</string> + <string name="title_pubkey_list">Publikus kulcsok</string> + <string name="title_port_forwards_list">Port átiránytások</string> + <string name="title_host_editor">Kiszolgáló szerkesztése</string> + <string name="title_help">Súgó</string> + <string name="title_colors">Színek</string> + <string name="resolve_connect">Csatlakozás</string> + <string name="resolve_entropy">Entrópia gyűjtés</string> + <string name="menu_insert">Kiszolgáló hozzáadása</string> + <string name="menu_delete">Kiszolgáló törlése</string> + <string name="menu_preferences">Beállítások</string> + <string name="help_intro">Válasszon témakört az alábbiak közül egy adott téma részletes leírásához.</string> + <string name="help_about">A ConnectBot névjegye</string> + <string name="help_keyboard">Billentyűzet</string> + <string name="pubkey_generate">Kulcs generálása</string> + <string name="pubkey_import">Kulcs importálása</string> + <string name="pubkey_delete">Kulcs törlésee</string> + <string name="pubkey_gather_entropy">Entrópia gyűjtés</string> + <string name="pubkey_touch_prompt">Érintse meg ezt a dobozt a véletlenszerűség gyűjtéséhez: %1$d%% kész</string> + <string name="pubkey_touch_hint">A kulcs egyediségének biztosítása érdekében mozgassa ujját véletlenszerűen az alábbi dobozban.</string> + <string name="pubkey_generating">"Kulcspár generálása…"</string> + <string name="pubkey_copy_private">Privát kulcs másolása</string> + <string name="pubkey_copy_public">Nyilvános kulcs másolása</string> + <string name="pubkey_list_empty">Nyomjon Menu-t, kulcspár\n létrehozáshoz/importáláshoz.</string> + <string name="pubkey_unknown_format">Ismeretlen formátum</string> + <string name="pubkey_change_password">Jelszócsere</string> + <string name="pubkey_list_pick">Kiválaszt /sdcard -ról</string> + <string name="pubkey_import_parse_problem">Probléma a privát kulcs feldolgozása során</string> + <string name="pubkey_unlock">Kulcs feloldása</string> + <string name="pubkey_failed_add">Hibás jelszó a \'%1$s\' kulcshoz. Sikertelen azonosítás.</string> + <string name="pubkey_memory_load">Betöltés a memóriába</string> + <string name="pubkey_memory_unload">Mermória ürítése</string> + <string name="pubkey_load_on_start">Kulcs betöltése induláskor</string> + <string name="pubkey_confirm_use">Jóváhagyás használat előtt</string> + <string name="portforward_list_empty">Nyomjon Menu-t a port\nátirányításhoz.</string> + <string name="portforward_edit">Port átirányítás módosítása</string> + <string name="portforward_delete">Port átirányítás törlése</string> + <string name="prompt_nickname">Becenév:</string> + <string name="prompt_nickname_hint_pubkey">A munkahelyi kulcsom</string> + <string name="prompt_source_port">Forrás port:</string> + <string name="prompt_destination">Cél port:</string> + <string name="prompt_old_password">Régi jelszó:</string> + <string name="prompt_password">Jelszó:</string> + <string name="prompt_again">(újra)</string> + <string name="prompt_type">Típus:</string> + <string name="prompt_password_can_be_blank">Tipp: a jelszóadás nem kötelező</string> + <string name="prompt_bits">Bitek:</string> + <string name="prompt_pubkey_password">A \'%1$s\' kulcs jelszava</string> + <string name="prompt_allow_agent_to_use_key">A \'%1$s\' kulcs engedélyezése\na távoli gépnek?</string> + <string name="host_verification_failure_warning_header">FIGYELEM: A TÁVOLI GÉP AZONOSÍTÓJA MEGVÁLTOZOTT!</string> + <string name="host_verification_failure_warning">FELTEHETŐEN VALAKI GYANÚS DOLGOKAT MŰVEL! \nValaki feltehetően megpróbál lehallgatni (man-in-the-middle attack) téged! \\ nDe az is lehetséges, hogy a távoli fél kulcsa közben megváltozott.</string> + <string name="prompt_host_disconnected">A kapcsolat megszakadt.\nBezárja a folyamatot?</string> + <string name="prompt_continue_connecting">Biztosan folytatja a csatlakozást?</string> + <string name="host_authenticity_warning">A \'%1$s\' kiszolgáló azonosítása sikertelen.</string> + <string name="host_fingerprint">A %1$s kulcs ujjlenyomata a(-z) %2$s</string> + <string name="alert_passwords_do_not_match_msg">Nem egyezik a jelszó!</string> + <string name="alert_wrong_password_msg">Hibás jelszó!</string> + <string name="alert_key_corrupted_msg">Sérült privát kulcs!</string> + <string name="alert_sdcard_absent">Nincs SD kártya!</string> + <string name="button_add">Hozzáadás</string> + <string name="button_change">Módosítás</string> + <string name="button_generate">Kulcs generálása</string> + <string name="button_resize">Átméretezés</string> + <string name="button_resize_reset">Alapértelmezett méret</string> + <string name="alert_disconnect_msg">A kapcsolat megszakadt</string> + <string name="pref_emulation_category">Terminál emulálás</string> + <string name="pref_emulation_title">Emulálási mód</string> + <string name="pref_emulation_summary">Terminál emulálási mód PTY kapcsolatokhoz</string> + <string name="pref_scrollback_title">Előzmények mérete</string> + <string name="pref_scrollback_summary">Az előzmények memóriában tartandó mérete konzolonként</string> + <string name="pref_ui_category">Felhasználói felület</string> + <string name="pref_rotation_title">Forgatási mód</string> + <string name="pref_rotation_summary">Hogyan forduljon a kijelző a billentyűzet ki/becsukása során</string> + <string name="pref_memkeys_title">Kulcsok megőrzése a memóriában</string> + <string name="pref_memkeys_summary">Tartsa nyitva a memóriában lévő kulcsokat amíg a háttérszolgáltatás meg nem szűnik</string> + <string name="pref_update_title">Frissítés ellenőrzése</string> + <string name="pref_update_summary">ConnectBot frissítés ellenőrzésének maximális gyakorisága</string> + <string name="pref_conn_persist_title">Kapcsolatok fenntartása</string> + <string name="pref_conn_persist_summary">A háttérben tartsa fenn a kapcsolatokat</string> + <string name="pref_keymode_title">Könyvtár hivatkozások</string> + <string name="pref_keymode_summary">Válassza ki, hogyan kell használni az Alt-ot\n a \'/\' helyett és a Shift-et a Tab helyett</string> + <string name="pref_camera_title">Kamera gomb hivatkozás</string> + <string name="pref_camera_summary">Válassza ki a kamera gombhoz tartozó hivatkozást</string> + <string name="pref_keepalive_title">Tartsa ébren a képernyőt</string> + <string name="pref_keepalive_summary">Akadályozza meg a képernyővédő bekapcsolását konzolon végzett munka alatt</string> + <string name="pref_wifilock_title">Tartsa fenn a Wi-Fi kapcsolatot</string> + <string name="pref_wifilock_summary">Akadályozza meg a Wi-Fi kikapcsolását amíg a munka zajlik</string> + <string name="pref_bumpyarrows_title">Ugráló nyilak</string> + <string name="pref_bumpyarrows_summary">Vibráljon amikor a hanyattegérrel mozgatjuk a kurzort; hasznos lehet lassú kapcsolatoknál</string> + <string name="pref_bell_category">Terminál csengő</string> + <string name="pref_bell_title">Hallható csengő</string> + <string name="pref_bell_volume_title">Csengő hangereje</string> + <string name="pref_bell_vibrate_title">Vibráljon csengetéskor</string> + <string name="pref_bell_notification_title">Háttér figyelmeztetések</string> + <string name="pref_bell_notification_summary">Küldjön értesítőt amikor a háttérben futó terminál csenget.</string> + <string name="list_keymode_right">A jobboldali gombok használata</string> + <string name="list_keymode_left">A baloldali gombok használata</string> + <string name="list_keymode_none">Tiltás</string> + <string name="list_pubkeyids_none">Kulcsok használatának tiltása</string> + <string name="list_pubkeyids_any">Bármely kinyitott privátkulcs használata</string> + <string name="hostpref_nickname_title">Becenév</string> + <string name="hostpref_color_title">Szín-kategória</string> + <string name="hostpref_fontsize_title">Betűtipus mérete (pt)</string> + <string name="hostpref_pubkeyid_title">Nyilvános kulcs használata azonosításhoz</string> + <string name="hostpref_authagent_title">Az SSH auth agent használata</string> + <string name="hostpref_postlogin_title">Bejelentkezést követő automatikus parancsok</string> + <string name="hostpref_postlogin_summary">Olyan parancsok amelyek a bejelentkezést követően kerülnek futtatásra</string> + <string name="hostpref_compression_title">Tömörítés</string> + <string name="hostpref_compression_summary">Jól jöhet lassú házatok esetén</string> + <string name="hostpref_stayconnected_title">Maradjon csatlakozva</string> + <string name="hostpref_stayconnected_summary">Újracsatlakozás ha a kapcsolat megszakad</string> + <string name="hostpref_delkey_title">DEL billentyű</string> + <string name="hostpref_delkey_summary">Az a billenytű kód amit a DEL lenyomásakor küldünk</string> + <string name="hostpref_encoding_title">Karakterkódolás</string> + <string name="hostpref_encoding_summary">A kiszolgáló karakterkódolása</string> + <string name="hostpref_connection_category">Kapcsolat beállításai</string> + <string name="hostpref_username_title">Felhasználónév</string> + <string name="hostpref_hostname_title">Kiszolgáló</string> + <string name="hostpref_port_title">Port</string> + <string name="bind_never">Még nem csatlakozott</string> + <string name="bind_minutes">%1$s perce</string> + <string name="bind_hours">%1$s órája</string> + <string name="bind_days">%1$s napja</string> + <string name="console_copy_done">%1$d bájt a vágólapra másolva</string> + <string name="console_copy_start">Érintéssel és húzással\nvagy a hanyattegér használatával\njelölje ki a másolandó területet.</string> + <string name="console_menu_close">Bezárás</string> + <string name="console_menu_copy">Másolás</string> + <string name="console_menu_paste">Beillesztés</string> + <string name="console_menu_portforwards">Port átirányítások</string> + <string name="console_menu_resize">Méret kényszerítése</string> + <string name="console_menu_urlscan">URL Keresés</string> + <string name="console_menu_screencapture">Képernyőkép készítése</string> + <string name="console_menu_download">Fájl letöltése</string> + <string name="console_menu_upload">Fájl feltöltése</string> + <string name="button_yes">Igen</string> + <string name="button_no">Nem</string> + <string name="portforward_local">Helyi</string> + <string name="portforward_remote">Távoli</string> + <string name="portforward_dynamic">Dinamikus (SOCKS)</string> + <string name="portforward_pos">Port átirányítás létrehozása</string> + <string name="portforward_done">Sikeres port átirányítás</string> + <string name="portforward_problem">Probléma a port átirányítás létrehozása során, 1024 alatti vagy már használatban lévő portot választott?</string> + <string name="portforward_menu_add">Port átirányítás hozzáadása</string> + <string name="hint_userhost">felhasználó\@gépnév</string> + <string name="list_format_error">A %1$s formátum használata</string> + <string name="format_username">felhasználónév</string> + <string name="format_hostname">gépnév</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Publikus kulcsok kezelése</string> + <string name="list_menu_sortcolor">Rendezés szín szerint</string> + <string name="list_menu_sortname">Rendezés név szerint</string> + <string name="list_menu_settings">Beállítások</string> + <string name="list_host_disconnect">A kapcsolat bontása</string> + <string name="list_host_edit">Kiszolgáló szerkesztése</string> + <string name="list_host_portforwards">Port átirányítások szerkesztése</string> + <string name="list_host_delete">Kiszolgáló törlése</string> + <string name="list_host_empty">Használja a gyors csatlakozás dobozt\n a csatlakozáshoz.</string> + <string name="list_rotation_default">Alapbeállitás</string> + <string name="list_rotation_land">Fekvő mód kényszerítése</string> + <string name="list_rotation_port">Álló mód kényszerítése</string> + <string name="list_rotation_auto">Automatikus</string> + <string name="list_hwbutton_screen_capture">Képernyőkép készítése</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A majd Space</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Semmi</string> + <string name="list_delkey_backspace">Backspace</string> + <string name="list_delkey_del">Delete</string> + <string name="delete_message">Biztosan törli a \'%1$s\'-t?</string> + <string name="delete_pos">Igen, törlés</string> + <string name="delete_neg">Mégsem</string> + <string name="wizard_agree">Elfogad</string> + <string name="wizard_next">Következő</string> + <string name="wizard_back">Vissza</string> + <string name="terminal_no_hosts_connected">Nincs kiszolgáló csatlakozva</string> + <string name="terminal_connecting">Csatlakozás %1$s:%2$d-hoz a %3$s protokollon</string> + <string name="terminal_sucess">Azonosított \'%1$s\' gépnév kulcsa: %2$s</string> + <string name="terminal_failed">Távoli gép, kulcs azonosítása sikertelen.</string> + <string name="terminal_using_s2c_algorithm">Szerver-kliens algoritmus: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Kliens-szerver algoritmus: %1$s %2$s</string> + <string name="terminal_using_algorithm">Használt algoritmus: %1$s %2$s</string> + <string name="terminal_auth">Azonosítási probálkozás</string> + <string name="terminal_auth_pass">Próbálkozás \'password\' azonosítással</string> + <string name="terminal_auth_pass_fail">A \'password\' azonosítás sikertelen.</string> + <string name="terminal_auth_pubkey_any">Próbálkozás \'publickey\' azonosítással, bármely memóriában található nyilvános kulccsal</string> + <string name="terminal_auth_pubkey_invalid">A nyilvános kulcs hibás, próbálja újra kiválasztani a kiszolgáló kezelőből</string> + <string name="terminal_auth_pubkey_specific">Próbálkozás \'publickey\' azonosítással, választott nyilvános kulccsal</string> + <string name="terminal_auth_pubkey_fail">A \'%1$s\' kulccsal történt \'publickey\' azonosítás sikertelen.</string> + <string name="terminal_auth_ki">Próbálkozás \'keyboard-interactive\' azonosítással</string> + <string name="terminal_auth_ki_fail">\'keyboard-interactive\' azonosítás sikertelen</string> + <string name="terminal_auth_fail">[A gépnév nem támogatja a \'password\' vagy \'keyboard-interactive\' azonosítást.]</string> + <string name="terminal_no_session">A munkamenet nem kezdhető el a távoli kiszolgáló beállításai miatt.</string> + <string name="terminal_enable_portfoward">Port átirányítás engedélyezése: %1$s</string> + <string name="local_shell_unavailable">Hiba! Nem elérhető a helyi shell ezen a telefonon.</string> + <string name="notification_text">%1$s a figyelmét kéri.</string> + <string name="no">Nem</string> + <string name="with_confirmation">Csak beleegyezéssel</string> + <string name="yes">Igen</string> + <string name="exceptions_submit_message">Úgy tűnik a ConnectBot a legutóbbi futtatáskor összeomlott. Elküldi a hibanaplót a ConnectBot fejleszőinek?</string> + <string name="menu_colors_reset">Visszaállít</string> + <string name="app_is_running">ConnectBot már fut</string> + <string name="color_red">piros</string> + <string name="color_green">zöld</string> + <string name="color_blue">kék</string> + <string name="color_gray">szürke</string> + <string name="colors_fg">"Előtér":</string> + <string name="color_bg">"Háttér:"</string> + <string name="image_description_connected">"Csatlakoztatva."</string> + <string name="image_description_key_is_locked">"Billentyűzet lezárva."</string> + <string name="image_description_toggle_control_character">Vezérlőkarakter kapcsolása.</string> + <string name="image_description_send_escape_character">Escape karakter küldése.</string> + <string name="image_description_show_keyboard">Billentyűzet megjelenítése.</string> + <string name="image_description_line_input">Egysoros bevitel</string> + <string name="image_description_sym">Karakterválasztó ablak</string> + <string name="button_close">Bezárás</string> + <string name="pref_custom_keymap_title">Egyedi kiosztás</string> + <string name="pref_custom_keymap_summary">Egyedi kiosztás beállítása bizonyos billentyűkre támogatott készülékek esetén.</string> + <string name="pref_custom_keymap_disabled">kikapcsolva</string> + <string name="resize_error_title">Hiba az átméretezés során</string> + <string name="resize_error_width_height">A szélességnek és a magasságnak 0-nál nagyobbnak kell lennie.</string> + <string name="dia_resize_x">x</string> + <string name="pref_screen_capture_category">Képernyőmentés</string> + <string name="pref_screen_capture_folder">Képernyőmentés mappája</string> + <string name="pref_screen_capture_folder_summary">A mappa, ahova a lementett képernyőképek kerülnek.</string> + <string name="pref_screen_capture_popup">Képernyőmentés visszajelzés</string> + <string name="pref_screen_capture_popup_summary">Sikeres képernyőképmentés készítésekor felugró ablak.</string> + <string name="screen_capture">Képernyőmentés</string> + <string name="screenshot_success_title">Sikeres képernyőmentés</string> + <string name="screenshot_saved_as">A képernyőkép mentve:</string> + <string name="screenshot_error_title">Hiba a képernyőkép készítése közben!</string> + <string name="screenshot_not_saved_as">A képernyőképet nem sikerült menteni:</string> + <string name="pref_picker_string">Sym ablak tartalma</string> + <string name="pref_picker_string_summary">Karakterem sorozat a karakterválasztó ablakhoz</string> + <string name="pref_picker_keep_open">Sym ablak nyitva tartása</string> + <string name="pref_picker_keep_open_summary">Csak a Vissza gomb zárja be a karakterválasztó ablakot.</string> + <string name="pref_file_transfer_category">Fájlátvitel</string> + <string name="pref_file_dialog_title">Fájl kijelölés</string> + <string name="pref_file_dialog_summary">Párbeszéd ablak fájlok és mappák kijelöléséhez</string> + <string name="pref_file_dialog_builtin">beépített</string> + <string name="error_starting_app">Hiba indításkor %1$s</string> + <string name="file_chooser_select_file">Válasszon fájlt %1$s</string> + <string name="select_for_download">letöltéshez</string> + <string name="select_for_upload">feltöltéshez</string> + <string name="select_for_key_import">kulcsimportáláshoz</string> + <string name="location">Hely</string> + <string name="cant_read_folder">Nem olvasható a mappa.</string> + <string name="nnew">Új</string> + <string name="select">Válasszon</string> + <string name="file_name">Fájlnév:</string> + <string name="cancel">Mégsem</string> + <string name="save">Mentés</string> + <string name="new_file">Új fájl</string> + <string name="no_data">Nincs adat</string> + <string name="pref_download_folder">Letöltési mappa</string> + <string name="pref_download_folder_summary">Az a mappa, ahova a letöltött fájlok kerülnek</string> + <string name="pref_remote_upload_folder">Távoli feltöltési mappa</string> + <string name="pref_remote_upload_folder_summary">Az a távoli mappa, ahova a feltöltött fájlok kerülnek</string> + <string name="pref_upload_dest_prompt">Rákérdezés a távoli mappára</string> + <string name="pref_upload_dest_prompt_summary">Rákérdez arra a távoli mappára, ahova a fájl fel fog töltődni.</string> + <string name="pref_background_file_transfer">Fájlátvitel a háttérben</string> + <string name="pref_background_file_transfer_summary">A fájlok fel- és letöltése a háttérben zajlik.</string> + <string name="transfer_downloading">Fájl letöltése…</string> + <string name="transfer_downloading_file">Fájl letöltése: %1$s</string> + <string name="transfer_download_complete">A fájl letöltése kész.</string> + <string name="transfer_download_failed">A fájl letöltése nem sikerült.</string> + <string name="transfer_select_remote_download_title">Fájl(ok) letöltése</string> + <string name="transfer_select_remote_download_desc">Adja meg a letöltendő fájlok elérési útvonalát (soronként egy fájl)</string> + <string name="transfer_select_remote_upload_dest_title">Feltöltési cél</string> + <string name="transfer_select_remote_upload_dest_desc">Adja meg a kívánt távoli fájlnevet:</string> + <string name="transfer_button_download">Letöltés</string> + <string name="transfer_button_upload">Feltöltés</string> + <string name="transfer_uploading">Feltöltés…</string> + <string name="transfer_uploading_file">Fájl feltöltés: %1$s</string> + <string name="transfer_upload_complete">Fájlfeltöltés kész.</string> + <string name="transfer_upload_failed">Fájlfeltöltés nem sikerült.</string> + <string name="pubkey_export_private">Privát kulcs exportálása</string> + <string name="pubkey_export_public">"Publikus kulcs exportálása"</string> + <string name="pubkey_public_save_as">Publikus kulcs mentése</string> + <string name="pubkey_public_save_as_desc">Fájlnév (teljes elérési útvonal), ahova a publikus kulcsot menteni szeretné.</string> + <string name="pubkey_private_save_as">Privát kulcs mentése</string> + <string name="pubkey_private_save_as_desc">Fájlnév (teljes elérési útvonal), ahova a privát kulcsot menteni szeretné.</string> + <string name="pubkey_public_export_success">A publikus kulcs exportálása sikeres.</string> + <string name="pubkey_public_export_problem">Hiba a publikus kulcs exportálása során.</string> + <string name="pubkey_private_export_success">A privát kulcs exportálása sikeres.</string> + <string name="pubkey_private_export_problem">Hiba a privát kulcs exportálása során.</string> + <string name="pref_debug_category">Hibakeresési beállítások</string> + <string name="pref_debug_keycodes">Billentyűkódok kiírása</string> + <string name="pref_debug_keycodes_summary">A terminálablakban lenyomott billentyűk kódjait kiírja.</string> + <string name="keycode_pressed">A lenyomott billentyű kódja</string> + <string name="pref_extended_longpress">Bővített hosszan nyomva tartott menü</string> + <string name="pref_extended_longpress_summary">A beviteli párbeszédablakot mutatja érintés és tartás esetén.</string> + <string name="longpress_select_action">Válassza ki a műveletet</string> + <string name="longpress_enable_full_screen_mode">Teljes képernyős mód bekapcsolása</string> + <string name="longpress_disable_full_screen_mode">Teljes képernyős mód kikapcsolása</string> + <string name="longpress_change_font_size">Betűméret változtatása</string> + <string name="longpress_arrows_dialog">Nyilak</string> + <string name="longpress_fkeys_dialog">Funkcióbillentyűk</string> + <string name="longpress_ctrl_dialog">CTRL+?</string> + <string name="longpress_sym_dialog">Karakterválasztó</string> + <string name="pref_ctrl_string">CTRL ablak tartalma</string> + <string name="pref_ctrl_string_summary">Karakterek sorozata a CTRL+? kombinációkhoz.</string> + <string name="fullscreen">Teljes képernyő</string> + <string name="hostpref_wantsession_title">"Héj indítása"</string> + <string name="hostpref_wantsession_summary">"Kapcsoljuk ki, ha csak port átirányításra van szükségünk"</string> + <string name="hostpref_x11_forwarding">"X11 átirányítás"</string> + <string name="hostpref_wantx11forward_title">"X11 átirányítás bekapcsolása"</string> + <string name="hostpref_wantx11forward_summary">"X11 munkamenetek átirányítása a lentebb megadott kiszolgálóra és portra"</string> + <string name="list_hwbutton_ctrl">"CTRL"</string> + <string name="list_hwbutton_tab">"Tab"</string> + <string name="pref_custom_keymap_full">Teljes hardveres billentyűzet</string> + <string name="pref_fullscreen_title">"Teljes képernyő"</string> + <string name="pref_fullscreen_summary">"Terminál indítása teljes képernyőn"</string> + <string name="pref_search_title">"Keresés gomb"</string> + <string name="pref_search_summary">"A keresés gomb megnyomásakor végrehajtott művelet"</string> + <string name="pref_volup_title">"Hangerő fel gomb"</string> + <string name="pref_volup_summary">"A hangerő fel megnyomásakor végrehajtott művelet"</string> + <string name="pref_voldn_title">"Hangerő le gomb"</string> + <string name="pref_voldn_summary">"A hangerő le megnyomásakor végrehajtott művelet"</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-id/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,201 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Sederhana, tangguh, klien SSH dengan kode terbuka.</string> + <string name="service_desc">"Mengelola koneksi SSH dan kunci publik yang terrekam"</string> + <string name="title_hosts_list">Host</string> + <string name="title_pubkey_list">Kunci Publik</string> + <string name="title_host_editor">Ubah Host</string> + <string name="title_help">Bantuan</string> + <string name="resolve_connect">Hubungi</string> + <string name="resolve_entropy">Kumpulkan entropy</string> + <string name="menu_insert">Tambahkan host</string> + <string name="menu_delete">Hapus Host</string> + <string name="menu_preferences">Kesukaan</string> + <string name="help_intro">Silahkan pilih sebuah topik dibawah untuk informasi lebih lanjut di suatu subjek tertentu.</string> + <string name="help_about">Mengenai ConnectBot</string> + <string name="help_keyboard">Papan Ketik</string> + <string name="pubkey_generate">Buat</string> + <string name="pubkey_import">Impor</string> + <string name="pubkey_delete">Tombol Hapus</string> + <string name="pubkey_gather_entropy">Kumpulkan Entropy</string> + <string name="pubkey_touch_prompt">Sentuh boks ini untuk mengumpulkan ke tidak tentuan: %1$d%% selesai</string> + <string name="pubkey_touch_hint">Untuk memastikan ketidaktentuan selama pembuatan kunci, gerakkan tangan anda secara acak diatas kotak dibawah ini.</string> + <string name="pubkey_generating">Membuat pasangan kunci...</string> + <string name="pubkey_copy_private">Salin kunci pribadi</string> + <string name="pubkey_copy_public">Salin kunci publik</string> + <string name="pubkey_list_empty">Sentuh Menu untuk membuat/atau mengimpor pasangan kunci.</string> + <string name="pubkey_unknown_format">Format tidak diketahui</string> + <string name="pubkey_change_password">Ubah kata sandi</string> + <string name="pubkey_list_pick">Ambil dari /sdcard</string> + <string name="pubkey_import_parse_problem">Masalah dalam mengambil kunci pribadi yang terimpor</string> + <string name="pubkey_unlock">Buka kunci</string> + <string name="pubkey_failed_add">Kata sandi salah untuk kunci \'%1$s\'. Authentifikasi gagal.</string> + <string name="pubkey_memory_load">Muat ke memori</string> + <string name="pubkey_memory_unload">Hapus dari memori</string> + <string name="pubkey_load_on_start">Muat kunci pada saat memulai</string> + <string name="pubkey_confirm_use">Konfirmasi sebelum digunakan</string> + <string name="portforward_list_empty">Sentu Menu untuk membuat\nport forwards.</string> + <string name="portforward_edit">Ubah port forward</string> + <string name="portforward_delete">Hapus port forward</string> + <string name="prompt_nickname">Nama panggilan:</string> + <string name="prompt_nickname_hint_pubkey">Kunci kerja saya</string> + <string name="prompt_source_port">Port asal</string> + <string name="prompt_destination">Tujuan:</string> + <string name="prompt_old_password">Kata sandi sebelumnya:</string> + <string name="prompt_password">Kata sandi:</string> + <string name="prompt_again">(sekali lagi)</string> + <string name="prompt_type">Tipe:</string> + <string name="prompt_password_can_be_blank">Catatan: sandi dapat dikosongkan</string> + <string name="prompt_bits">Jumlah bit:</string> + <string name="prompt_pubkey_password">Kata sandi untuk kunci \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Ijinkan remote host untuk\nmenggunakan kunci \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">PERINGATAN: IDENTIFIKASI REMOTE HOST TELAH BERUBAH!</string> + <string name="host_verification_failure_warning">KEMUNGKINAN SESEORANG SEDANG BERBUAT KOTOR!\nSeseorang mungkin tengah menyadap anda saat ini (serangan man-in-the-middle)!\nMungkin juga kunci host baru saja diubah.</string> + <string name="prompt_host_disconnected">Sambungan dengan host telah terputus.\nTutup sesi ini?</string> + <string name="prompt_continue_connecting">Apakah Anda yakin ingin\nterus mencoba menyambungkan?</string> + <string name="host_authenticity_warning">Authentifikasi dari host \'%1$s\' tidak dapat dibuat.</string> + <string name="host_fingerprint">Host %1$s tanda tangan kunci adalah %2$s</string> + <string name="alert_passwords_do_not_match_msg">Kata sandi tidak cocok!</string> + <string name="alert_wrong_password_msg">Kata sandi salah!</string> + <string name="alert_key_corrupted_msg">Kunci pribadi nampaknya telah rusak!</string> + <string name="alert_sdcard_absent">SD card belum dimasukan!</string> + <string name="button_add">Tambahkan</string> + <string name="button_change">Ubah</string> + <string name="button_generate">Buat Kunci</string> + <string name="button_resize">Ubah ukuran</string> + <string name="alert_disconnect_msg">Koneksi terputus</string> + <string name="pref_emulation_category">Terminal Emulasi</string> + <string name="pref_emulation_title">Mode Emulasi</string> + <string name="pref_emulation_summary">Mode terminal emulasi digunakan untuk koneksi PTY</string> + <string name="pref_scrollback_title">Ukuran Scrollback</string> + <string name="pref_scrollback_summary">Ukuran penyangga scrollback yang harus tersimpan di memori pada setiap konsol</string> + <string name="pref_ui_category">Antarmuka pengguna</string> + <string name="pref_rotation_title">Mode rotasi</string> + <string name="pref_rotation_summary">Bagaimana mengubah rotasi ketika papan ketik menyembul masuk/keluar</string> + <string name="pref_fullscreen_title">Layar penuh</string> + <string name="pref_fullscreen_summary">Sembunyikan bar status ketika dalam konsol</string> + <string name="pref_memkeys_title">Ingat kunci dalam memori</string> + <string name="pref_memkeys_summary">Simpan kunci yang terbuka kedalam memori hingga layanan backend berakhir</string> + <string name="pref_update_title">Memeriksa pembaharuan</string> + <string name="pref_update_summary">Tentukan frekuensi maksimal untuk memeriksa pembaharuan pada ConnectBot</string> + <string name="pref_conn_persist_title">Pertahankan koneksi</string> + <string name="pref_conn_persist_summary">Paksa koneksi untuk tetap terhubung ketika bekerja di belakang layar</string> + <string name="pref_keymode_title">Jalan pintas direktori</string> + <string name="pref_keymode_summary">Pilih bagaimana menggunakan Alt untuk \'/\' dan Shift untuk Tab</string> + <string name="pref_camera_title">Jalan pintas kamera</string> + <string name="pref_camera_summary">Pilih jalan pintas yang akan diaktifkan saat tombol kamera ditekan</string> + <string name="pref_keepalive_title">Jaga layar tetap terbuka</string> + <string name="pref_keepalive_summary">Mencegah layar menjadi padam ketika bekerja dalam sebuah konsol</string> + <string name="pref_wifilock_title">Wi-Fi selalu aktif</string> + <string name="pref_wifilock_summary">Jaga Wi-Fi agar tidak padam ketika sesi aktif</string> + <string name="pref_bumpyarrows_title">Panah belok</string> + <string name="pref_bumpyarrows_summary">Getarkan saat mengirim tombol panah dari trackball, berguna untuk koneksi lambat</string> + <string name="pref_bell_category">Bel terminal</string> + <string name="pref_bell_title">Bel berdering</string> + <string name="pref_bell_volume_title">Volume dering</string> + <string name="pref_bell_vibrate_title">Getarkan saat berdering</string> + <string name="pref_bell_notification_title">Pemberitahuan di belakang layar</string> + <string name="pref_bell_notification_summary">Kirim pemberitahuan ketika sebuah terminal berjalan di belakang dengan membunyikan sebuah nada dering</string> + <string name="list_keymode_right">Gunakan tombol sisi kanan</string> + <string name="list_keymode_left">Gunakan tombol sisi-kiri</string> + <string name="list_keymode_none">Tidak aktif</string> + <string name="list_pubkeyids_none">Jangan gunakan kunci</string> + <string name="list_pubkeyids_any">Gunakan kunci apapun yang tidak terkunci</string> + <string name="hostpref_nickname_title">Nama panggilan</string> + <string name="hostpref_color_title">Kategori warna</string> + <string name="hostpref_fontsize_title">Ukuran huruf (pt)</string> + <string name="hostpref_pubkeyid_title">Gunakan otentifikasi pubkey</string> + <string name="hostpref_authagent_title">Gunakan SSH auth agent</string> + <string name="hostpref_postlogin_title">otomasi setelah login</string> + <string name="hostpref_postlogin_summary">Perintah yang dijalankan diremote server sekali terotentifikasi</string> + <string name="hostpref_compression_title">Kompresi</string> + <string name="hostpref_compression_summary">Ini mungkin akan membantu dengan jaringan lambat</string> + <string name="hostpref_wantsession_title">Jalankan sesi shell</string> + <string name="hostpref_wantsession_summary">Non-aktifkan kesukaan ini hanya untuk port forwards</string> + <string name="hostpref_stayconnected_summary">Coba menyambungkan kembali ke host jika terputus</string> + <string name="hostpref_delkey_title">Tombol DEL</string> + <string name="hostpref_delkey_summary">Kode kunci terkirim ketika tombol DEL ditekan</string> + <string name="hostpref_encoding_title">Pengkodean</string> + <string name="hostpref_encoding_summary">Karakter pengkodean untuk host</string> + <string name="hostpref_connection_category">Konfigurasi koneksi</string> + <string name="hostpref_username_title">Nama pengguna</string> + <string name="bind_never">Tidak pernah terhubung</string> + <string name="bind_minutes">%1$s menit yang lalu</string> + <string name="bind_hours">%1$s jam yang lalu</string> + <string name="bind_days">%1$s hari yang lalu</string> + <string name="console_copy_done">Tersalin %1$d byte ke papan-klip</string> + <string name="console_copy_start">Sentuh dan tarik\natau gunakan tombol panah\nuntuk memilih area yang akan disalin</string> + <string name="console_menu_close">Tutup</string> + <string name="console_menu_copy">Salin</string> + <string name="console_menu_paste">Tempel</string> + <string name="console_menu_portforwards">Penerusan port</string> + <string name="console_menu_resize">Paksakan ukuran</string> + <string name="console_menu_urlscan">Pindai URL</string> + <string name="portforward_local">Lokal</string> + <string name="portforward_remote">Remote</string> + <string name="portforward_dynamic">Dinamis (SOCKS)</string> + <string name="portforward_pos">Buat penerusan port</string> + <string name="portforward_done">Berhasil membuat penerusan port</string> + <string name="portforward_problem">Masalah dalam membuat penerusan port, mungkin Anda menggunakan nomor port di bawah 1024 atau nomor port telah digunakan?</string> + <string name="portforward_menu_add">Tambah penerusan port</string> + <string name="hint_userhost">pengguna\@namahost</string> + <string name="list_format_error">Gunakan bentuk \"%1$s\"</string> + <string name="format_username">pengguna</string> + <string name="format_hostname">namahost</string> + <string name="list_menu_pubkeys">Atur Pubkey</string> + <string name="list_menu_sortcolor">Urutkan berdasarkan warna</string> + <string name="list_menu_sortname">Urutkan berdasarkan nama</string> + <string name="list_menu_settings">Pengaturan</string> + <string name="list_host_disconnect">Putus koneksi</string> + <string name="list_host_edit">Ubah host</string> + <string name="list_host_portforwards">Ubah penerusan port</string> + <string name="list_host_delete">Hapus host</string> + <string name="list_host_empty">Gunakan kotak cepat-sambung\ndi bawah untuk tersambung dengan sebuah host</string> + <string name="list_rotation_default">Baku</string> + <string name="list_rotation_land">Paksakan bentuk datar</string> + <string name="list_rotation_port">Paksakan bentuk tegak</string> + <string name="list_rotation_auto">Otomatis</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A kemudian spasi</string> + <string name="list_hwbutton_none">Kosong</string> + <string name="delete_message">Apakah anda yakin ingin menghapus %1$s?</string> + <string name="delete_pos">Ya, hapus</string> + <string name="delete_neg">Batal</string> + <string name="wizard_agree">Setuju</string> + <string name="wizard_next">Selanjutnya</string> + <string name="wizard_back">Sebelumnya</string> + <string name="terminal_no_hosts_connected">Tidak ada host yang saat ini terhubung</string> + <string name="terminal_connecting">Menyambungkan ke %1$s:%2$d melalui %3$s</string> + <string name="terminal_sucess">Host terverifikasi \'%1$s\' kunci: %2$s</string> + <string name="terminal_failed">Verifikasi kunci host gagal.</string> + <string name="terminal_using_s2c_algorithm">Algoritma server-ke-klien: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algoritma klien-ke-server: %1$s %2$s</string> + <string name="terminal_using_algorithm">Menggunakan algoritma : %1$s %2$s</string> + <string name="terminal_auth">Mencoba untuk mengotentifikasi</string> + <string name="terminal_auth_pass">Mencoba otentifikasi \'kata sandi\'</string> + <string name="terminal_auth_pass_fail">Metoda otentifikasi \'kata sandi\' gagal</string> + <string name="terminal_auth_pubkey_any">Mencoba otentifikasi \'kunci publik\' dengan kunci publik apapun dalam memori</string> + <string name="terminal_auth_pubkey_invalid">Kunci publik yang dipilih tidak valid, coba pilih kembali kunci dalam editor host</string> + <string name="terminal_auth_pubkey_specific">Mencoba otentifikasi \'kunci publik\' dengan kunci publik spesifik</string> + <string name="terminal_auth_pubkey_fail">Metode otentifikasi \'kunci publik\' dengan kunci \'%1$s\' gagal</string> + <string name="terminal_auth_ki">Mencoba otentifikasi \'papan ketik interaktif\'</string> + <string name="terminal_auth_ki_fail">Metode otentifikasi \'papan ketik interaktif\' gagal</string> + <string name="terminal_auth_fail">[Host anda tidak mendukung otentifikasi \'kata sandi\' atau \'papan ketik interaktif\'.]</string> + <string name="terminal_no_session">Sesi tidak akan dimulai karena preferensi host</string> + <string name="terminal_enable_portfoward">Aktifkan port forward: %1$s</string> + <string name="local_shell_unavailable">Gagal! Shell lokal tidak tersedia di telepon ini.</string> + <string name="notification_text">%1$s memerlukan perhatian anda.</string> + <string name="with_confirmation">Dengan konfirmasi</string> + <string name="exceptions_submit_message">Sepertinya ConnectBot mengalami masalah saat berjalan sebelumnya. Kirim laporan galat ke para pengembang ConnectBot?</string> + <string name="app_is_running">ConnectBot sedang berjalan</string> + <string name="color_red">merah</string> + <string name="color_green">hijau</string> + <string name="color_blue">biru</string> + <string name="color_gray">abu-abu</string> + <string name="colors_fg">WD:</string> + <string name="color_bg">WB:</string> + <string name="image_description_connected">Tersambung.</string> + <string name="image_description_key_is_locked">Pubkey terkunci.</string> + <string name="image_description_toggle_control_character">Ubah-ubah karakter control.</string> + <string name="image_description_send_escape_character">Kirim karakter escape.</string> + <string name="image_description_show_keyboard">Perlihatkan papan ketik.</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-is/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,177 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="service_desc">Heldur utan um SSH tengingar og geymda \"pubkeys\"</string> + <string name="title_hosts_list">Þjónar</string> + <string name="title_pubkey_list">Almennir lyklar</string> + <string name="title_port_forwards_list">Áframsending ports</string> + <string name="title_host_editor">Breyta þjónum</string> + <string name="title_help">Hjálp</string> + <string name="title_colors">Litir</string> + <string name="resolve_connect">Tengjast</string> + <string name="resolve_entropy">Safna bitum af handahófi</string> + <string name="menu_insert">Bæta við þjóni</string> + <string name="menu_delete">Eyða þjóni</string> + <string name="menu_preferences">Valmöguleikar</string> + <string name="help_intro">Vinsamlegast veldu atriði hér að neðan til þess að fá nánari upplýsingar um það.</string> + <string name="help_about">Um ConnectBot</string> + <string name="help_keyboard">Lyklaborð</string> + <string name="pubkey_generate">Búa til</string> + <string name="pubkey_import">Flytja inn</string> + <string name="pubkey_delete">Eyða lykli</string> + <string name="pubkey_gather_entropy">Safna bitum af handahófi</string> + <string name="pubkey_touch_prompt">Snertu kassann til þess að safna bitum af handahófi, %1$d%% búið.</string> + <string name="pubkey_touch_hint">Til þess að tryggja handahófs kenndan lykil, færðu fingurinn á þér handahófskennt yfir kassann að neðan.</string> + <string name="pubkey_generating">"Framkalla lykla par…"</string> + <string name="pubkey_copy_private">Afrita einka lykil</string> + <string name="pubkey_copy_public">Afrita almennan lykil</string> + <string name="pubkey_list_empty">Ýttu á \"Menu\" til þess að búa til\neða fluttu inn lykla par.</string> + <string name="pubkey_unknown_format">Óþekkt snið</string> + <string name="pubkey_change_password">Breyta lykilorði</string> + <string name="pubkey_list_pick">Velja af /sdcard</string> + <string name="pubkey_import_parse_problem">Ekki tókst að lesa einkalykilinn</string> + <string name="pubkey_unlock">Aflæsa lykli</string> + <string name="pubkey_failed_add">Rangt lykilorð fyrir lykilinn \'%1$s\'. Staðfesting mistókst</string> + <string name="pubkey_memory_load">Hlaða inn í minni</string> + <string name="pubkey_memory_unload">Hlaða úr minni</string> + <string name="pubkey_load_on_start">Hlaða lyklum við ræsingu</string> + <string name="pubkey_confirm_use">Staðfesta fyrir notkun</string> + <string name="portforward_list_empty">Ýttu á \"Menu\" til þess að\nbúa til port áframsendingu</string> + <string name="portforward_edit">Breyta áframsendingu ports</string> + <string name="portforward_delete">Eyða áframsendingu ports</string> + <string name="prompt_nickname">Gælunafn:</string> + <string name="prompt_nickname_hint_pubkey">Lykillinn minn</string> + <string name="prompt_source_port">Frá:</string> + <string name="prompt_destination">Til:</string> + <string name="prompt_old_password">Gamla lykilorðið</string> + <string name="prompt_password">Lykilorð:</string> + <string name="prompt_again">(aftur)</string> + <string name="prompt_type">Tegund:</string> + <string name="prompt_password_can_be_blank">ATH: lykilorðið getur verið tómt</string> + <string name="prompt_bits">Bitar:</string> + <string name="prompt_pubkey_password">Lykilorð fyrir lykilinn \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Leyfa þjóninum að\nnota lykilinn \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">VIÐVÖRUN: AUÐKENNING ÞJÓNSINS HEFUR BREYST!</string> + <string name="host_verification_failure_warning">ÞAÐ ER MÖGULEIKI Á AÐ EINHVER SÉ AÐ GERA EITTHVAÐ LJÓTT!\nÞað gæti verið að einhver sé að fylgjast með með þér (man-in-the-middle árás)!\nEn það gæti líka verið að lykill þjónsins hafi einfaldlega breyst.</string> + <string name="prompt_host_disconnected">Þjónninn hefur verið aftengdur.\nViltu loka?</string> + <string name="prompt_continue_connecting">Ertu viss um að þú\nviljir halda áfram að tengjast?</string> + <string name="host_authenticity_warning">Upprunaleiki lykilsins fyrir þjóninn \'%1$s\' getur ekki verið staðfestur.</string> + <string name="host_fingerprint">Þjónninn er %1$s fingrafar lykilsins er %2$s</string> + <string name="alert_passwords_do_not_match_msg">Lykilorðin passa ekki saman!</string> + <string name="alert_wrong_password_msg">Rangt lykilorð!</string> + <string name="alert_key_corrupted_msg">Einka lykillinn lítur út fyrir að vera skemmdur!</string> + <string name="alert_sdcard_absent">SD kort er ekki til staðar!</string> + <string name="button_add">Bæta við</string> + <string name="button_change">Breyta</string> + <string name="button_generate">Framkalla lykil</string> + <string name="button_resize">Breyta stærð</string> + <string name="alert_disconnect_msg">Tengingu tapað</string> + <string name="pref_ui_category">Notenda viðmót</string> + <string name="pref_rotation_title">Snúnings hamur</string> + <string name="pref_rotation_summary">Hvernig breyta skal snúningnum þegar lyklaborðið er sýnilegt/falið</string> + <string name="pref_fullscreen_title">Fylla skjáinn</string> + <string name="pref_fullscreen_summary">Fela stöðustiku þegar tenging er virk</string> + <string name="pref_memkeys_title">Geyma lykla í minni</string> + <string name="pref_memkeys_summary">Geyma ólæsta lykla í minni þangað til forritinu er lokað</string> + <string name="pref_update_title">Athuga með uppfærslu</string> + <string name="pref_update_summary">Velja hve oft ConnectBot leitar að uppfærslum</string> + <string name="pref_conn_persist_title">Halda tengingum</string> + <string name="pref_conn_persist_summary">Halda tengingum í gangi þegar þær eru í bakgrunni</string> + <string name="pref_keymode_title">Orðabók</string> + <string name="pref_keymode_summary">Veldu hvernig nota skal Alt fyrir \'/\' og Shift fyrir Tab</string> + <string name="pref_camera_title">Myndavéla takkinn</string> + <string name="pref_camera_summary">Veldu hvað gerist þegar þrýst er á myndavéla takkann</string> + <string name="pref_keepalive_title">Halda skjánum í gangi</string> + <string name="pref_keepalive_summary">Banna skjánum að slokkna þegar tenging er virk</string> + <string name="pref_wifilock_title">Halda þráðlausu neti í gangi</string> + <string name="pref_wifilock_summary">Halda þráðlausu neti í gangi þegar tenging er virk</string> + <string name="pref_bumpyarrows_summary">Titra þegar örvar eru sendar með trackball; sniðugt fyrir óstöðugar tengingar</string> + <string name="pref_bell_category">Terminal bjalla</string> + <string name="pref_bell_title">Bjalla með hljóði</string> + <string name="pref_bell_volume_title">Hljóðstyrkur bjöllu</string> + <string name="pref_bell_vibrate_title">Titra þegar bjallan er virk</string> + <string name="pref_bell_notification_title">Boð frá bakgrunni</string> + <string name="pref_bell_notification_summary">Senda boð þegar þónn í bakgrunni sendir frá sé bjöllu.</string> + <string name="list_keymode_right">Nota hægri-hliðar lykla</string> + <string name="list_keymode_left">Nota vinstri-hliðar lykla</string> + <string name="list_keymode_none">Afvirkja</string> + <string name="list_pubkeyids_none">Ekki nota lykla</string> + <string name="list_pubkeyids_any">Nota hvaða ólæsta lykil sem er</string> + <string name="hostpref_nickname_title">Gælunafn</string> + <string name="hostpref_color_title">Lita flokk</string> + <string name="hostpref_fontsize_title">Leturstærð (pt)</string> + <string name="hostpref_pubkeyid_title">Innskráning með almennum lykli</string> + <string name="hostpref_postlogin_summary">Skipanir til þess að keyra á þjóni eftir innskráningu</string> + <string name="hostpref_compression_title">Þjöppun</string> + <string name="hostpref_compression_summary">Þetta getur hjálpað á hægu neti</string> + <string name="hostpref_stayconnected_title">Halda tengingu</string> + <string name="hostpref_stayconnected_summary">Reyna að endurtengjast ef aftenging verður</string> + <string name="hostpref_encoding_title">Kóðun</string> + <string name="hostpref_connection_category">Stillingar fyrir tengingu</string> + <string name="hostpref_username_title">Notendanafn</string> + <string name="hostpref_hostname_title">Þjónn</string> + <string name="hostpref_port_title">Port</string> + <string name="bind_never">Aldrei tengt</string> + <string name="bind_minutes">Fyrir %1$s mínútum síðan</string> + <string name="bind_hours">Fyrir %1$s tímum síðan</string> + <string name="bind_days">Fyrir %1$s dögum síðan</string> + <string name="console_copy_done">Afritaði %1$d bæti</string> + <string name="console_menu_close">Loka</string> + <string name="console_menu_copy">Afrita</string> + <string name="console_menu_paste">Líma</string> + <string name="console_menu_resize">Þvinga stærð</string> + <string name="console_menu_urlscan">Skanna fyrir slóðum</string> + <string name="button_yes">Já</string> + <string name="button_no">Nei</string> + <string name="portforward_dynamic">Breytilegt (SOCKS)</string> + <string name="portforward_pos">Áframsenda port</string> + <string name="portforward_done">Áframsendi port farsællega</string> + <string name="portforward_problem">Gat ekki áframsent portið, varstu að nota port minna en 1024? Eða er portið nú þegar áframsent?</string> + <string name="portforward_menu_add">Áframsenda port</string> + <string name="hint_userhost">notandi\@þjónn</string> + <string name="format_username">notendanafn</string> + <string name="format_hostname">þjónn</string> + <string name="format_port">port</string> + <string name="list_menu_sortcolor">Raða eftir lit</string> + <string name="list_menu_sortname">Raða eftir nafni</string> + <string name="list_menu_settings">Stillingar</string> + <string name="list_host_disconnect">Aftengjast</string> + <string name="list_host_edit">Breyta þjóni</string> + <string name="list_host_portforwards">Breyta áframsendingu ports</string> + <string name="list_host_delete">Eyða þjóni</string> + <string name="list_host_empty">Notaðu boxið hér að neðan\ntil þess að tengjast á þjón.</string> + <string name="list_rotation_default">Sjálfgefið</string> + <string name="list_rotation_land">þvinga á hlið</string> + <string name="list_rotation_port">þvinga beint</string> + <string name="list_rotation_auto">Sjálfgefið</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A og Space</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Ekkert</string> + <string name="list_delkey_del">Eyða</string> + <string name="delete_message">Ert þú viss um að þú viljir eyða \'%1$s\'?</string> + <string name="delete_pos">Já, eyða</string> + <string name="delete_neg">Hætta við</string> + <string name="wizard_agree">Samþykkja</string> + <string name="wizard_next">Næsta</string> + <string name="wizard_back">Til baka</string> + <string name="terminal_no_hosts_connected">Engir þjónar tengdir í augnablikinu</string> + <string name="terminal_connecting">Tengist við %1$s:%2$d með %3$s</string> + <string name="terminal_failed">Ekki tókst að staðfesta lykil þjóns.</string> + <string name="terminal_using_algorithm">Nota algorithmann: %1$s %2$s</string> + <string name="terminal_auth">Reyni að staðfesta</string> + <string name="terminal_auth_pass">Reyni að tengjast með lykilorði</string> + <string name="terminal_auth_pass_fail">Ekki tókst að tengjast með lykilorði</string> + <string name="terminal_enable_portfoward">Áframsenda port: %1$s</string> + <string name="notification_text">%1$s krefst athygli þinnar.</string> + <string name="no">Nei</string> + <string name="with_confirmation">Með staðfestingu</string> + <string name="yes">Já</string> + <string name="exceptions_submit_message">Það lítur út fyrir að ConnectBot hafi verið í vandræðum síðast þegar það keyrði. Viltu senda villu greiningu á höfunda forritsins?</string> + <string name="menu_colors_reset">Endurstilla</string> + <string name="app_is_running">ConnectBot er í gangi</string> + <string name="color_red">rauður</string> + <string name="color_green">grænn</string> + <string name="color_blue">blár</string> + <string name="color_gray">grár</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-it/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,214 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Un client SSH semplice, potente ed open-source.</string> + <string name="service_desc">Mantieni le connessioni SSH e le chiavi pubbliche caricate</string> + <string name="title_hosts_list">Connessione</string> + <string name="title_pubkey_list">Chiavi pubbliche</string> + <string name="title_port_forwards_list">Inoltro porte</string> + <string name="title_host_editor">Modifica connessione</string> + <string name="title_help">Guida</string> + <string name="title_colors">Colori</string> + <string name="resolve_connect">Connetti</string> + <string name="resolve_entropy">Raccolta disordinata</string> + <string name="menu_insert">Aggiungi connessione</string> + <string name="menu_delete">Elimina connessione</string> + <string name="menu_preferences">Preferenze</string> + <string name="help_intro">Seleziona un argomento dalla lista per ottenere maggiori informazioni.</string> + <string name="help_about">Informazioni su ConnectBot</string> + <string name="help_keyboard">Tastiera</string> + <string name="pubkey_generate">Genera</string> + <string name="pubkey_import">Importa</string> + <string name="pubkey_delete">Elimina chiave</string> + <string name="pubkey_gather_entropy">Raccolta entropia</string> + <string name="pubkey_touch_prompt">Tocca questo riquadro per raccogliere informazioni casuali: %1$d%% fatto</string> + <string name="pubkey_touch_hint">Per poter assicurare una sorgente di casualità durante la generazione della chiave, muovere le dita casualmente sul riquadro sottostante.</string> + <string name="pubkey_generating">"La coppia di chiavi viene generata…"</string> + <string name="pubkey_copy_private">Copia chiave privata</string> + <string name="pubkey_copy_public">Copia chiave pubblica</string> + <string name="pubkey_list_empty">Seleziona Menu per creare\no importare chiavi.</string> + <string name="pubkey_unknown_format">Formato non riconosciuto</string> + <string name="pubkey_change_password">Cambia password</string> + <string name="pubkey_list_pick">Leggi da /sdcard</string> + <string name="pubkey_import_parse_problem">Problemi durante l\'importazione della chiave privata</string> + <string name="pubkey_unlock">Chiave di sblocco</string> + <string name="pubkey_failed_add">Password errata per la chiave \'%1$s\'. Errore di autenticazione.</string> + <string name="pubkey_memory_load">Carica in memoria</string> + <string name="pubkey_memory_unload">Elimina dalla memoria</string> + <string name="pubkey_load_on_start">Carica la chiave all\'avvio</string> + <string name="pubkey_confirm_use">Conferma prima di usare</string> + <string name="portforward_list_empty">Seleziona Menu per creare\ninoltri delle porte.</string> + <string name="portforward_edit">Modifica inoltro porte</string> + <string name="portforward_delete">Elimina inoltro porta</string> + <string name="prompt_nickname">Nome utente:</string> + <string name="prompt_nickname_hint_pubkey">La mia chiave di lavoro</string> + <string name="prompt_source_port">Porta sorgente:</string> + <string name="prompt_destination">Destinazione:</string> + <string name="prompt_old_password">Vecchia password:</string> + <string name="prompt_password">Password:</string> + <string name="prompt_again">(ripeti)</string> + <string name="prompt_type">Tipo:</string> + <string name="prompt_password_can_be_blank">Nota: la password può essere vuota</string> + <string name="prompt_bits">Bits:</string> + <string name="prompt_pubkey_password">Password per la chiave \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Permetti all\'host remoto di\n usare la chiave \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">ATTENZIONE: L\'IDENTIFICAZIONE DELL\'HOST REMOTO E\' CAMBIATA!</string> + <string name="host_verification_failure_warning">E\' POSSIBILE CHE QUALCUNO STIA FACENDO QUALCOSA DI MALEVOLO!\nQualcuno potrebbe spiarti in questo momento (attacco man-in-the-middle)!\nMa è anche possibile che la chiave dell\'host sia cambiata.</string> + <string name="prompt_host_disconnected">L\'host si è disconnesso.\nChiudere la sessione?</string> + <string name="prompt_continue_connecting">Sei sicuro di voler\ncontinuare a connetterti?</string> + <string name="host_authenticity_warning">L\'autenticità dell\'host \'%1$s\' non può essere accertata.</string> + <string name="host_fingerprint">L\'impronta digitale della chiave dell\'Host %1$s è %2$s</string> + <string name="alert_passwords_do_not_match_msg">Le password non corrispondono!</string> + <string name="alert_wrong_password_msg">Password errata!</string> + <string name="alert_key_corrupted_msg">La chiave privata sembra corrotta!</string> + <string name="alert_sdcard_absent">Scheda SD non trovata!</string> + <string name="button_add">Aggiungi</string> + <string name="button_change">Modifica</string> + <string name="button_generate">Genera le chiavi</string> + <string name="button_resize">Ridimensiona</string> + <string name="alert_disconnect_msg">Connessione persa</string> + <string name="pref_emulation_category">Emulazione terminale</string> + <string name="pref_emulation_title">Modalità emulazione</string> + <string name="pref_emulation_summary">Modalità di emulazione terminale da usare per connessioni PTY</string> + <string name="pref_scrollback_title">Dimensione scrollback</string> + <string name="pref_scrollback_summary">Dimensione del buffer scrollback da tenere in memoria per ciascuna console</string> + <string name="pref_ui_category">Interfaccia utente</string> + <string name="pref_rotation_title">Modalità rotazione</string> + <string name="pref_rotation_summary">Come cambiare rotazione quando la tastiera esce/rientra</string> + <string name="pref_fullscreen_title">Schermo intero</string> + <string name="pref_fullscreen_summary">Nascondi la barra di stato in console</string> + <string name="pref_memkeys_title">Mantieni chiavi in memoria</string> + <string name="pref_memkeys_summary">Mantiene le chiavi in memoria finché il servizio non viene terminato</string> + <string name="pref_update_title">Controlla aggiornamenti</string> + <string name="pref_update_summary">Imposta la frequenza massima per il controllo degli aggiornamenti</string> + <string name="pref_conn_persist_title">Connessioni permanenti</string> + <string name="pref_conn_persist_summary">Forza connessioni a rimanere collegate in sottofondo</string> + <string name="pref_keymode_title">Scorciatoie directory</string> + <string name="pref_keymode_summary">Controlla l\'uso di Alt per \'/\' e di Shift per Tab</string> + <string name="pref_camera_title">Scorciatoia camera</string> + <string name="pref_camera_summary">Seleziona quale scorciatoia azionare quando il bottone della camera viene premuto</string> + <string name="pref_keepalive_title">Impedisci lo spegnimento dello schermo</string> + <string name="pref_keepalive_summary">Impedisce lo spegnimento dello schermo quando si è collegati</string> + <string name="pref_wifilock_title">Mantieni Wi-Fi attivo</string> + <string name="pref_wifilock_summary">Non spegne la connessione Wi-Fi quando una sessione è attiva</string> + <string name="pref_bumpyarrows_title">Vibrazione frecce</string> + <string name="pref_bumpyarrows_summary">Vibra quando si inviano movimenti con la trackball; utile per connessioni lente</string> + <string name="pref_bell_category">Campanella del terminale</string> + <string name="pref_bell_title">Campanella udibile</string> + <string name="pref_bell_volume_title">Volume della campanella</string> + <string name="pref_bell_vibrate_title">Vibra alla campanella</string> + <string name="pref_bell_notification_title">Notifiche in sottofondo</string> + <string name="pref_bell_notification_summary">Invia una notifica quando un terminale eseguito in sottofondo suona una campanella.</string> + <string name="list_keymode_right">Usa tasti sul lato destro</string> + <string name="list_keymode_left">Usa tasti sul lato sinistro</string> + <string name="list_keymode_none">Disabilita</string> + <string name="list_pubkeyids_none">Non usare chiavi</string> + <string name="list_pubkeyids_any">Usa qualsiasi chiave sbloccata</string> + <string name="hostpref_nickname_title">Soprannome</string> + <string name="hostpref_color_title">Categoria colore</string> + <string name="hostpref_fontsize_title">Dimensione caratteri (pt)</string> + <string name="hostpref_pubkeyid_title">Usa autenticazione a chiave pubblica</string> + <string name="hostpref_authagent_title">Usa l\'agente di autorizzazione SSH</string> + <string name="hostpref_postlogin_title">Automazione post-accesso</string> + <string name="hostpref_postlogin_summary">Comandi da eseguire su un server remoto una volta autenticati</string> + <string name="hostpref_compression_title">Compressione</string> + <string name="hostpref_compression_summary">Può essere utile con connessioni lente</string> + <string name="hostpref_wantsession_title">Avvia sessione shell</string> + <string name="hostpref_wantsession_summary">Disabilita questa preferenza per usare solo port forward</string> + <string name="hostpref_stayconnected_title">Mantieni connessioni</string> + <string name="hostpref_stayconnected_summary">Tenta di riconnettersi in caso di disconnessione</string> + <string name="hostpref_delkey_title">Tasto CANC</string> + <string name="hostpref_delkey_summary">Il codice di tastiera inviato quando viene premuto il tasto CANC</string> + <string name="hostpref_encoding_title">Codifica</string> + <string name="hostpref_encoding_summary">Codifica dei caratteri per la connessione</string> + <string name="hostpref_connection_category">Impostazioni di connessione</string> + <string name="hostpref_username_title">Nome utente</string> + <string name="hostpref_hostname_title">Host</string> + <string name="hostpref_port_title">Porta</string> + <string name="bind_never">Mai connesso</string> + <string name="bind_minutes">%1$s minuti fa</string> + <string name="bind_hours">%1$s ore fa</string> + <string name="bind_days">%1$s giorni fa</string> + <string name="console_copy_done">%1$d byte copiati</string> + <string name="console_copy_start">Tocca e trascina\noppure usa il pad direzionale\nper selezionare un\'area da copiare</string> + <string name="console_menu_close">Chiudi</string> + <string name="console_menu_copy">Copia</string> + <string name="console_menu_paste">Incolla</string> + <string name="console_menu_portforwards">Inoltro porte</string> + <string name="console_menu_resize">Forza Dimensione</string> + <string name="console_menu_urlscan">Scansione URL</string> + <string name="button_yes">Sì</string> + <string name="button_no">No</string> + <string name="portforward_local">Locale</string> + <string name="portforward_remote">Remota</string> + <string name="portforward_dynamic">Dinamica (SOCKS)</string> + <string name="portforward_pos">Crea inoltro porta</string> + <string name="portforward_done">Inoltro della porta impostato correttamente</string> + <string name="portforward_problem">Problema configurando l\'inoltro della porta, forse si cerca di usare una porta più bassa di 1024 o la porta è già in uso?</string> + <string name="portforward_menu_add">Aggiungi inoltro di una porta</string> + <string name="hint_userhost">utente\@host</string> + <string name="list_format_error">Usa il formato %1$s</string> + <string name="format_username">nome utente</string> + <string name="format_hostname">nome host</string> + <string name="format_port">porta</string> + <string name="list_menu_pubkeys">Gestione chiavi pubbliche</string> + <string name="list_menu_sortcolor">Ordina per colore</string> + <string name="list_menu_sortname">Ordina per nome</string> + <string name="list_menu_settings">Impostazioni</string> + <string name="list_host_disconnect">Disconnetti</string> + <string name="list_host_edit">Modifica connessione</string> + <string name="list_host_portforwards">Modifica inoltri porta</string> + <string name="list_host_delete">Elimina connessione</string> + <string name="list_host_empty">Usa la casella connessione rapida\nqui sotto per connetterti ad un host.</string> + <string name="list_rotation_default">Predefinita</string> + <string name="list_rotation_land">Forza orizzontale</string> + <string name="list_rotation_port">Forza verticale</string> + <string name="list_rotation_auto">Automatica</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A poi Spazio</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Niente</string> + <string name="list_delkey_backspace">Barra Spaziatrice</string> + <string name="list_delkey_del">Elimina</string> + <string name="delete_message">Sei sicuro di voler eliminare \'%1$s\'?</string> + <string name="delete_pos">Sì, elimina</string> + <string name="delete_neg">Annulla</string> + <string name="wizard_agree">Accetto</string> + <string name="wizard_next">Successiva</string> + <string name="wizard_back">Precedente</string> + <string name="terminal_no_hosts_connected">Nessun host attualmente connesso</string> + <string name="terminal_connecting">Connessione a %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">Host verificato \'%1$s\' chiave: %2$s</string> + <string name="terminal_failed">Verifica della chiave dell\'host fallita.</string> + <string name="terminal_using_s2c_algorithm">Algoritmo server-to-client: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algoritmo client-to-server: %1$s %2$s</string> + <string name="terminal_using_algorithm">Algoritmo in uso: %1$s %2$s</string> + <string name="terminal_auth">Tentativo di autenticazione</string> + <string name="terminal_auth_pass">Provando l\'autenticazione \'password\'</string> + <string name="terminal_auth_pass_fail">Metodo di autenticazione \'password\' fallito</string> + <string name="terminal_auth_pubkey_any">Tentativo di utilizzo autenticazione a \'chiave pubblica\' con una delle chiavi pubbliche in memoria</string> + <string name="terminal_auth_pubkey_invalid">La chiave pubblica selezionata non è valida, provare a riselezionare la chiave nell\'host editor</string> + <string name="terminal_auth_pubkey_specific">Tentativo di autenticazione a \'chiave pubblica\' con una chiave pubblica specifica</string> + <string name="terminal_auth_pubkey_fail">Metodo di autenticazione a \'chiave pubblica\' con la chiave \'%1$s\' fallito</string> + <string name="terminal_auth_ki">Provando l\'autenticazione \'keyboard-interactive\'</string> + <string name="terminal_auth_ki_fail">Metodo di autenticazione \'keyboard-interactive\' fallito</string> + <string name="terminal_auth_fail">[Il tuo host non supporta l\'autenticazione \'password\' o \'keyboard-interactive\'</string> + <string name="terminal_no_session">La sessione non inizierà a causa delle preferenze dell\'host.</string> + <string name="terminal_enable_portfoward">Abilita il port forward: %1$s</string> + <string name="local_shell_unavailable">Fallimento! La shell locale non è disponibile su questo telefono.</string> + <string name="notification_text">%1$s richiede la tua attenzione.</string> + <string name="no">No</string> + <string name="with_confirmation">Richiedi conferma</string> + <string name="yes">Sì</string> + <string name="exceptions_submit_message">Sembrerebbe che ConnectBot abbia avuto un problema durante l\'ultima esecuzione. Inviare una segnalazione d\'errore agli sviluppatori di ConnectBot?</string> + <string name="menu_colors_reset">Reimposta</string> + <string name="app_is_running">ConnectBot è in esecuzione</string> + <string name="color_red">rosso</string> + <string name="color_green">verde</string> + <string name="color_blue">blu</string> + <string name="color_gray">grigio</string> + <string name="image_description_connected">Connesso.</string> + <string name="image_description_key_is_locked">La chiave e\' bloccata.</string> + <string name="image_description_send_escape_character">Mandare un carattere escape.</string> + <string name="image_description_show_keyboard">Mostra la tastiera.</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-ja/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,202 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">シンプルでパワフルなオープンソースのSSHクライアント</string> + <string name="title_hosts_list">ホスト</string> + <string name="title_pubkey_list">公開鍵</string> + <string name="title_port_forwards_list">ポート転送</string> + <string name="title_host_editor">ホストを編集</string> + <string name="title_help">ヘルプ</string> + <string name="title_colors">配色</string> + <string name="resolve_connect">接続</string> + <string name="resolve_entropy">エントロピーの取得</string> + <string name="menu_insert">ホストを追加</string> + <string name="menu_delete">ホストを削除</string> + <string name="menu_preferences">設定</string> + <string name="help_intro">特定の情報について知りたいときは、以下のトピックを選択してください。</string> + <string name="help_about">ConnectBotについて</string> + <string name="help_keyboard">キーボード</string> + <string name="pubkey_generate">生成</string> + <string name="pubkey_import">インポート</string> + <string name="pubkey_delete">鍵を削除</string> + <string name="pubkey_gather_entropy">エントロピー収集中</string> + <string name="pubkey_touch_prompt">この四角内をランダムに触ってください: %1$d%% 完了</string> + <string name="pubkey_touch_hint">鍵作成時のランダムさを保証するため、下の四角内で指をランダムに動かしてください。</string> + <string name="pubkey_generating">"鍵ペアを生成しています…"</string> + <string name="pubkey_copy_private">秘密鍵をコピー</string> + <string name="pubkey_copy_public">公開鍵をコピー</string> + <string name="pubkey_list_empty">Menuボタンを押して鍵の作成またはインポートを行ってください。</string> + <string name="pubkey_unknown_format">不明なフォーマット</string> + <string name="pubkey_change_password">パスワードを変更</string> + <string name="pubkey_list_pick">SDカードから選ぶ</string> + <string name="pubkey_import_parse_problem">インポートした秘密鍵を解析時に問題発生</string> + <string name="pubkey_unlock">鍵をアンロック</string> + <string name="pubkey_failed_add">鍵 \'%1$s\' のパスワードが正しくありません。認証に失敗しました。</string> + <string name="pubkey_memory_load">メモリにロード</string> + <string name="pubkey_memory_unload">メモリからアンロード</string> + <string name="pubkey_load_on_start">起動時に鍵をロード</string> + <string name="pubkey_confirm_use">使用時に確認する</string> + <string name="portforward_list_empty">MENUをタップして\nポート転送を作成します.</string> + <string name="portforward_edit">ポート転送を編集</string> + <string name="portforward_delete">ポート転送を削除</string> + <string name="prompt_nickname">鍵の名前</string> + <string name="prompt_source_port">ソースポート:</string> + <string name="prompt_destination">転送先:</string> + <string name="prompt_old_password">旧パスワード:</string> + <string name="prompt_password">パスワード:</string> + <string name="prompt_again">(再入力)</string> + <string name="prompt_type">タイプ:</string> + <string name="prompt_password_can_be_blank">備考: パスワードは空欄にできます。</string> + <string name="prompt_bits">ビット長:</string> + <string name="prompt_pubkey_password">鍵 \'%1$s\' のパスワード</string> + <string name="prompt_allow_agent_to_use_key">リモートホストが鍵 \'%1$s\' を使用することを許可しますか?</string> + <string name="host_verification_failure_warning_header">警告: リモートホストのIDが変わっています!</string> + <string name="host_verification_failure_warning">何者かが不正を行っている可能性があります!\n現在誰かに盗聴されているかもしれません (中間者攻撃)!\n単にホストキーが変更されただけの可能性もあります。</string> + <string name="prompt_host_disconnected">ホスト切断されました.\nセッションを閉じますか?</string> + <string name="prompt_continue_connecting">このまま接続しますか?</string> + <string name="host_authenticity_warning">ホスト \'%1$s\' の確認ができませんでした。</string> + <string name="host_fingerprint">ホストの%1$sキーフィンガープリントは%2$s</string> + <string name="alert_passwords_do_not_match_msg">パスワードが一致しません!</string> + <string name="alert_wrong_password_msg">間違ったパスワードです.</string> + <string name="alert_key_corrupted_msg">秘密鍵が壊れています!</string> + <string name="alert_sdcard_absent">SD カードが挿入されていません.</string> + <string name="button_add">追加</string> + <string name="button_change">変更</string> + <string name="button_generate">鍵生成</string> + <string name="button_resize">リサイズ</string> + <string name="alert_disconnect_msg">接続が失われました.</string> + <string name="pref_emulation_category">端末エミュレート</string> + <string name="pref_emulation_title">エミュレートモード</string> + <string name="pref_emulation_summary">PTYで使う端末エミュレーションモード</string> + <string name="pref_scrollback_title">スクロールサイズ</string> + <string name="pref_scrollback_summary">メモリに保持するスクロールバッファのサイズ</string> + <string name="pref_ui_category">ユーザーインターフェース</string> + <string name="pref_rotation_title">画面の向き</string> + <string name="pref_rotation_summary">キーボードのポップイン/アウト時の向きの変更</string> + <string name="pref_fullscreen_title">全画面</string> + <string name="pref_fullscreen_summary">ステータスバーを隠蔽しコンソールとして利用</string> + <string name="pref_memkeys_title">メモリに鍵を保持する</string> + <string name="pref_memkeys_summary">バックエンドのサービスが終了しない限り、アンロックした鍵をメモリに保持します</string> + <string name="pref_update_title">更新を確認</string> + <string name="pref_update_summary">ConnectBotの更新をチェックする頻度を設定します</string> + <string name="pref_conn_persist_title">持続的接続</string> + <string name="pref_conn_persist_summary">バックグラウンドでの実行中に接続の持続を強制する</string> + <string name="pref_keymode_title">ディレクトリのショートカット</string> + <string name="pref_keymode_summary">Altを\'/\'、ShiftをTabに割り当てます</string> + <string name="pref_camera_title">カメラボタンショートカット</string> + <string name="pref_camera_summary">カメラボタンが押されたときのショートカットを選びます</string> + <string name="pref_keepalive_title">画面をスリープしない</string> + <string name="pref_keepalive_summary">コンソール作業中に画面がOFFになるのを防ぎます</string> + <string name="pref_wifilock_title">Wi-Fiをスリープしない</string> + <string name="pref_wifilock_summary">セッションが有効な間Wi-FiがOFFになるのを防ぎます</string> + <string name="pref_bumpyarrows_title">矢印で振動</string> + <string name="pref_bumpyarrows_summary">トラックボールで矢印キーを送信するときに振動します; ラグがある接続時に便利</string> + <string name="pref_bell_category">端末音設定</string> + <string name="pref_bell_title">ベル音</string> + <string name="pref_bell_volume_title">ボリューム設定</string> + <string name="pref_bell_vibrate_title">バイブレーション</string> + <string name="pref_bell_notification_title">バックグラウンド通知</string> + <string name="pref_bell_notification_summary">バックグランドで実行中の端末がベルを鳴らしたとき通知します</string> + <string name="list_keymode_right">右側のキーで使う</string> + <string name="list_keymode_left">左側のキーで使う</string> + <string name="list_keymode_none">無効</string> + <string name="list_pubkeyids_none">公開鍵を使わない</string> + <string name="list_pubkeyids_any">アンロックされた鍵のいずれかを使う</string> + <string name="hostpref_nickname_title">ニックネーム</string> + <string name="hostpref_color_title">色の系統</string> + <string name="hostpref_fontsize_title">フォントのサイズ (pt)</string> + <string name="hostpref_pubkeyid_title">公開鍵認証を使用</string> + <string name="hostpref_authagent_title">SSH認証エージェントを使う</string> + <string name="hostpref_postlogin_title">ログイン後の自動実行</string> + <string name="hostpref_postlogin_summary">認証後にリモートで実行するコマンド</string> + <string name="hostpref_compression_title">圧縮</string> + <string name="hostpref_compression_summary">遅いネットワークで有効かもしれません</string> + <string name="hostpref_wantsession_title">シェルセッションを使う</string> + <string name="hostpref_wantsession_summary">ポート転送のみ行う場合に無効にしてください</string> + <string name="hostpref_stayconnected_title">接続の維持</string> + <string name="hostpref_stayconnected_summary">接続が切れたら再接続を試みます</string> + <string name="hostpref_delkey_title">DELキー</string> + <string name="hostpref_delkey_summary">DELキーが押されたときに送るキーコード</string> + <string name="hostpref_encoding_title">エンコーディング</string> + <string name="hostpref_encoding_summary">ホスト側の文字エンコーディング</string> + <string name="hostpref_connection_category">接続設定</string> + <string name="hostpref_username_title">ユーザ名</string> + <string name="hostpref_hostname_title">ホスト</string> + <string name="hostpref_port_title">ポート</string> + <string name="bind_never">未接続</string> + <string name="bind_minutes">%1$s 分前</string> + <string name="bind_hours">%1$s 時間前</string> + <string name="bind_days">%1$s 日前</string> + <string name="console_copy_done">クリップボードに %1$d バイトコピーしました.</string> + <string name="console_copy_start">タッチしてドラッグ\nまたは方向パッドで\nコピー領域を選択</string> + <string name="console_menu_close">切断</string> + <string name="console_menu_copy">コピー</string> + <string name="console_menu_paste">貼り付け</string> + <string name="console_menu_portforwards">ポート転送</string> + <string name="console_menu_resize">サイズ強制</string> + <string name="console_menu_urlscan">URL スキャン</string> + <string name="button_yes">はい</string> + <string name="button_no">いいえ</string> + <string name="portforward_local">ローカル</string> + <string name="portforward_remote">リモート</string> + <string name="portforward_dynamic">動的 (SOCKS)</string> + <string name="portforward_pos">ポート転送の作成</string> + <string name="portforward_done">ポート転送の作成に成功しました.</string> + <string name="portforward_problem">ポート転送の作成ができません.おそらく1024ポート以下か既に利用されているポートを指定されています.</string> + <string name="portforward_menu_add">ポート転送の追加</string> + <string name="list_format_error">%1$s 形式を使ってください</string> + <string name="format_username">ユーザ名</string> + <string name="format_hostname">ホスト名</string> + <string name="format_port">ポート</string> + <string name="list_menu_pubkeys">公開鍵管理</string> + <string name="list_menu_sortcolor">色でソート</string> + <string name="list_menu_sortname">名前順でソート</string> + <string name="list_menu_settings">設定</string> + <string name="list_host_disconnect">切断</string> + <string name="list_host_edit">接続ホストの編集</string> + <string name="list_host_portforwards">ポート転送の編集</string> + <string name="list_host_delete">接続ホストの削除</string> + <string name="list_host_empty">下のquick-connect box\nを使ってホストに接続できます.</string> + <string name="list_rotation_default">デフォルト</string> + <string name="list_rotation_land">横向き固定</string> + <string name="list_rotation_port">縦向き固定</string> + <string name="list_rotation_auto">自動判定</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+Aに続いてSpace</string> + <string name="list_hwbutton_none">なし</string> + <string name="delete_message">\'%1$s\'を削除してよろしいですか?</string> + <string name="delete_pos">はい、削除します</string> + <string name="delete_neg">キャンセル</string> + <string name="wizard_agree">同意します</string> + <string name="wizard_next">次へ</string> + <string name="wizard_back">戻る</string> + <string name="terminal_no_hosts_connected">接続済みのホストはありません.</string> + <string name="terminal_connecting">%1$s:%2$dに%3$sで接続しています</string> + <string name="terminal_sucess">ホスト\'%1$s\' キー%2$s を検証しました</string> + <string name="terminal_failed">ホストキーが検証できません</string> + <string name="terminal_using_s2c_algorithm">サーバtoクライアント アルゴリズム: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">クライアントからサーバ アルゴリズム: %1$s %2$s</string> + <string name="terminal_using_algorithm">使用アルゴリズム: %1$s %2$s</string> + <string name="terminal_auth">認証を試行中</string> + <string name="terminal_auth_pass">\'password\' 認証を試行</string> + <string name="terminal_auth_pass_fail">\'password\' 認証失敗</string> + <string name="terminal_auth_pubkey_any">メモリ上の公開鍵による \'publickey\' 認証を試行</string> + <string name="terminal_auth_pubkey_invalid">選択された公開鍵は無効です、ホストの編集で選び直してください</string> + <string name="terminal_auth_pubkey_specific">指定された公開鍵による \'publickey\' 認証を試行</string> + <string name="terminal_auth_pubkey_fail">鍵 \'%1$s\' での \'publickey\' 認証に失敗</string> + <string name="terminal_auth_ki">\'keyboard-interactive\' 認証を試行</string> + <string name="terminal_auth_ki_fail">\'keyboard-interactive\' 認証に失敗</string> + <string name="terminal_auth_fail">[ホストは \'password\' や \'keyboard-interactive\' 認証をサポートしていません.]</string> + <string name="terminal_no_session">ホスト設定によりセッションを開始しません</string> + <string name="terminal_enable_portfoward">ポート転送 %1$s を有効化</string> + <string name="local_shell_unavailable">エラー! この電話機にはローカルシェルがありません.</string> + <string name="notification_text">%1$s でベルが鳴りました</string> + <string name="no">いいえ</string> + <string name="with_confirmation">確認が必要</string> + <string name="yes">はい</string> + <string name="exceptions_submit_message">前回ConnectBot実行時に問題が発生したようです。ConnectBotの開発者にエラーレポートを送信しますか?</string> + <string name="menu_colors_reset">リセット</string> + <string name="app_is_running">ConnectBot起動中</string> + <string name="color_red">赤</string> + <string name="color_green">緑</string> + <string name="color_blue">青</string> + <string name="color_gray">グレー</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-ka/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title_host_editor">ჰოსტის შეცვლა</string> + <string name="title_help">დახმარება</string> + <string name="title_colors">ფერი</string> + <string name="resolve_connect">დაკავშირება</string> + <string name="menu_insert">ჰოსტის დამატება</string> + <string name="menu_delete">ჰოსტის წაშლა</string> + <string name="menu_preferences">პარამეტრები</string> + <string name="help_about">ConnectBot-ის შესახებ</string> + <string name="help_keyboard">კლავიატურა</string> + <string name="pubkey_generate">გენერირება</string> + <string name="pubkey_import">იმპორტი</string> + <string name="pubkey_delete">გასაღების წაშლა</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-ko/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,189 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">간단하고, 강력한, 오픈소스 SSH 클라이언트.</string> + <string name="title_hosts_list">호스트</string> + <string name="title_pubkey_list">공개키</string> + <string name="title_port_forwards_list">포트 포워딩</string> + <string name="title_host_editor">호스트 편집</string> + <string name="title_help">도움말</string> + <string name="title_colors">색상</string> + <string name="resolve_connect">접속</string> + <string name="resolve_entropy">엔트로피 수집</string> + <string name="menu_insert">호스트 추가</string> + <string name="menu_delete">호스트 삭제</string> + <string name="menu_preferences">기본 설정</string> + <string name="help_intro">아래의 제목들을 선택하면 특정 주제의 정보를 더 알 수 있습니다.</string> + <string name="help_about">ConnectBot 정보</string> + <string name="help_keyboard">키보드</string> + <string name="pubkey_generate">생성</string> + <string name="pubkey_import">가져오기</string> + <string name="pubkey_delete">키 삭제</string> + <string name="pubkey_gather_entropy">엔트로피 수집 중</string> + <string name="pubkey_touch_prompt">이 사각형의 랜덤으로 터치하세요: %1$d%% 완료</string> + <string name="pubkey_touch_hint">키 생성시 랜덤을 보장하기 위해 아래의 사각형 안에서 손가락을 랜덤으로 이동하십시오.</string> + <string name="pubkey_generating">"키 쌍 생성 중…"</string> + <string name="pubkey_copy_private">개인 키 복사</string> + <string name="pubkey_copy_public">공개 키 복사</string> + <string name="pubkey_list_empty">메뉴 버튼을 눌러 키 쌍을\n만들거나 가져 옵니다.</string> + <string name="pubkey_unknown_format">알 수 없는 형식</string> + <string name="pubkey_change_password">암호 바꾸기</string> + <string name="pubkey_list_pick">/sdcard에서 선택</string> + <string name="pubkey_import_parse_problem">가져온 개인키 분석 중 문제 발생</string> + <string name="pubkey_unlock">키 잠금 해제</string> + <string name="pubkey_memory_load">메모리에 올리기</string> + <string name="pubkey_memory_unload">메모리에서 내리기</string> + <string name="pubkey_load_on_start">시작할 때 키를 올리기</string> + <string name="pubkey_confirm_use">사용 전에 확인</string> + <string name="portforward_list_empty">메뉴를 눌러\n포트 포워딩을 만듭니다.</string> + <string name="portforward_edit">포트 포워딩 편집</string> + <string name="portforward_delete">포트 포워딩을 삭제</string> + <string name="prompt_nickname">대화명:</string> + <string name="prompt_nickname_hint_pubkey">내 작업 키</string> + <string name="prompt_source_port">원본 포트:</string> + <string name="prompt_destination">설명:</string> + <string name="prompt_old_password">이전 암호:</string> + <string name="prompt_password">암호:</string> + <string name="prompt_again">(다시)</string> + <string name="prompt_type">종류:</string> + <string name="prompt_password_can_be_blank">참고: 암호는 비워둘 수 있습니다.</string> + <string name="prompt_bits">비트:</string> + <string name="host_verification_failure_warning_header">경고: 원격 호스트의 식별이 바뀌었습니다!</string> + <string name="host_verification_failure_warning">누군가가 나쁜 짓을 하고 있는 것일 수 있습니다!\n지금 누군가가 당신을 도청하고 있을 수도 있습니다 (중간자 공격)!\n또는, 단순히 호스트 키가 바뀐 것일 수도 있습니다.</string> + <string name="prompt_host_disconnected">호스트 연결이 끊겼습니다.\n세션을 닫을까요?</string> + <string name="prompt_continue_connecting">정말로 연결을 진행하기\n바랍니까?</string> + <string name="host_fingerprint">호스트 %1$s 키 지문은 %2$s</string> + <string name="alert_passwords_do_not_match_msg">암호가 맞지 않습니다!</string> + <string name="alert_wrong_password_msg">잘못된 암호입니다!</string> + <string name="alert_key_corrupted_msg">개인 키가 손상되었습니다!</string> + <string name="alert_sdcard_absent">SD 카드가 삽입되지 않습니다!</string> + <string name="button_add">추가</string> + <string name="button_change">바꾸기</string> + <string name="button_generate">키 생성</string> + <string name="button_resize">크기 조정</string> + <string name="alert_disconnect_msg">연결이 끊어짐</string> + <string name="pref_emulation_category">터미널 에뮬레이션</string> + <string name="pref_emulation_title">에뮬레이션 모드</string> + <string name="pref_emulation_summary">PTY 연결 용 터미널 에뮬레이션 모드</string> + <string name="pref_scrollback_title">스크롤 크기</string> + <string name="pref_scrollback_summary">각 콘솔별로 메모리에 담아 둘 스크롤 버퍼의 크기</string> + <string name="pref_ui_category">사용자 인터페이스</string> + <string name="pref_rotation_title">회전 모드</string> + <string name="pref_rotation_summary">키보드 팝 인/아웃시 회전 방법</string> + <string name="pref_fullscreen_title">전체 화면</string> + <string name="pref_fullscreen_summary">콘솔일 때 상태 표시줄을 숨김</string> + <string name="pref_memkeys_title">메모리에 키를 기억</string> + <string name="pref_memkeys_summary">백엔드 서비스가 종료되기 전까지 잠금이 풀린 키들을 메모리에 유지합니다</string> + <string name="pref_update_title">업데이트 검사</string> + <string name="pref_update_summary">ConnectBot 업데이트 확인 주기 설정</string> + <string name="pref_conn_persist_title">접속 유지</string> + <string name="pref_conn_persist_summary">백그라운드 동안에도 강제로 연결된 상태 유지</string> + <string name="pref_keymode_title">디렉터리 바로 가기</string> + <string name="pref_camera_title">카메라 바로 가기</string> + <string name="pref_camera_summary">카메라 버튼을 눌러 실행할 바로 가기 선택</string> + <string name="pref_keepalive_title">화면 켜짐 유지</string> + <string name="pref_keepalive_summary">콘솔 작업 중 화면이 꺼지는 것을 방지</string> + <string name="pref_wifilock_title">Wi-Fi 켜짐 유지</string> + <string name="pref_wifilock_summary">세션이 유효한 동안 Wi-Fi가 꺼지지 않도록 함</string> + <string name="pref_bumpyarrows_title">방향키 진동</string> + <string name="pref_bumpyarrows_summary">트랙볼로 방향키를 보낼 때 진동합니다; 연결이 느린 경우 유용</string> + <string name="pref_bell_category">터미널 벨</string> + <string name="pref_bell_title">벨소리</string> + <string name="pref_bell_volume_title">벨 볼륨</string> + <string name="pref_bell_vibrate_title">진동 벨</string> + <string name="pref_bell_notification_title">백그라운드 알림</string> + <string name="pref_bell_notification_summary">백그라운드에서 실행중인 터미널 벨을 울리 때 알립니다.</string> + <string name="list_keymode_right">오른쪽의 키들 사용</string> + <string name="list_keymode_left">왼쪽의 키들 사용</string> + <string name="list_keymode_none">사용 안 함</string> + <string name="list_pubkeyids_none">키 사용 안함</string> + <string name="list_pubkeyids_any">잠금키 사용</string> + <string name="hostpref_nickname_title">닉네임</string> + <string name="hostpref_color_title">색상 카테고리</string> + <string name="hostpref_fontsize_title">글꼴 크기 (pt)</string> + <string name="hostpref_pubkeyid_title">공개 키 인증 사용</string> + <string name="hostpref_authagent_title">SSH 인증 에이전트 사용</string> + <string name="hostpref_postlogin_title">로그인 후 자동 실행</string> + <string name="hostpref_postlogin_summary">인증 후 원격 서버에서 실행될 명령어들</string> + <string name="hostpref_compression_title">압축</string> + <string name="hostpref_compression_summary">네트워크가 느린 경우 유용</string> + <string name="hostpref_wantsession_title">쉘 세션 시작</string> + <string name="hostpref_wantsession_summary">포트 포워드만 사용할 경우 이 설정을 해제 하세요</string> + <string name="hostpref_stayconnected_title">연결 유지</string> + <string name="hostpref_stayconnected_summary">연결이 끊기면 다시 연결을 시도</string> + <string name="hostpref_delkey_title">삭제 키</string> + <string name="hostpref_delkey_summary">삭제 키를 눌렀을 때 보낼 키 코드</string> + <string name="hostpref_encoding_title">인코딩</string> + <string name="hostpref_encoding_summary">호스트의 문자 인코딩</string> + <string name="hostpref_connection_category">접속 설정</string> + <string name="hostpref_username_title">사용자 이름</string> + <string name="hostpref_hostname_title">호스트</string> + <string name="hostpref_port_title">포트</string> + <string name="bind_never">연결된 적 없음</string> + <string name="bind_minutes">%1$s 분 전</string> + <string name="bind_hours">%1$s 시간 전</string> + <string name="bind_days">%1$s 일 전</string> + <string name="console_copy_done">클립 보드에 %1$d 바이트가 복사되었습니다.</string> + <string name="console_copy_start">터치 후 드래그 또는\n방향 키로\n복사 영역을 선택</string> + <string name="console_menu_close">닫기</string> + <string name="console_menu_copy">복사</string> + <string name="console_menu_paste">붙여넣기</string> + <string name="console_menu_portforwards">포트 포워드</string> + <string name="console_menu_resize">크기 고정</string> + <string name="console_menu_urlscan">URL 검색</string> + <string name="button_yes">예</string> + <string name="button_no">아니오</string> + <string name="portforward_local">로컬</string> + <string name="portforward_remote">원격</string> + <string name="portforward_dynamic">동적 (SOCKS)</string> + <string name="portforward_pos">포트 포워딩 만들기</string> + <string name="portforward_done">포트 포워딩을 만드는 데 성공했습니다.</string> + <string name="portforward_menu_add">포트 포워딩 추가</string> + <string name="list_format_error">%1$s 형식을 사용</string> + <string name="format_username">사용자 이름</string> + <string name="format_hostname">호스트 이름</string> + <string name="format_port">포트</string> + <string name="list_menu_pubkeys">개인키 관리자</string> + <string name="list_menu_sortcolor">색상순 정렬</string> + <string name="list_menu_sortname">이름순 정렬</string> + <string name="list_menu_settings">설정</string> + <string name="list_host_disconnect">연결끊기</string> + <string name="list_host_edit">호스트 편집</string> + <string name="list_host_portforwards">포트 포워딩 편집</string> + <string name="list_host_delete">호스트 삭제</string> + <string name="list_host_empty">아래의 빠른-연결 상자로\n호스트에 연결할 수 있습니다.</string> + <string name="list_rotation_default">기본</string> + <string name="list_rotation_land">가로 고정</string> + <string name="list_rotation_port">세로 고정</string> + <string name="list_rotation_auto">자동</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A 후 Space</string> + <string name="list_hwbutton_none">없음</string> + <string name="list_delkey_backspace">백스페이스</string> + <string name="list_delkey_del">삭제</string> + <string name="delete_pos">예, 삭제</string> + <string name="delete_neg">취소</string> + <string name="wizard_agree">동의</string> + <string name="wizard_next">다음</string> + <string name="wizard_back">뒤로</string> + <string name="terminal_no_hosts_connected">현재 연결된 호스트가 없음</string> + <string name="terminal_connecting">%3$s(으)로 %1$s:%2$d에 연결 중</string> + <string name="terminal_failed">호스트 키를 확인할 수 없습니다.</string> + <string name="terminal_using_s2c_algorithm">서버->클라이언트 알고리즘: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">클라이언트->서버 알고리즘: %1$s %2$s</string> + <string name="terminal_using_algorithm">사용중인 알고리즘: %1$s %2$s</string> + <string name="terminal_auth">인증 시도 중</string> + <string name="terminal_auth_pubkey_invalid">선택된 공개 키가 잘못되었습니다. 호스트 편집에서 키를 다시 선택해 보세요</string> + <string name="terminal_no_session">호스트 설정 동안에는 세션이 시작되지 않을 것 입니다.</string> + <string name="terminal_enable_portfoward">포트 포워딩 사용: %1$s</string> + <string name="local_shell_unavailable">실패! 이 폰은 로컬 쉘을 사용할 수 없습니다.</string> + <string name="notification_text">%1$s에서 알림이 있습니다.</string> + <string name="no">아니오</string> + <string name="with_confirmation">확인 작업 수행</string> + <string name="yes">예</string> + <string name="exceptions_submit_message">마지막으로 ConnectBot이 실행했을 때 문제가 있었던 것 같습니다. ConnectBot 개발자에 오류 보고서를 보내시겠습니까?</string> + <string name="menu_colors_reset">초기화</string> + <string name="app_is_running">ConnectBot 실행 중</string> + <string name="color_red">빨간색</string> + <string name="color_green">녹색</string> + <string name="color_blue">파란색</string> + <string name="color_gray">회색</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-lt/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title_help">Pagalba</string> + <string name="title_colors">Spalvos</string> + <string name="resolve_connect">Prisijungti</string> + <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> + <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-lv/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-mk/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Едноставен но моќен SSH клиент со отворен код.</string> + <string name="service_desc">Ги оддрѓува SSH конекциите и вчитаните pub клучеви</string> + <string name="title_hosts_list">Хостови</string> + <string name="title_pubkey_list">Pub клучеви</string> + <string name="title_host_editor">Промени хост</string> + <string name="title_help">Помош</string> + <string name="title_colors">Бои</string> + <string name="resolve_connect">Поврзи се</string> + <string name="menu_insert">Додај хост</string> + <string name="menu_delete">Одстрани хост</string> + <string name="menu_preferences">Параметри</string> + <string name="help_intro">Одбеи тема од подолу наведените за повеќе информации за таа тема.</string> + <string name="help_about">За ConnectBot</string> + <string name="help_keyboard">Тастатура</string> + <string name="pubkey_generate">Генерирај</string> + <string name="pubkey_import">Увези</string> + <string name="pubkey_delete">Одстрани клуч</string> + <string name="pubkey_generating">Се генерира пар на клучеви</string> + <string name="pubkey_copy_private">Копирај го приватниот клуч</string> + <string name="pubkey_copy_public">Копирај го јавниот клуч</string> + <string name="pubkey_list_empty">Притисни мени за да направиш\nили увезеш нов пар на клучеви</string> + <string name="pubkey_unknown_format">Непознат тип</string> + <string name="pubkey_change_password">Промени лозинка</string> + <string name="pubkey_list_pick">Превземи од /sdcard</string> + <string name="pubkey_import_parse_problem">Проблем со анализирањето на увезениот приватен клуч</string> + <string name="pubkey_unlock">Клуч за отклучување</string> + <string name="pubkey_failed_add">Погрешна лозинка за клучот \'%1$s\'. Неуспешна авторизација.</string> + <string name="pubkey_memory_load">Вчитај во меморија</string> + <string name="pubkey_memory_unload">Извади од меморијата</string> + <string name="pubkey_load_on_start">Вчитај клуч при вклучување</string> + <string name="pubkey_confirm_use">Побарај потврда пред користење</string> + <string name="prompt_nickname">Прекар:</string> + <string name="prompt_nickname_hint_pubkey">Мојот работен клуч</string> + <string name="prompt_source_port">Изворна порта:</string> + <string name="prompt_destination">Дестинација:</string> + <string name="prompt_old_password">Стара лозинка:</string> + <string name="prompt_password">Лозинка:</string> + <string name="prompt_again">(повторно)</string> + <string name="prompt_type">Тип:</string> + <string name="prompt_password_can_be_blank">Белешка: Лозинката не мора да се впише</string> + <string name="prompt_bits">Битови:</string> + <string name="prompt_pubkey_password">Лозинка за \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Дозволи му на одалечениот хост\nда го искористи \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">ПРЕДУПРЕДУВАЊЕ: ИДЕНТИФИКАЦИЈАТА НА ОДАЛЕЧЕНИОТ ХОСТ Е ПРОМЕНЕТА!</string> + <string name="host_verification_failure_warning">МОЖНО Е НЕКОЈ ДА ПРАВИ НЕШТО ЛОШО!\nНекој можеби ве прислушкува сега (напад човек во средина)!\nИсто така можно е да се променил клучот на одалечениот хост.</string> + <string name="prompt_host_disconnected">Хостот се дисконектираше.\nЗатвори ја сесијата?</string> + <string name="prompt_continue_connecting">Дали си сигурен дека\nсакаш да продолжиш со поврзување?</string> + <string name="host_authenticity_warning">Автентичноста на \'%1$s\' не може да биде потврдена.</string> + <string name="alert_passwords_do_not_match_msg">Лозинките не се совпаѓаат!</string> + <string name="alert_wrong_password_msg">Погрешна лозинка!</string> + <string name="alert_key_corrupted_msg">Приватниот клуч е корумпиран!</string> + <string name="alert_sdcard_absent">СД картичката не е ставена!</string> + <string name="button_add">Додај</string> + <string name="button_change">Промени</string> + <string name="button_generate">Направи клуч</string> + <string name="button_resize">Промени големина</string> + <string name="alert_disconnect_msg">Врската е изгубена</string> + <string name="pref_emulation_category">Емулација на терминал</string> + <string name="pref_emulation_title">Вид на емулација</string> + <string name="pref_emulation_summary">Вид на емулација на терминал да се користи за PTY врски</string> + <string name="pref_ui_category">Кориснички интерфејс</string> + <string name="pref_fullscreen_title">На цел екран</string> + <string name="pref_fullscreen_summary">Сокриј ја статусната трака додека си во конзола</string> + <string name="pref_memkeys_title">Запомни ги клучевите во меморија</string> + <string name="pref_update_title">Проверка на ажурирања</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-nb/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Enkel og omfattende SSH-klient med åpen kildekode.</string> + <string name="service_desc">Opprettholder SSH-tilkoblinger og innlastede offentlige nøkler</string> + <string name="title_hosts_list">Verter</string> + <string name="title_pubkey_list">Offentlige nøkler</string> + <string name="title_port_forwards_list">Portvideresending</string> + <string name="title_host_editor">Rediger vert</string> + <string name="title_help">Hjelp</string> + <string name="title_colors">Farger</string> + <string name="resolve_connect">Koble til</string> + <string name="resolve_entropy">Samle entropi</string> + <string name="menu_insert">Legg til vert</string> + <string name="menu_delete">Slett vert</string> + <string name="menu_preferences">Innstillinger</string> + <string name="help_intro">Velg en overskrift nedenfor for mer informasjon om et bestemt emne.</string> + <string name="help_about">Om ConnectBot</string> + <string name="help_keyboard">Tastatur</string> + <string name="pubkey_generate">Generer</string> + <string name="pubkey_import">Importer</string> + <string name="pubkey_delete">Slett nøkkel</string> + <string name="pubkey_gather_entropy">Samler entropi</string> + <string name="pubkey_touch_prompt">Berør denne boksen for å samle tilfeldige tall: %1$d%% ferdig</string> + <string name="pubkey_touch_hint">Beveg fingeren over boksen nedenfor for å sikre vilkårlighet ved generering av nøkkel.</string> + <string name="pubkey_generating">"Genererer nøkkelpar…"</string> + <string name="pubkey_copy_private">Kopier privat nøkkel</string> + <string name="pubkey_copy_public">Kopier offentlig nøkkel</string> + <string name="pubkey_list_empty">Trykk \"Meny\" for å opprette\neller importere nøkkelpar.</string> + <string name="pubkey_unknown_format">Ukjent format</string> + <string name="pubkey_change_password">Endre passord</string> + <string name="pubkey_list_pick">Hent fra /sdcard</string> + <string name="pubkey_import_parse_problem">Feil ved innlasting av privat nøkkel</string> + <string name="pubkey_unlock">Frigjør nøkkel</string> + <string name="pubkey_failed_add">Feil passord for nøkkel \'%1$s\'. Autentisering mislyktes.</string> + <string name="pubkey_memory_load">Last inn i minne</string> + <string name="pubkey_memory_unload">Last ut av minne</string> + <string name="pubkey_load_on_start">Last nøkkel ved start</string> + <string name="pubkey_confirm_use">Godkjenn før bruk</string> + <string name="portforward_list_empty">Trykk \"Meny\" for å opprette\nportvideresending.</string> + <string name="portforward_edit">Rediger videresendte porter</string> + <string name="portforward_delete">Slett videresendte porter</string> + <string name="prompt_nickname">Kallenavn:</string> + <string name="prompt_nickname_hint_pubkey">Min arbeidsnøkkel</string> + <string name="prompt_source_port">Kildeport:</string> + <string name="prompt_destination">Mål:</string> + <string name="prompt_old_password">Tidligere passord:</string> + <string name="prompt_password">Passord:</string> + <string name="prompt_again">(en gang til)</string> + <string name="prompt_type">Type:</string> + <string name="prompt_password_can_be_blank">NB: passord kan stå tomt</string> + <string name="prompt_bits">Bits:</string> + <string name="prompt_pubkey_password">Passord for nøkkel \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Godta ekstern vert til\nå bruke nøkkel \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">ADVARSEL: EKSTERN VERT IDENTIFIKASJON HAR BLITT ENDRET!</string> + <string name="host_verification_failure_warning">DET KAN VÆRE UGLER I MOSEN!\nNoen kan lytte på deg akkurat nå (et mellommann-angrep)!\nMen det er også mulig at vertsnøkkelen har blitt endret.</string> + <string name="prompt_host_disconnected">Vert har koblet fra.\nLukk sesjon?</string> + <string name="prompt_continue_connecting">Er du sikker på at\ndu vil koble til?</string> + <string name="host_authenticity_warning">Kan ikke bekrefte integriteten til \'%1$s\'.</string> + <string name="host_fingerprint">Nøkkelfingeravtrykk til vert %1$s er %2$s</string> + <string name="alert_passwords_do_not_match_msg">Passordene er ikke like!</string> + <string name="alert_wrong_password_msg">Feil passord!</string> + <string name="alert_key_corrupted_msg">Privat nøkkel ser ut til å være korrupt!</string> + <string name="alert_sdcard_absent">SD-kortet er ikke satt inn!</string> + <string name="button_add">Legg til</string> + <string name="button_change">Endre</string> + <string name="button_generate">Generer nøkkel</string> + <string name="button_resize">Endre størrelse</string> + <string name="alert_disconnect_msg">Mistet tilkobling</string> + <string name="pref_emulation_category">Terminalemulering</string> + <string name="pref_emulation_title">Etterligningsmodus</string> + <string name="pref_emulation_summary">Etterligningsmodus for terminal for PTY-tilkoblinger</string> + <string name="pref_scrollback_title">Husk skjermtekst</string> + <string name="pref_scrollback_summary">Mengde skjermtekst som skal beholdes i minnet for hvert konsollvindu</string> + <string name="pref_ui_category">Brukergrensesnitt</string> + <string name="pref_rotation_title">Rotasjonsretning</string> + <string name="pref_rotation_summary">Hvordan rotasjonsretning endres når tastatur skyves inn/ut</string> + <string name="pref_fullscreen_title">Full skjerm</string> + <string name="pref_fullscreen_summary">Gjem statuslinje mens du er i konsoll</string> + <string name="pref_memkeys_title">Lagre nøkler</string> + <string name="pref_memkeys_summary">Husk opplåste nøkler helt til programmet avsluttes</string> + <string name="pref_update_title">Se etter oppdateringer</string> + <string name="pref_update_summary">Angi hyppigheten for å se etter oppdateringer til ConnectBot</string> + <string name="pref_conn_persist_title">Oppretthold forbindelser</string> + <string name="pref_conn_persist_summary">Oppretthold forbindelser selv når programmet kjører i bakgrunnen</string> + <string name="pref_keymode_title">Hurtigtaster for mapper</string> + <string name="pref_keymode_summary">Velg hvordan Alt- og Skift-tasten skal brukes for \'/\' og Tab</string> + <string name="pref_camera_title">Snarvei til kamera</string> + <string name="pref_camera_summary">Velg hvilken snarvei som skal benyttes når kameraknapp trykkes</string> + <string name="pref_keepalive_title">Hold skjerm våken</string> + <string name="pref_keepalive_summary">Unngå at skjermen slås av når du jobber konsoll</string> + <string name="pref_wifilock_title">Hold Wi-Fi aktiv</string> + <string name="pref_wifilock_summary">Hindre Wi-Fi å koble fra når en økt er aktiv</string> + <string name="pref_bumpyarrows_title">Vibrerende piler</string> + <string name="pref_bumpyarrows_summary">Vibrer når pilkommandoer sendes med styrekule; nyttig for trege forbindelser</string> + <string name="pref_bell_category">Terminalklokke</string> + <string name="pref_bell_title">Varselklokke</string> + <string name="pref_bell_volume_title">Klokkevolum</string> + <string name="pref_bell_vibrate_title">Vibrere med bjelle</string> + <string name="pref_bell_notification_title">Bakgrunnsvarsling</string> + <string name="pref_bell_notification_summary">Vis varsling når en terminal i bakgrunnen gir et klokkevarsel.</string> + <string name="list_keymode_right">Bruk knapper på høyre side</string> + <string name="list_keymode_left">Bruk knapper på venstre side</string> + <string name="list_keymode_none">Deaktiver</string> + <string name="list_pubkeyids_none">Ikke bruk nøkler</string> + <string name="list_pubkeyids_any">Bruk en vilkårlig ulåst tast</string> + <string name="hostpref_nickname_title">Kallenavn</string> + <string name="hostpref_color_title">Fargeinndeling</string> + <string name="hostpref_fontsize_title">Skriftstørrelse (pt)</string> + <string name="hostpref_pubkeyid_title">Bruk offentlig nøkkel som godkjenning</string> + <string name="hostpref_authagent_title">Bruk SSH auth-agent</string> + <string name="hostpref_postlogin_title">Kommandoer etter innlogging</string> + <string name="hostpref_postlogin_summary">Kommandoer som kjøres på tilkoblet tjener etter vellykket autentisering</string> + <string name="hostpref_compression_title">Komprimering</string> + <string name="hostpref_compression_summary">Dette kan hjelpe på trege nettverk</string> + <string name="hostpref_wantsession_title">Start skallsesjon</string> + <string name="hostpref_wantsession_summary">Deaktiver denne innstillingen og benytt denne kun for portvideresending</string> + <string name="hostpref_stayconnected_title">Oppretthold forbindelse</string> + <string name="hostpref_stayconnected_summary">Forsøk å koble til på nytt ved frakobling</string> + <string name="hostpref_delkey_title">DEL-knapp</string> + <string name="hostpref_delkey_summary">Tastekode som sendes når DEL trykkes</string> + <string name="hostpref_encoding_title">Tegnkoding</string> + <string name="hostpref_encoding_summary">Tegnkoding for verten</string> + <string name="hostpref_connection_category">Tilkoblingsinnstillinger</string> + <string name="hostpref_username_title">Brukernavn</string> + <string name="hostpref_hostname_title">Vert</string> + <string name="hostpref_port_title">Port</string> + <string name="bind_never">Aldri tilkoblet</string> + <string name="bind_minutes">%1$s minutt siden</string> + <string name="bind_hours">%1$s timer siden</string> + <string name="bind_days">%1$s dager siden</string> + <string name="console_copy_done">Kopierte %1$d bytes til utklippstavle</string> + <string name="console_copy_start">Trykk og dra, eller\nbruk styrekule for å\nvelge område å\nkopiere fra</string> + <string name="console_menu_close">Lukk</string> + <string name="console_menu_copy">Kopier</string> + <string name="console_menu_paste">Lim inn</string> + <string name="console_menu_portforwards">Portvideresending</string> + <string name="console_menu_resize">Tving størrelse</string> + <string name="console_menu_urlscan">URL-søk</string> + <string name="button_yes">Ja</string> + <string name="button_no">Nei</string> + <string name="portforward_local">Lokal</string> + <string name="portforward_remote">Ekstern</string> + <string name="portforward_dynamic">Dynamisk (SOCKS)</string> + <string name="portforward_pos">Opprett portvideresending</string> + <string name="portforward_done">Vellykket oppretting av portvideresending</string> + <string name="portforward_problem">Mislyktes å opprette portvideresending. Bruker du porter under 1024, eller er denne porten allerede tatt?</string> + <string name="portforward_menu_add">Legg til portvideresending</string> + <string name="hint_userhost">bruker\@vert</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="format_username">brukernavn</string> + <string name="format_hostname">vertsnavn</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Behandle offentlige nøkler</string> + <string name="list_menu_sortcolor">Sorter etter farge</string> + <string name="list_menu_sortname">Sorter etter navn</string> + <string name="list_menu_settings">Innstillinger</string> + <string name="list_host_disconnect">Koble fra</string> + <string name="list_host_edit">Rediger vert</string> + <string name="list_host_portforwards">Rediger portvidersendinger</string> + <string name="list_host_delete">Slett vert</string> + <string name="list_host_empty">Bruk hurtigtilkoblingsboksen\nunder for å koble til en vert.</string> + <string name="list_rotation_default">Forvalg</string> + <string name="list_rotation_land">Tving landskap</string> + <string name="list_rotation_port">Tving portrett</string> + <string name="list_rotation_auto">Automatisk</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A og mellomrom</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Ingen</string> + <string name="list_delkey_backspace">Tilbaketast</string> + <string name="list_delkey_del">Slett</string> + <string name="delete_message">Er du sikker på at du vil slette \'%1$s\'?</string> + <string name="delete_pos">Ja, slett</string> + <string name="delete_neg">Avbryt</string> + <string name="wizard_agree">Godta</string> + <string name="wizard_next">Neste</string> + <string name="wizard_back">Tilbake</string> + <string name="terminal_no_hosts_connected">Ingen verter tilkoblet for øyeblikket</string> + <string name="terminal_connecting">Kobler til %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">Verifiserte vert \'%1$s\' sin nøkkel: %2$s</string> + <string name="terminal_failed">Verifisering av vertsnøkkelen feilet.</string> + <string name="terminal_using_s2c_algorithm">Algoritme fra tjener til klient: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algoritme fra klient til tjener: %1$s %2$s</string> + <string name="terminal_using_algorithm">Bruker algoritme: %1$s %2$s</string> + <string name="terminal_auth">Forsøker å autentisere</string> + <string name="terminal_auth_pass">Forsøker \'passord\'-autentisering</string> + <string name="terminal_auth_pass_fail">Autentiseringsmetode \'passord\' feilet</string> + <string name="terminal_auth_pubkey_any">Forsøker \'publickey\'-autentisering med lagrede offentlige nøkler</string> + <string name="terminal_auth_pubkey_invalid">Valgt offentlig nøkkel er ugyldig, forsøk å velge en annen nøkkel i vertsvinduet.</string> + <string name="terminal_auth_pubkey_specific">Forsøker \'publickey\'-autentisering med angitt offentlig nøkkel</string> + <string name="terminal_auth_pubkey_fail">Autentisering med \'publickey\' og nøkkel \'%1$s\' mislyktes</string> + <string name="terminal_auth_ki">Forsøker \'keyboard-interactive\' autentisering</string> + <string name="terminal_auth_ki_fail">Autentiseringsmetoden \'keyboard-interactive\' mislyktes</string> + <string name="terminal_auth_fail">[Din vert støtter ikke autentiseringsmetodene \'password\' eller \'keyboard-interactive\'.]</string> + <string name="terminal_no_session">Sesjonen vil ikke bli startet grunnet vertsinnstillinger.</string> + <string name="terminal_enable_portfoward">Aktiver portvideresending: %1$s</string> + <string name="local_shell_unavailable">Feil! Lokalt skall er utilgjengelig på denne telefonen.</string> + <string name="notification_text">%1$s ønsker din oppmerksomhet.</string> + <string name="no">Nei</string> + <string name="with_confirmation">Med bekreftelse</string> + <string name="yes">Ja</string> + <string name="exceptions_submit_message">Det ser ut som ConnectBot hadde et problem forrige gang den kjørte. Vil du sende en feilrapport til utviklerne av ConnectBot?</string> + <string name="menu_colors_reset">Tilbakestill</string> + <string name="app_is_running">ConnectBot kjører</string> + <string name="color_red">rød</string> + <string name="color_green">grønn</string> + <string name="color_blue">blå</string> + <string name="color_gray">grå</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-nl/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Simpele, krachtige, open-source SSH client.</string> + <string name="service_desc">Onderhoud SSH verbindingen en geladen pubkeys</string> + <string name="title_hosts_list">Hosts</string> + <string name="title_pubkey_list">Pubkeys</string> + <string name="title_port_forwards_list">Port forwards</string> + <string name="title_host_editor">Host bewerken</string> + <string name="title_help">Help</string> + <string name="title_colors">Kleuren</string> + <string name="resolve_connect">Verbinden</string> + <string name="resolve_entropy">Verzamel Entropie</string> + <string name="menu_insert">Host Toevoegen</string> + <string name="menu_delete">Host verwijderen</string> + <string name="menu_preferences">Voorkeuren</string> + <string name="help_intro">Selecteer hieronder een onderwerp voor meer informatie over een onderwerp.</string> + <string name="help_about">Over ConnectBot</string> + <string name="help_keyboard">Toetsenbord</string> + <string name="pubkey_generate">Genereren</string> + <string name="pubkey_import">Importeren</string> + <string name="pubkey_delete">Sleutel verwijderen</string> + <string name="pubkey_gather_entropy">Bezig met het verzamelen van Entropie</string> + <string name="pubkey_touch_prompt">Raak dit vierkant aan om willekeurigheid te verzamelen: %1$d%% gedaan</string> + <string name="pubkey_touch_hint">Beweeg je vinger in willekeurige volgorde over het vak beneden om er voor te zorgen dat de invoer willekeurig blijft.</string> + <string name="pubkey_generating">"Genereren van een sleutel paar…"</string> + <string name="pubkey_copy_private">Kopieer privé sleutel</string> + <string name="pubkey_copy_public">Kopieer publieke sleutel</string> + <string name="pubkey_list_empty">Tik op Menu om te maken\nof importeer sleutel paren.</string> + <string name="pubkey_unknown_format">Onbekend formaat</string> + <string name="pubkey_change_password">Verander wachtwoord</string> + <string name="pubkey_list_pick">Kies van /sdcard</string> + <string name="pubkey_import_parse_problem">Probleem met het parsen van geimporteerde privé sleutel</string> + <string name="pubkey_unlock">Ontgrendel sleutel</string> + <string name="pubkey_failed_add">Slecht wachtwoord voor sleutel \'%1$s\'. Authenticatie mislukt</string> + <string name="pubkey_memory_load">Laad in geheugen</string> + <string name="pubkey_memory_unload">Ontlaad uit geheugen</string> + <string name="pubkey_load_on_start">Laad sleutel op start</string> + <string name="pubkey_confirm_use">Bevestig voor gebruik</string> + <string name="portforward_list_empty">Tik Menu om poort\nforwards te maken.</string> + <string name="portforward_edit">Bewerk port forward</string> + <string name="portforward_delete">Verwijder port forward</string> + <string name="prompt_nickname">Bijnaam:</string> + <string name="prompt_nickname_hint_pubkey">Mijn werk sleutel</string> + <string name="prompt_source_port">Bron poort:</string> + <string name="prompt_destination">Bestemming:</string> + <string name="prompt_old_password">Oud wachtwoord:</string> + <string name="prompt_password">Wachtwoord:</string> + <string name="prompt_again">(opnieuw)</string> + <string name="prompt_type">Type:</string> + <string name="prompt_password_can_be_blank">Opmerking: wachtwoord kan leeg zijn</string> + <string name="prompt_bits">Bits:</string> + <string name="prompt_pubkey_password">Wachtwoord voor sleutel \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Sta host toe om \'%1$s\' \nsleutel te gebruiken ?</string> + <string name="host_verification_failure_warning_header">WAARSCHUWING: REMOTE HOST IDENTIFICATIE IS VERANDERD!</string> + <string name="host_verification_failure_warning">HET IS MOGELIJK DAT IEMAND ONGEWILD BEZIG IS!\nIemand kan nu misschien mee kijken met wat je aan het doen bent (man-in-the-middle attack)!\nHet is ook mogelijk dat de host sleutel veranderd is.</string> + <string name="prompt_host_disconnected">Host heeft de verbinding verbroken.\nSessie afsluiten?</string> + <string name="prompt_continue_connecting">Weet je zeker dat je\nwilt doorgaan met verbinden?</string> + <string name="host_authenticity_warning">De authenticatie van host \'%1$s\' kan niet worden vastgesteld.</string> + <string name="host_fingerprint">Host %1$s sleutel vingerafdruk is %2$s</string> + <string name="alert_passwords_do_not_match_msg">Wachtwoorden zijn niet hetzelfde!</string> + <string name="alert_wrong_password_msg">Verkeerd wachtwoord!</string> + <string name="alert_key_corrupted_msg">Privé sleutel lijkt corrupt!</string> + <string name="alert_sdcard_absent">SD kaart niet aanwezig!</string> + <string name="button_add">Voeg toe</string> + <string name="button_change">Verander</string> + <string name="button_generate">Genereer sleutel</string> + <string name="button_resize">Verander formaat</string> + <string name="alert_disconnect_msg">Verbinding verloren</string> + <string name="pref_emulation_category">Terminal emulatie</string> + <string name="pref_emulation_title">Emulatie mode</string> + <string name="pref_emulation_summary">Terminal emulatie mode voor gebruik in PTY verbindingen</string> + <string name="pref_scrollback_title">Scrollback grootte</string> + <string name="pref_scrollback_summary">Grootte van scrollback buffer om in geheugen te houden voor elke console</string> + <string name="pref_ui_category">Gebruikers interface</string> + <string name="pref_rotation_title">Rotatie mode</string> + <string name="pref_rotation_summary">Hoe rotatie te veranderen wanneer keyboard in/uit geschoven is</string> + <string name="pref_fullscreen_title">Volledig scherm</string> + <string name="pref_fullscreen_summary">Verberg status balk terwijl in console</string> + <string name="pref_memkeys_title">Onthoud sleutels in geheugen</string> + <string name="pref_memkeys_summary">Houd ontgrendelde sleutels in geheugen tot achtergrond service is gestopt</string> + <string name="pref_update_title">Update controle</string> + <string name="pref_update_summary">Stel de maximale frequentie in om te controleren voor ConnectBot updates</string> + <string name="pref_conn_persist_title">Behoud verbindingen</string> + <string name="pref_conn_persist_summary">Forceer dat de verbindingen actief blijven op de achtergrond</string> + <string name="pref_keymode_title">Folder snelkoppelingen</string> + <string name="pref_keymode_summary">Selecteer hoe Alt voor \'/\' en Shift voor Tab te gebruiken</string> + <string name="pref_camera_title">Camera snelkoppeling</string> + <string name="pref_camera_summary">Selecteer welke snelkoppeling te activeren wanneer camera knop is ingedrukt</string> + <string name="pref_keepalive_title">Houd scherm wakker</string> + <string name="pref_keepalive_summary">Voorkom scherm van uitgaan wanneer er gewerkt word in een console</string> + <string name="pref_wifilock_title">Houd Wi-Fi actief</string> + <string name="pref_wifilock_summary">Voorkom Wi-Fi van uitgaan wanneer er een sessie actief is</string> + <string name="pref_bumpyarrows_title">Hobbelige pijlen</string> + <string name="pref_bumpyarrows_summary">Tril als pijl knoppen worden gestuurd van trackball; handig voor langzame verbindingen</string> + <string name="pref_bell_category">Terminal bel</string> + <string name="pref_bell_title">Hoorbare bel</string> + <string name="pref_bell_volume_title">Bel volume</string> + <string name="pref_bell_vibrate_title">Tril bij bel</string> + <string name="pref_bell_notification_title">Achtergrond notificaties</string> + <string name="pref_bell_notification_summary">Stuur notificatie als terminal in de achtergrond een bel laat klinken.</string> + <string name="list_keymode_right">Gebruik rechter kant sleutels</string> + <string name="list_keymode_left">Gebruik linker kant sleutels</string> + <string name="list_keymode_none">Schakel uit</string> + <string name="list_pubkeyids_none">Gebruik sleutels niet</string> + <string name="list_pubkeyids_any">Gebruik een willekeurige ontgrendelde sleutel</string> + <string name="hostpref_nickname_title">Bijnaam</string> + <string name="hostpref_color_title">Kleur catogorie</string> + <string name="hostpref_fontsize_title">Lettergrootte</string> + <string name="hostpref_pubkeyid_title">Gebruik pubkey authenticatie</string> + <string name="hostpref_authagent_title">Gebruik SSH auth agent</string> + <string name="hostpref_postlogin_title">Na-login automatie</string> + <string name="hostpref_postlogin_summary">Commando\'s om uit te voeren op de remote server wanneer geauthenticeerd</string> + <string name="hostpref_compression_title">Compressie</string> + <string name="hostpref_compression_summary">Dit kan helpen bij langzame netwerken</string> + <string name="hostpref_wantsession_title">Start shell sessie</string> + <string name="hostpref_wantsession_summary">Schakel dit uit om alleen port forwards te gebruiken</string> + <string name="hostpref_stayconnected_title">Blijf verbonden</string> + <string name="hostpref_stayconnected_summary">Verbinding automatisch proberen te herstellen</string> + <string name="hostpref_delkey_title">Del-toets</string> + <string name="hostpref_delkey_summary">De toetscode als de DEL-knop in wordt gedrukt</string> + <string name="hostpref_encoding_title">Codering</string> + <string name="hostpref_encoding_summary">Tekencodering voor de host</string> + <string name="hostpref_connection_category">Verbindings instellingen</string> + <string name="hostpref_username_title">Gebruikersnaam</string> + <string name="hostpref_hostname_title">Host</string> + <string name="hostpref_port_title">Poort</string> + <string name="bind_never">Nooit verbonden</string> + <string name="bind_minutes">%1$s minuten geleden</string> + <string name="bind_hours">%1$s uren geleden</string> + <string name="bind_days">%1$s dagen geleden</string> + <string name="console_copy_done">%1$d bytes gekopieerd naar het klembord</string> + <string name="console_copy_start">Tik en sleep\nof gebruik directioneel pad\nom velden te selecteren omte kopiëren</string> + <string name="console_menu_close">Sluit</string> + <string name="console_menu_copy">Kopieer</string> + <string name="console_menu_paste">Plak</string> + <string name="console_menu_portforwards">Port Forwards</string> + <string name="console_menu_resize">Forceer grootte</string> + <string name="console_menu_urlscan">URK Scan</string> + <string name="button_yes">Ja</string> + <string name="button_no">Nee</string> + <string name="portforward_local">Lokaal</string> + <string name="portforward_remote">Op afstand</string> + <string name="portforward_dynamic">Dynamisch (SOCKS)</string> + <string name="portforward_pos">Maak port forward</string> + <string name="portforward_done">Succesvol port forward gemaakt</string> + <string name="portforward_problem">Probleem met het maken van een port forward, misschien gebruik je poort onder 1024 of is de poort al gebruikt?</string> + <string name="portforward_menu_add">Voeg port forward toe</string> + <string name="hint_userhost">gebruiker\@hostnaam</string> + <string name="list_format_error">Gebruik het formaat %1$s</string> + <string name="format_username">gebruiker</string> + <string name="format_hostname">hostnaam</string> + <string name="format_port">poort</string> + <string name="list_menu_pubkeys">Beheer Pubkeys</string> + <string name="list_menu_sortcolor">Sorteer op kleur</string> + <string name="list_menu_sortname">Sorteer op naam</string> + <string name="list_menu_settings">Instellingen</string> + <string name="list_host_disconnect">Verbreek verbinding</string> + <string name="list_host_edit">Bewerk host</string> + <string name="list_host_portforwards">Bewerk port forwards</string> + <string name="list_host_delete">Verwijder hosts</string> + <string name="list_host_empty">Gebruik het snel-verbindings vierkant\nonder om een host te verbinden.</string> + <string name="list_rotation_default">Standaard</string> + <string name="list_rotation_land">Forceer landschap</string> + <string name="list_rotation_port">Forceer portret</string> + <string name="list_rotation_auto">Automatisch</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A en dan Spatie</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Geen</string> + <string name="list_delkey_backspace">Backspace</string> + <string name="list_delkey_del">Verwijderen</string> + <string name="delete_message">Weet je zeker dat je \'%1$s\' wilt verwijderen?</string> + <string name="delete_pos">Ja, verwijder</string> + <string name="delete_neg">Annuleren</string> + <string name="wizard_agree">Ga akkoord</string> + <string name="wizard_next">Volgende</string> + <string name="wizard_back">Terug</string> + <string name="terminal_no_hosts_connected">Momenteel geen hosts verbonden</string> + <string name="terminal_connecting">Bezig met verbinden naar %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">Gecontroleerde host \'%1$s\' sleutel: %2$s</string> + <string name="terminal_failed">Host sleutel verificatie mislukt</string> + <string name="terminal_using_s2c_algorithm">Server-naar-cliënt algoritme: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Cliënt-naar-server algoritme: %1$s %2$s</string> + <string name="terminal_using_algorithm">Gebruikt algoritme: %1$s %2$s</string> + <string name="terminal_auth">Probeert te authenticeren</string> + <string name="terminal_auth_pass">Probeert \'wachtwoord\' authenticatie</string> + <string name="terminal_auth_pass_fail">Authenticatie methode \'wachtwoord\' mislukt</string> + <string name="terminal_auth_pubkey_any">Probeert \'publieke sleutel\' authenticatie met een willekeurige in-geheugen publieke sleutel</string> + <string name="terminal_auth_pubkey_invalid">Geselecteerde publieke sleutel is ongeldig, probeer herselecteren van de sleutel in de host bewerker</string> + <string name="terminal_auth_pubkey_specific">Probeert \'publickey\' authenticatie met een specifieke publieke sleutel</string> + <string name="terminal_auth_pubkey_fail">Authenticatie methode \'publickey\' met sleutel \'%1$s\' gefaald</string> + <string name="terminal_auth_ki">Probeert \'keyboard-interactive\' authenticatie</string> + <string name="terminal_auth_ki_fail">Authenticatie methode \'keyboard-interactive\' mislukt</string> + <string name="terminal_auth_fail">[Uw host ondersteund \'wachtwoord\' of \'keyboard-interactive\' authenticatie niet.]</string> + <string name="terminal_no_session">Sessie zal niet gestart worden door host instelling</string> + <string name="terminal_enable_portfoward">Activeer port forward: %1$s</string> + <string name="local_shell_unavailable">Mislukking! Lokale shell is niet beschikbaar op deze telefoon.</string> + <string name="notification_text">%1$s wil je aandacht.</string> + <string name="no">Nee</string> + <string name="with_confirmation">Met toestemming</string> + <string name="yes">Ja</string> + <string name="exceptions_submit_message">Het lijkt erop dat ConnectBot een probleem had de laatste keer dat het gebruikt werd. Wilt u een foutenrapport naar de ConnectBot ontwikkelaars sturen?</string> + <string name="menu_colors_reset">Terug naar standaardinstellingen</string> + <string name="app_is_running">ConnectBot werkt (Connecties zijn actief)</string> + <string name="color_red">rood</string> + <string name="color_green">groen</string> + <string name="color_blue">blauw</string> + <string name="color_gray">grijs</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-oc/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Un client SSH simple, open-source e poderós.</string> + <string name="title_hosts_list">Òstes</string> + <string name="title_pubkey_list">Claus publicas</string> + <string name="title_port_forwards_list">Redireccions de pòrts</string> + <string name="title_host_editor">Modificar lo servidor</string> + <string name="title_help">Ajuda</string> + <string name="resolve_connect">Connexion</string> + <string name="resolve_entropy">Generacion d\'aleatòri</string> + <string name="menu_insert">Apondre un servidor</string> + <string name="menu_delete">Supprimir lo servidor</string> + <string name="menu_preferences">Preferéncias</string> + <string name="help_intro">Seleccionatz un subjècte çaijós per mai d\'entresenhas.</string> + <string name="help_about">A prepaus de ConnectBot</string> + <string name="help_keyboard">Clavièr</string> + <string name="pubkey_generate">Generar</string> + <string name="pubkey_import">Importar</string> + <string name="pubkey_delete">Suprimir la clau</string> + <string name="pubkey_gather_entropy">Generacion d\'aleatòri</string> + <string name="pubkey_touch_prompt">Tocatz aquesta bóstia per recuperar un nombre aleatòri : %1$d%% fach</string> + <string name="pubkey_copy_private">Copiar la clau privada</string> + <string name="pubkey_copy_public">Copiar la clau publica</string> + <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> + <string name="pubkey_unknown_format">Format desconegut</string> + <string name="pubkey_change_password">Modificar lo senhal</string> + <string name="pubkey_list_pick">Recuperar dempuèi /sdcard</string> + <string name="pubkey_confirm_use">Confirmar abans utilizacion</string> + <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> + <string name="prompt_nickname">Escais :</string> + <string name="prompt_nickname_hint_pubkey">Ma clau de trabalh</string> + <string name="prompt_destination">Destinacion :</string> + <string name="prompt_old_password">Senhal ancian :</string> + <string name="prompt_password">Senhal :</string> + <string name="prompt_again">(encara)</string> + <string name="prompt_type">Tipe :</string> + <string name="prompt_bits">Bits :</string> + <string name="alert_wrong_password_msg">Marrit senhal</string> + <string name="button_add">Apondre</string> + <string name="button_change">Cambiar</string> + <string name="button_generate">Generar una clau</string> + <string name="button_resize">Redimensionar</string> + <string name="alert_disconnect_msg">Connexion perduda</string> + <string name="pref_ui_category">Interfàcia d\'utilizaire</string> + <string name="pref_fullscreen_title">Ecran complet</string> + <string name="pref_update_title">Verificar las mesas a jorn</string> + <string name="pref_conn_persist_title">Connexions persistentas</string> + <string name="pref_keymode_title">Acorchis de navigacion</string> + <string name="list_keymode_none">Desactivar</string> + <string name="hostpref_nickname_title">Escais</string> + <string name="hostpref_encoding_title">Encodatge</string> + <string name="hostpref_connection_category">Paramètre de connexion</string> + <string name="hostpref_username_title">Nom d\'utilizaire</string> + <string name="hostpref_hostname_title">Òste</string> + <string name="hostpref_port_title">Pòrt</string> + <string name="console_menu_close">Tampar</string> + <string name="console_menu_copy">Copiar</string> + <string name="console_menu_paste">Empegar</string> + <string name="button_yes">Òc</string> + <string name="button_no">Non</string> + <string name="portforward_remote">Distant</string> + <string name="portforward_dynamic">Dinamic (SOCKS)</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="format_username">nom d\'utilizaire</string> + <string name="format_hostname">nom d\'òste</string> + <string name="list_menu_sortname">Triar per nom</string> + <string name="list_menu_settings">Paramètres</string> + <string name="list_host_disconnect">Desconnectar</string> + <string name="list_rotation_default">Per defaut</string> + <string name="list_hwbutton_esc">Escap</string> + <string name="list_hwbutton_none">Pas cap</string> + <string name="list_delkey_backspace">Retorn enrèire</string> + <string name="list_delkey_del">Suprimir</string> + <string name="delete_neg">Anullar</string> + <string name="wizard_agree">Acceptar</string> + <string name="wizard_next">Seguent</string> + <string name="wizard_back">Precedent</string> + <string name="terminal_connecting">Connexion a %1$s:%2$d via %3$s</string> + <string name="no">Non</string> + <string name="with_confirmation">Aprèp confirmacion</string> + <string name="yes">Òc</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> + <string name="menu_colors_reset">Reïnicializar</string> + <string name="color_red">roge</string> + <string name="color_green">verd</string> + <string name="color_blue">blau</string> + <string name="color_gray">gris</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-pl/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Prosty, wszechstronny i otwarty klient SSH</string> + <string name="service_desc">Zarządza połączeniami SSH i załadowanymi kluczami publicznymi</string> + <string name="title_hosts_list">Hosty</string> + <string name="title_pubkey_list">Klucze publiczne</string> + <string name="title_port_forwards_list">Przekierowania portów</string> + <string name="title_host_editor">Edytuj host</string> + <string name="title_help">Pomoc</string> + <string name="title_colors">Kolory</string> + <string name="resolve_connect">Połącz</string> + <string name="resolve_entropy">Zbierz dane losowe</string> + <string name="menu_insert">Dodaj host</string> + <string name="menu_delete">Usuń host</string> + <string name="menu_preferences">Ustawienia</string> + <string name="help_intro">Proszę wybrać temat poniżej aby uzyskać więcej informacji na konkretny temat.</string> + <string name="help_about">O ConnectBot</string> + <string name="help_keyboard">Klawiatura</string> + <string name="pubkey_generate">Wygeneruj</string> + <string name="pubkey_import">Importuj</string> + <string name="pubkey_delete">Usuń klucz</string> + <string name="pubkey_gather_entropy">Zbieranie danych losowych</string> + <string name="pubkey_touch_prompt">Dotknij to pole, żeby losowo wygenerować dane. Ukończono: %1$d%%</string> + <string name="pubkey_touch_hint">Dla niepowtarzalności klucza, poruszaj losowo palcem po polu poniżej.</string> + <string name="pubkey_generating">"Generowanie pary kluczy…"</string> + <string name="pubkey_copy_private">Kopiuj klucz prywatny</string> + <string name="pubkey_copy_public">Kopiuj klucz publiczny</string> + <string name="pubkey_list_empty">Naciśnij \"Menu\", by utworzyć\nlub zaimportować parę kluczy.</string> + <string name="pubkey_unknown_format">Nieznany format</string> + <string name="pubkey_change_password">Zmień hasło</string> + <string name="pubkey_list_pick">Wybierz z karty SD</string> + <string name="pubkey_import_parse_problem">Niewłaściwy format importowanego klucza prywatnego</string> + <string name="pubkey_unlock">Odblokuj klucz</string> + <string name="pubkey_failed_add">Nieprawidłowe hasło dla klucza \'%1$s\'. Uwierzytelnienie nie powiodło się.</string> + <string name="pubkey_memory_load">Załaduj do pamięci</string> + <string name="pubkey_memory_unload">Usuń z pamięci</string> + <string name="pubkey_load_on_start">Załaduj klucz przy uruchamianiu</string> + <string name="pubkey_confirm_use">Potwierdź przed użyciem</string> + <string name="portforward_list_empty">Naciśnij \"Menu\",\nżeby stworzyć przekierowanie portu.</string> + <string name="portforward_edit">Edytuj przekierowanie portu</string> + <string name="portforward_delete">Usuń przekierowanie portu</string> + <string name="prompt_nickname">Skrócona nazwa:</string> + <string name="prompt_nickname_hint_pubkey">Klucz służbowy</string> + <string name="prompt_source_port">Port żródłowy</string> + <string name="prompt_destination">Host docelowy:</string> + <string name="prompt_old_password">Stare hasło:</string> + <string name="prompt_password">Hasło:</string> + <string name="prompt_again">(ponownie)</string> + <string name="prompt_type">Typ:</string> + <string name="prompt_password_can_be_blank">Uwaga: hasło może być puste</string> + <string name="prompt_bits">Bity:</string> + <string name="prompt_pubkey_password">Proszę podać hasło dla klucza \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Zezwolić zdalnemu hostowi na\nużycie klucza \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">OSTRZEŻENIE: DANE IDENTYFIKACYJNE ZDALNEGO HOSTU ZMIENIŁY SIĘ!</string> + <string name="host_verification_failure_warning">MOŻLIWE, ŻE STAŁEŚ SIĘ OFIARĄ ATAKU!\nPrawdopodobnie jest to atak: man-in-the-middle!\nJednak możliwe jest to, że zmienił się tylko klucz hostu.</string> + <string name="prompt_host_disconnected">Host rozłączył się.\nZamknąć sesję?</string> + <string name="prompt_continue_connecting">Czy na pewno chcesz\nkontynuować połączenie?</string> + <string name="host_authenticity_warning">Autentyczność hostu \'%1$s\' nie może zostać ustalona.</string> + <string name="host_fingerprint">Odcisk hostu %1$s to %2$s</string> + <string name="alert_passwords_do_not_match_msg">Hasła nie zgadzają się!</string> + <string name="alert_wrong_password_msg">Nieprawidłowe hasło!</string> + <string name="alert_key_corrupted_msg">Klucz prywatny wydaje się być uszkodzony!</string> + <string name="alert_sdcard_absent">Brak karty SD</string> + <string name="button_add">Dodaj</string> + <string name="button_change">Zmień</string> + <string name="button_generate">Generuj klucz</string> + <string name="button_resize">Zmień rozmiar</string> + <string name="alert_disconnect_msg">Połączenie utracone</string> + <string name="pref_emulation_category">Emulacja terminalu</string> + <string name="pref_emulation_title">Tryb emulacji</string> + <string name="pref_emulation_summary">Emulacja terminalu dla połączeń PTY</string> + <string name="pref_scrollback_title">Rozmiar buforu przewijania</string> + <string name="pref_scrollback_summary">Rozmiar pamięci dla buforu przewijania dla każdej konsoli</string> + <string name="pref_ui_category">Interfejs użytkownika</string> + <string name="pref_rotation_title">Sposób orientacji ekranu</string> + <string name="pref_rotation_summary">Sposób orientacji ekranu przy wysuniętej/wsuniętej klawiaturze</string> + <string name="pref_fullscreen_title">Pełny ekran</string> + <string name="pref_fullscreen_summary">Ukryj pasek statusu podczas pracy w konsoli</string> + <string name="pref_memkeys_title">Zapamiętaj klucze w pamięci</string> + <string name="pref_memkeys_summary">Trzymaj odblokowane klucze w pamięci dopóki usługa się nie rozłączy</string> + <string name="pref_update_title">Sprawdź aktualizacje</string> + <string name="pref_update_summary">Ustawienie częstości sprawdzania aktualizacji</string> + <string name="pref_conn_persist_title">Utrzymuj połącznia</string> + <string name="pref_conn_persist_summary">Wymuś utrzymanie połączeń, gdy aplikacja działa w tle</string> + <string name="pref_keymode_title">Skróty klawiaturowe</string> + <string name="pref_keymode_summary">Wybierz, którego Alt, Shift używać dla \'/\' oraz \'Tab\'</string> + <string name="pref_camera_title">Klawisz aparatu</string> + <string name="pref_camera_summary">Wybierz jaki skrót ma być wywoływany po wciśnięciu klawisza aparatu</string> + <string name="pref_keepalive_title">Wstrzymaj uśpienie ekranu</string> + <string name="pref_keepalive_summary">Wstrzymaj uśpienie ekranu kiedy konsola jest aktywna</string> + <string name="pref_wifilock_title">Wstrzymaj usypianie Wi-Fi</string> + <string name="pref_wifilock_summary">Wstrzymaj usypianie Wi-Fi gdy sesja jest aktywna</string> + <string name="pref_bumpyarrows_title">Podskakujące strzałki</string> + <string name="pref_bumpyarrows_summary">Wibruj kiedy emulowane są klawisze strzałek; użyteczne dla wolnych połączeń</string> + <string name="pref_bell_category">Brzęczyk terminalu</string> + <string name="pref_bell_title">Brzęczyk słyszalny</string> + <string name="pref_bell_volume_title">Głośność brzęczyka</string> + <string name="pref_bell_vibrate_title">Włącz wibracje</string> + <string name="pref_bell_notification_title">Powiadomienia w tle</string> + <string name="pref_bell_notification_summary">Uruchom powiadomienie podczas akcji w zminimalizowanej aplikacji.</string> + <string name="list_keymode_right">Używaj klawiszy z prawej strony</string> + <string name="list_keymode_left">Używaj klawiszy z lewej strony</string> + <string name="list_keymode_none">Wyłącz</string> + <string name="list_pubkeyids_none">Nie używaj kluczy</string> + <string name="list_pubkeyids_any">Użyj dowolnego odblokowanego klucza</string> + <string name="hostpref_nickname_title">Nazwa skrócona</string> + <string name="hostpref_color_title">Kolor kategorii</string> + <string name="hostpref_fontsize_title">Rozmiar czcionki</string> + <string name="hostpref_pubkeyid_title">Używaj kluczy publicznych do uwierzytelnienia</string> + <string name="hostpref_authagent_title">Używaj agenta SSH dla uwierzytelniania</string> + <string name="hostpref_postlogin_title">Wykonaj po zalogowaniu</string> + <string name="hostpref_postlogin_summary">Komendy do wykonania po stronie serwera po zalogowaniu</string> + <string name="hostpref_compression_title">Kompresja</string> + <string name="hostpref_compression_summary">Może pomóc przy wolniejszych łączach</string> + <string name="hostpref_wantsession_title">Uruchom sesję powłoki</string> + <string name="hostpref_wantsession_summary">Wyłącz jeśli chcesz tylko przekierować porty</string> + <string name="hostpref_stayconnected_title">Pozostań połączony</string> + <string name="hostpref_stayconnected_summary">Spróbuj połączyć się z hostem ponownie po przerwaniu połączenia</string> + <string name="hostpref_delkey_title">Klawisz DEL</string> + <string name="hostpref_delkey_summary">Kod klawisza wysyłany przy wciśnięciu DEL</string> + <string name="hostpref_encoding_title">Kodowanie</string> + <string name="hostpref_encoding_summary">Kodowanie znaków dla hostu</string> + <string name="hostpref_connection_category">Ustawienia połączenia</string> + <string name="hostpref_username_title">Nazwa użytkownika</string> + <string name="hostpref_hostname_title">Host</string> + <string name="hostpref_port_title">Port</string> + <string name="bind_never">Nigdy nie połączono</string> + <string name="bind_minutes">%1$s minut temu</string> + <string name="bind_hours">%1$s godzin temu</string> + <string name="bind_days">%1$s dni temu</string> + <string name="console_copy_done">Skopiowano %1$d bajtów do schowka</string> + <string name="console_copy_start">Dotknij i przeciągnij\nlub użyj trackball\'a\naby zaznaczyć obszar do skopiowania</string> + <string name="console_menu_close">Zamknij</string> + <string name="console_menu_copy">Kopiuj</string> + <string name="console_menu_paste">Wklej</string> + <string name="console_menu_portforwards">Przekierowania portów</string> + <string name="console_menu_resize">Wymuś rozmiar</string> + <string name="console_menu_urlscan">Szukaj URLi</string> + <string name="button_yes">Tak</string> + <string name="button_no">Nie</string> + <string name="portforward_local">Lokalny</string> + <string name="portforward_remote">Zdalny</string> + <string name="portforward_dynamic">Dynamiczny (SOCKS)</string> + <string name="portforward_pos">Utwórz przekierowanie portu</string> + <string name="portforward_done">Pomyślnie utworzono przekierowanie portu</string> + <string name="portforward_problem">Wystąpił problem podczas tworzenia przekierowania, być może użyłeś portu niższego niż 1024 lub port jest już używany?</string> + <string name="portforward_menu_add">Dodaj przekierowanie portu</string> + <string name="hint_userhost">użytkownik\@host</string> + <string name="list_format_error">Proszę użyć formatu %1$s</string> + <string name="format_username">Nazwa użytkownika</string> + <string name="format_hostname">nazwa_hostu</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Zarządzaj kluczami publicznymi</string> + <string name="list_menu_sortcolor">Sortuj według koloru</string> + <string name="list_menu_sortname">Sortuj według nazwy</string> + <string name="list_menu_settings">Ustawienia</string> + <string name="list_host_disconnect">Rozłącz</string> + <string name="list_host_edit">Edytuj host</string> + <string name="list_host_portforwards">Edytuj przekierowania portów</string> + <string name="list_host_delete">Usuń host</string> + <string name="list_host_empty">Użyj pola szybkiego połączenia\nponiżej, żeby połączyć się z hostem.</string> + <string name="list_rotation_default">Domyślne</string> + <string name="list_rotation_land">Wymuś orientację poziomą</string> + <string name="list_rotation_port">Wymuś orientację pionową</string> + <string name="list_rotation_auto">Automatycznie</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A następnie Spacja</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Brak akcji</string> + <string name="list_delkey_backspace">Backspace</string> + <string name="list_delkey_del">Usuń</string> + <string name="delete_message">Jesteś pewien, że chcesz usunąć \'%1$s\'?</string> + <string name="delete_pos">Tak, usuń</string> + <string name="delete_neg">Anuluj</string> + <string name="wizard_agree">Akceptuj</string> + <string name="wizard_next">Dalej</string> + <string name="wizard_back">Wróć</string> + <string name="terminal_no_hosts_connected">Żaden host nie jest obecnie połączony</string> + <string name="terminal_connecting">Łączenie z hostem %1$s:%2$d przez %3$s</string> + <string name="terminal_sucess">Host \'%1$s \' zweryfikowany kluczem: %2$s</string> + <string name="terminal_failed">Weryfikacja klucza dla hostu nie powiodła się.</string> + <string name="terminal_using_s2c_algorithm">Algorytm serwer-klient: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algorytm klient-serwer: %1$s %2$s</string> + <string name="terminal_using_algorithm">Użyty algorytm: %1$s %2$s</string> + <string name="terminal_auth">Próba uwierzytelnienia</string> + <string name="terminal_auth_pass">Próba uwierzytelnienia za pomocą hasła</string> + <string name="terminal_auth_pass_fail">Uwierzytelnienie hasłem nie powiodło się</string> + <string name="terminal_auth_pubkey_any">Próba uwierzytelnienia za pomocą dowolnego zapamiętanego klucza publicznego</string> + <string name="terminal_auth_pubkey_invalid">Wybrany klucz publiczny jest nieprawidłowy, spróbuj wybrać inny w ustawieniach hostu</string> + <string name="terminal_auth_pubkey_specific">"Próba uwierzytelnienia za pomocą wybranego klucza publicznego"</string> + <string name="terminal_auth_pubkey_fail">Uwierzytelnienie metodą klucza publicznego z kluczem \'%1$s\' nie powiodło się</string> + <string name="terminal_auth_ki">Próba uwierzytelnienia za pomocą klawiatury</string> + <string name="terminal_auth_ki_fail">Uwierzytelnienie za pomocą klawiatury nie powiodło się</string> + <string name="terminal_auth_fail">[Twój host nie obsługuje uwierzytelnienia za pomocą klawiatury lub hasła]</string> + <string name="terminal_no_session">Sesja nie zostanie rozpoczęta z powodu ustawień hostu</string> + <string name="terminal_enable_portfoward">Włącz przekierowanie portu: %1$s</string> + <string name="local_shell_unavailable">Niepowodzenie! Lokalna powłoka nie jest obsługiwana na tym telefonie.</string> + <string name="notification_text">%1$s wymaga reakcji</string> + <string name="no">Nie</string> + <string name="with_confirmation">Z potwierdzeniem</string> + <string name="yes">Tak</string> + <string name="exceptions_submit_message">ConnectBot miał prawdopodobnie problem podczas ostatniego uruchomienia. Wysłać raport o błędzie?</string> + <string name="menu_colors_reset">Przywróć</string> + <string name="app_is_running">ConnectBot jest uruchomiony</string> + <string name="color_red">czerwony</string> + <string name="color_green">zielony</string> + <string name="color_blue">niebieski</string> + <string name="color_gray">szary</string> + <string name="colors_fg">FG:</string> + <string name="color_bg">BG:</string> + <string name="image_description_connected">Połączono</string> + <string name="image_description_key_is_locked">Klucz zablokowany</string> + <string name="image_description_toggle_control_character">Przełącz znak kontrolny</string> + <string name="image_description_send_escape_character">Wyślij znak ESC</string> + <string name="image_description_show_keyboard">Pokarz klawiaturę</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-pt-rBR/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,216 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Cliente SSH simples e poderoso de código aberto</string> + <string name="service_desc">Mantém conexões SSH e de Chaves Públicas</string> + <string name="title_hosts_list">Hosts</string> + <string name="title_pubkey_list">Chaves Públicas</string> + <string name="title_port_forwards_list">Redirecionamento de Portas</string> + <string name="title_host_editor">Edição de Host</string> + <string name="title_help">Ajuda</string> + <string name="title_colors">Cores</string> + <string name="resolve_connect">Conectar</string> + <string name="resolve_entropy">Sensibilidade</string> + <string name="menu_insert">Adicionar Host</string> + <string name="menu_delete">Apagar host</string> + <string name="menu_preferences">Preferências</string> + <string name="help_intro">Escolha um dos tópicos abaixo para maiores informações</string> + <string name="help_about">Sobre o ConnectBot</string> + <string name="help_keyboard">Teclado</string> + <string name="pubkey_generate">Gerar</string> + <string name="pubkey_import">Importar</string> + <string name="pubkey_delete">Apagar chave</string> + <string name="pubkey_gather_entropy">Ajustando sensibilidade</string> + <string name="pubkey_touch_prompt">Toque na caixa para testar sensibilidade: %1$d%% pronto</string> + <string name="pubkey_touch_hint">Para garantir aleatoriedade durante a geração da chave, mova seu dedo aleatoriamente na caixa abaixo.</string> + <string name="pubkey_generating">""Gerando par de chaves…"</string> + <string name="pubkey_copy_private">Copiar chave privada</string> + <string name="pubkey_copy_public">Copiar chave pública</string> + <string name="pubkey_list_empty">Pressione Menu para criar ou importar pares de chaves.</string> + <string name="pubkey_unknown_format">Formato desconhecido</string> + <string name="pubkey_change_password">Mudar senha</string> + <string name="pubkey_list_pick">Escolher do /sdcard</string> + <string name="pubkey_import_parse_problem">Erro na leitura da chave privada importada</string> + <string name="pubkey_unlock">Abrir chave</string> + <string name="pubkey_failed_add">Senha inválida para Chave \'%1$s\'.Falha na autenticação.</string> + <string name="pubkey_memory_load">Carregar na memória</string> + <string name="pubkey_memory_unload">Descarregar da memória</string> + <string name="pubkey_load_on_start">Carregar chave ao iniciar</string> + <string name="pubkey_confirm_use">Confirmar antes de usar</string> + <string name="portforward_list_empty">Pressione Menu para criar encaminhamentos de porta.</string> + <string name="portforward_edit">Editar encaminhamento de porta</string> + <string name="portforward_delete">Apagar encaminhamento de porta</string> + <string name="prompt_nickname">Apelido:</string> + <string name="prompt_nickname_hint_pubkey">Minha chave de trabalho</string> + <string name="prompt_source_port">Porta de origem:</string> + <string name="prompt_destination">Destino:</string> + <string name="prompt_old_password">Senha antiga:</string> + <string name="prompt_password">Senha:</string> + <string name="prompt_again">(novamente)</string> + <string name="prompt_type">Tipo:</string> + <string name="prompt_password_can_be_blank">Nota: a senha pode ser em branco</string> + <string name="prompt_bits">Bits:</string> + <string name="prompt_pubkey_password">Senha para chave %1$s</string> + <string name="prompt_allow_agent_to_use_key">Permitir que a máquina remota use a chave %1$s?</string> + <string name="host_verification_failure_warning_header">ATENÇÃO: A IDENTIFICAÇÃO DO HOST REMOTO FOI ALTERADA!</string> + <string name="host_verification_failure_warning">É POSSÍVEL QUE ALGUÉM ESTEJA QUERENDO TE ENGANAR!\nAlguém pode estar tentando um ataque do tipo man-in-the-middle!\nTambém é possível que a chave do host remoto tenha mesmo sido modificada.</string> + <string name="prompt_host_disconnected">Host desconectado.\nFechar sessão?</string> + <string name="prompt_continue_connecting">Você tem certeza que\ndeseja se conectar?</string> + <string name="host_authenticity_warning">A autenticidade do Host \'%1$s\' não pode ser estabelecida</string> + <string name="host_fingerprint">O host %1$s tem a impressão digital %2$s</string> + <string name="alert_passwords_do_not_match_msg">As senhas são diferentes!</string> + <string name="alert_wrong_password_msg">Senha incorreta!</string> + <string name="alert_key_corrupted_msg">A chave privada parece estar corrompida!</string> + <string name="alert_sdcard_absent">O cartão SD não está inserido!</string> + <string name="button_add">Adicionar</string> + <string name="button_change">Alterar</string> + <string name="button_generate">Gerar chave</string> + <string name="button_resize">Redimensionar</string> + <string name="alert_disconnect_msg">Conexão perdida</string> + <string name="pref_emulation_category">Emulação de Terminal</string> + <string name="pref_emulation_title">Modo de emulação</string> + <string name="pref_emulation_summary">Modo de emulação do terminal com conexões PTY</string> + <string name="pref_scrollback_title">Tamanho do buffer da tela</string> + <string name="pref_scrollback_summary">Tamanho do buffer de memória a manter para cada terminal</string> + <string name="pref_ui_category">Interface do usuário</string> + <string name="pref_rotation_title">Rotação da tela</string> + <string name="pref_rotation_summary">Como alterar a rotação da tela quando se conecta/desconecta um teclado</string> + <string name="pref_fullscreen_title">Tela cheia</string> + <string name="pref_fullscreen_summary">Ocultar a barra de estatus no modo terminal</string> + <string name="pref_memkeys_title">Guardar as chaves em memória</string> + <string name="pref_memkeys_summary">Manter chaves desbloqueadas na memória até que o serviço seja terminado</string> + <string name="pref_update_title">Procurar por atualizações</string> + <string name="pref_update_summary">Configurar frequencia para checar atualizações do ConnectBot</string> + <string name="pref_conn_persist_title">Conexões persistentes</string> + <string name="pref_conn_persist_summary">Forçar as conexões para que continuem conectadas mesmo em segundo plano</string> + <string name="pref_keymode_title">Teclas de atalho</string> + <string name="pref_keymode_summary">Selecione para usar Alt para \'/\' e Shift para Tab</string> + <string name="pref_camera_title">Atalho para a câmera</string> + <string name="pref_camera_summary">Selecione o que fazer quando o botão da câmera for pressionado</string> + <string name="pref_keepalive_title">Manter tela ligada</string> + <string name="pref_keepalive_summary">Evitar desligamento de tela quando conectado em um terminal</string> + <string name="pref_wifilock_title">Manter a rede Wi-Fi ativo</string> + <string name="pref_wifilock_summary">Evitar que a rede Wi-Fi seja desligada quando alguma sesão está ativa</string> + <string name="pref_bumpyarrows_title">Feedback de rolagem</string> + <string name="pref_bumpyarrows_summary">Vibrar quando pressionar o botão principal (trackball)</string> + <string name="pref_bell_category">Alerta do terminal</string> + <string name="pref_bell_title">Alerta audível</string> + <string name="pref_bell_volume_title">Volume dos alerta</string> + <string name="pref_bell_vibrate_title">Vibrar ao alertar</string> + <string name="pref_bell_notification_title">Enviar notificações visuais quando em segundo plano</string> + <string name="pref_bell_notification_summary">Enviar notificações sonoras quando em segundo plano</string> + <string name="list_keymode_right">Usar atalhos especiais da direita</string> + <string name="list_keymode_left">Usar atalhos especiais da esquerda</string> + <string name="list_keymode_none">Desabilitar</string> + <string name="list_pubkeyids_none">Não usar chaves</string> + <string name="list_pubkeyids_any">Usar qualquer chave pública</string> + <string name="hostpref_nickname_title">Apelido</string> + <string name="hostpref_color_title">Categoria de cor</string> + <string name="hostpref_fontsize_title">Tamanho da fonte (pontos)</string> + <string name="hostpref_pubkeyid_title">Usar autenticação por chave púbilca</string> + <string name="hostpref_authagent_title">Usar agente de autenticação SSH</string> + <string name="hostpref_postlogin_title">Automação pós-login</string> + <string name="hostpref_postlogin_summary">Comandos a serem executados no servidor remoto na autenticação</string> + <string name="hostpref_compression_title">Compressão</string> + <string name="hostpref_compression_summary">Útil em conexões lentas (2G)</string> + <string name="hostpref_wantsession_title">Iniciar sessão de terminal na conexão</string> + <string name="hostpref_wantsession_summary">Desabilite esta preferência para usar apenas encaminhamento de portas</string> + <string name="hostpref_stayconnected_title">Manter conectado</string> + <string name="hostpref_stayconnected_summary">Tentar reconectar ao host caso a conexão seja perdida</string> + <string name="hostpref_delkey_title">Tecla DEL</string> + <string name="hostpref_delkey_summary">Código a ser enviado quando a tecla DEL for pressionada</string> + <string name="hostpref_encoding_title">Codificação</string> + <string name="hostpref_encoding_summary">Codificação de caracteres para o host</string> + <string name="hostpref_connection_category">Configurações de conexão</string> + <string name="hostpref_username_title">Usuário</string> + <string name="hostpref_hostname_title">Anfitrião (host)</string> + <string name="hostpref_port_title">Porta</string> + <string name="bind_never">Nunca usado</string> + <string name="bind_minutes">%1$s minutos atrás</string> + <string name="bind_hours">%1$s horas atrás</string> + <string name="bind_days">%1$s dias atrás</string> + <string name="console_copy_done">%1$d bytes copiados para a área de tranferência</string> + <string name="console_copy_start">Toque e arraste\nou use o trackball\npara selecionar uma área para copiar</string> + <string name="console_menu_close">Fechar</string> + <string name="console_menu_copy">Copiar</string> + <string name="console_menu_paste">Colar</string> + <string name="console_menu_portforwards">Encaminhamento de portas</string> + <string name="console_menu_resize">Forçar tamanho</string> + <string name="console_menu_urlscan">Localizar URLs</string> + <string name="button_yes">Sim</string> + <string name="button_no">Não</string> + <string name="portforward_local">Porta local</string> + <string name="portforward_remote">Remoto</string> + <string name="portforward_dynamic">Dinâmico (SOCKS)</string> + <string name="portforward_pos">Criar encaminhamento de porta</string> + <string name="portforward_done">Encaminhamento de porta criado com sucesso</string> + <string name="portforward_problem">Problema na criação do redirecionamento de portas, talvez você esteja usando portas menores que 1024 ou a porta já esteja sendo usada.</string> + <string name="portforward_menu_add">Adicionar encaminhamento de porta</string> + <string name="hint_userhost">usuario\@nome_do_host</string> + <string name="list_format_error">Use o formato %1$s</string> + <string name="format_username">usuário</string> + <string name="format_hostname">nome do host</string> + <string name="format_port">porta</string> + <string name="list_menu_pubkeys">Gerenciar chaves públicas</string> + <string name="list_menu_sortcolor">Ordenar por cor</string> + <string name="list_menu_sortname">Ordenar por nome</string> + <string name="list_menu_settings">Configurações</string> + <string name="list_host_disconnect">Desconectar</string> + <string name="list_host_edit">Editar host</string> + <string name="list_host_portforwards">Editar encaminhamento de porta</string> + <string name="list_host_delete">Apagar host</string> + <string name="list_host_empty">Use a conexão rápida abaixo\npara conectar a um host.</string> + <string name="list_rotation_default">Padrão</string> + <string name="list_rotation_land">Forçar modo paisagem</string> + <string name="list_rotation_port">Forçar modo retrato</string> + <string name="list_rotation_auto">Automático</string> + <string name="list_hwbutton_ctrlaspace">Ctrl + A + Espaço</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Nada</string> + <string name="list_delkey_backspace">Tecla Backspace</string> + <string name="list_delkey_del">Apagar</string> + <string name="delete_message">Certeza que quer deletar \'%1$s\' ?</string> + <string name="delete_pos">Sim, apagar</string> + <string name="delete_neg">Cancelar</string> + <string name="wizard_agree">Aceito</string> + <string name="wizard_next">Próximo</string> + <string name="wizard_back">Voltar</string> + <string name="terminal_no_hosts_connected">Sem host conectado atualmente</string> + <string name="terminal_connecting">Conectando no %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">"Anfitrião comprovado \'%1$s\' chave: %2$s"</string> + <string name="terminal_failed">Falha na verificação da chave do host</string> + <string name="terminal_using_s2c_algorithm">Algoritmo do servidor para o cliente: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algoritmo do cliente para o servidor: %1$s %2$s</string> + <string name="terminal_using_algorithm">Usando o algoritmo: %1$s %2$s</string> + <string name="terminal_auth">Tentando autenticação</string> + <string name="terminal_auth_pass">Tentativa de autenticação de \'senha\' em andamento</string> + <string name="terminal_auth_pass_fail">Método de autenticação por \'senha\' falhou</string> + <string name="terminal_auth_pubkey_any">Tentando autenticação \'chave pública\' com qualquer chave pública na memória</string> + <string name="terminal_auth_pubkey_invalid">A chave pública selecionada é inválida, tente selecionar outra no editor de hosts</string> + <string name="terminal_auth_pubkey_specific">Tentando autenticação \'chave pública\' com uma chave pública específica</string> + <string name="terminal_auth_pubkey_fail">Metodo de autenticação \'publickey\' com a chave \'%1$s\' falhou</string> + <string name="terminal_auth_ki">Tentando autenticação \'teclado-interativo\'</string> + <string name="terminal_auth_ki_fail">Metodo de autenticação \'interativa por teclado\' falhou</string> + <string name="terminal_auth_fail">[Seu host não suporta autenticação por \'senha\' ou \'interativa por teclado\'.</string> + <string name="terminal_no_session">A sessão não será iniciada devido à configurações do host.</string> + <string name="terminal_enable_portfoward">Habilitar encaminhamento de porta: %1$s</string> + <string name="local_shell_unavailable">Erro! O terminal local não está disponível neste telefone.</string> + <string name="notification_text">%1$s deseja sua atenção.</string> + <string name="no">Não</string> + <string name="with_confirmation">Com confirmação</string> + <string name="yes">Sim</string> + <string name="exceptions_submit_message">Aparentemente o ConnectBot teve um problema na última execução. Deseja enviar relatório de erro aos desenvolvedores do aplicativo?</string> + <string name="menu_colors_reset">Reiniciar</string> + <string name="app_is_running">ConnectBot está executando</string> + <string name="color_red">vermelho</string> + <string name="color_green">verde</string> + <string name="color_blue">azul</string> + <string name="color_gray">cinza</string> + <string name="colors_fg">PP:</string> + <string name="color_bg">SP:</string> + <string name="image_description_connected">Conectado.</string> + <string name="image_description_key_is_locked">A chave está bloqueada.</string> + <string name="image_description_send_escape_character">Enviar caractere de escape.</string> + <string name="image_description_show_keyboard">Exibir teclado</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-pt/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Simples e poderoso cliente SSH open-source</string> + <string name="service_desc">Manter ligações SSH e chaves públicas carregadas</string> + <string name="title_hosts_list">Máquinas</string> + <string name="title_pubkey_list">Chaves Públicas</string> + <string name="title_port_forwards_list">Redireciomento de portas</string> + <string name="title_host_editor">Editar a Máquina</string> + <string name="title_help">Ajuda</string> + <string name="title_colors">Cores</string> + <string name="resolve_connect">Ligar</string> + <string name="resolve_entropy">Gerar Entropia</string> + <string name="menu_insert">Adicionar uma Máquina</string> + <string name="menu_delete">Eliminar anfitrião</string> + <string name="menu_preferences">Preferências</string> + <string name="help_intro">Selecione um tópico para mais informações sobre o assunto.</string> + <string name="help_about">Sobre ConnectBot</string> + <string name="help_keyboard">Teclado</string> + <string name="pubkey_generate">Gerar</string> + <string name="pubkey_import">Importar</string> + <string name="pubkey_delete">Apagar a chave</string> + <string name="pubkey_gather_entropy">Recolhendo entropia</string> + <string name="pubkey_touch_prompt">Toque nesta caixa para gerar aleariedade: %1$d%% completo</string> + <string name="pubkey_touch_hint">Para assegurar aleatoriedade durante a geração da chave, mova o dedo aleatoriamente sobre a caixa a baixo.</string> + <string name="pubkey_generating">A gerar par de chaves</string> + <string name="pubkey_copy_private">Copiar chave privada</string> + <string name="pubkey_copy_public">Copiar chave pública</string> + <string name="pubkey_list_empty">Carregue em Menu para criar\nou importar as chaves.</string> + <string name="pubkey_unknown_format">Formato desconhecido</string> + <string name="pubkey_change_password">Alterar password</string> + <string name="pubkey_list_pick">Escolher de /sdcard</string> + <string name="pubkey_import_parse_problem">Problema de análise com a chave privada importada</string> + <string name="pubkey_unlock">Desbloquear chave</string> + <string name="pubkey_failed_add">Password inválida para a chave \'%1$s\'. Erro na autenticação.</string> + <string name="pubkey_memory_load">Carregar para a memória</string> + <string name="pubkey_memory_unload">retirar da memória</string> + <string name="pubkey_load_on_start">carregar chave no Inicio</string> + <string name="pubkey_confirm_use">Confirmar antes de usar</string> + <string name="portforward_list_empty">Carregue Menu para criar\nport forward</string> + <string name="portforward_edit">Editar port forward</string> + <string name="portforward_delete">Apagar port forward</string> + <string name="prompt_nickname">Alcunha:</string> + <string name="prompt_nickname_hint_pubkey">A minha chave de trabalho</string> + <string name="prompt_source_port">Porta de origem:</string> + <string name="prompt_destination">Destino:</string> + <string name="prompt_old_password">Palavra-passe Antiga:</string> + <string name="prompt_password">Palavra-passe:</string> + <string name="prompt_again">(novamente)</string> + <string name="prompt_type">Tipo:</string> + <string name="prompt_password_can_be_blank">Nota: password pode ser em branco</string> + <string name="prompt_bits">bits:</string> + <string name="prompt_pubkey_password">Password para a chave \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Permitir ao anfitrião remoto\nusar a chave \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">AVISO: a identificação do anfitrião remoto mudou!</string> + <string name="host_verification_failure_warning">É POSSÍVEL QUE ALGUÉM ESTEJA A FAZER ALGO ERRADO!\n Alguém pode estar espiando ( ataque man-in-the-middle)!\nTambém e possível que a chave do hospede tenha sido alterada</string> + <string name="prompt_host_disconnected">Hospede desconectou-se.\nFechar sessão?</string> + <string name="prompt_continue_connecting">Tem a certeza que quer\ncontinuar a connectar?</string> + <string name="host_authenticity_warning">A autenticidade do anfitrião \'%1$s\' não pode ser verificada.</string> + <string name="host_fingerprint">Hospede %1$s id da chave é %2$s</string> + <string name="alert_passwords_do_not_match_msg">As palavras passe não coincidem!</string> + <string name="alert_wrong_password_msg">Palavra passe errada!</string> + <string name="alert_key_corrupted_msg">Chave privada parece estar corrupta.</string> + <string name="alert_sdcard_absent">Cartão SD não parece estar inserido!</string> + <string name="button_add">Adicionar</string> + <string name="button_change">Alterar</string> + <string name="button_generate">Gerar Chave</string> + <string name="button_resize">Redimensionar</string> + <string name="alert_disconnect_msg">Ligação Perdida</string> + <string name="pref_emulation_category">Terminal de emulação</string> + <string name="pref_emulation_title">Modo de emulação</string> + <string name="pref_emulation_summary">Terminal de emulação para usar conecções PTY</string> + <string name="pref_scrollback_title">Tamanho de Scrollback</string> + <string name="pref_scrollback_summary">Tamanho do buffer de scrollback em memória para cada consola</string> + <string name="pref_ui_category">Interface de utilizador</string> + <string name="pref_rotation_title">Modo de rotação</string> + <string name="pref_rotation_summary">Como alterar a rotação quando o teclado é aberto/fechado</string> + <string name="pref_fullscreen_title">Ecrã completo</string> + <string name="pref_fullscreen_summary">Esconder a barra de notificação quando estiver na consola</string> + <string name="pref_memkeys_title">Lembrar chaves em memoria</string> + <string name="pref_memkeys_summary">Manter chaves desbloqueadas em memória até ao serviço de fundo terminar</string> + <string name="pref_update_title">Verificar actualizações</string> + <string name="pref_update_summary">Definir a frequência máxima para verificar actualizações do ConnectBot</string> + <string name="pref_conn_persist_title">Persistir ligações</string> + <string name="pref_conn_persist_summary">Forçar ligações a ficarem ligadas quando em segundo plano</string> + <string name="pref_keymode_title">Atalhos de directoria</string> + <string name="pref_keymode_summary">Escolher como usar Alt para \'/\' e Shift para Tab</string> + <string name="pref_camera_title">Atalho para a camera</string> + <string name="pref_camera_summary">Escolha o atalho a activar quando o botão da camara é pressionado</string> + <string name="pref_keepalive_title">Mantar ecrã activo</string> + <string name="pref_keepalive_summary">Previne que o ecrã seja desligado quando se esta a utilizar a consola</string> + <string name="pref_wifilock_title">Manter Wi-Fi activo</string> + <string name="pref_wifilock_summary">Evitar que o Wi-Fi desligue quando uma sessão está activa</string> + <string name="pref_bumpyarrows_title">Cursores com vibração</string> + <string name="pref_bumpyarrows_summary">Vibrar quando enviar teclas de cursor com a trackball; útil para ligações com atraso</string> + <string name="pref_bell_category">Aviso sonoro do terminal</string> + <string name="pref_bell_title">Aviso sonoro audível</string> + <string name="pref_bell_volume_title">Volume do aviso sonoro</string> + <string name="pref_bell_vibrate_title">Vibrar em aviso sonoro</string> + <string name="pref_bell_notification_title">Notificações em segundo plano</string> + <string name="pref_bell_notification_summary">Enviar notificação quando um terminal a correr em segundo plano enviar um aviso sonoro.</string> + <string name="list_keymode_right">Usar teclas do lado direito</string> + <string name="list_keymode_left">Usar teclas do lado esquerdo</string> + <string name="list_keymode_none">Desactivar</string> + <string name="list_pubkeyids_none">Não usar teclas</string> + <string name="list_pubkeyids_any">Usar qualquer tecla não bloqueada</string> + <string name="hostpref_nickname_title">Alcunha</string> + <string name="hostpref_color_title">Categoria de cor</string> + <string name="hostpref_fontsize_title">Tamanho da fonte (pt)</string> + <string name="hostpref_pubkeyid_title">Utilizar autenticação de chave publica (pubkey)</string> + <string name="hostpref_authagent_title">Usar agente de autenticação SSH</string> + <string name="hostpref_postlogin_title">Automação pós-login</string> + <string name="hostpref_postlogin_summary">Comandos a correr no servidor remoto após autenticar</string> + <string name="hostpref_compression_title">Compressão</string> + <string name="hostpref_compression_summary">Isto pode ajudar em redes mais lentas</string> + <string name="hostpref_wantsession_title">Iniciar sessão de shell</string> + <string name="hostpref_wantsession_summary">Desactivar esta preferência para usar apenas redirecionamento de portas</string> + <string name="hostpref_stayconnected_title">Permanecer ligado</string> + <string name="hostpref_stayconnected_summary">Tentar ligar de novo ao anfitrião se desligar</string> + <string name="hostpref_delkey_title">Tecla DEL</string> + <string name="hostpref_delkey_summary">O código de tecla a enviar quando a tecla DEL é pressionada</string> + <string name="hostpref_encoding_title">Codificação</string> + <string name="hostpref_encoding_summary">Codificação de caractéres para o anfitrião</string> + <string name="hostpref_connection_category">Configuração da Ligação</string> + <string name="hostpref_username_title">Nome do Utilizador</string> + <string name="hostpref_hostname_title">Anfitrião</string> + <string name="hostpref_port_title">Porto</string> + <string name="bind_never">Nunca ligado</string> + <string name="bind_minutes">%1$s minutos atrás</string> + <string name="bind_hours">%1$s horas atrás</string> + <string name="bind_days">%1$s dias atrás</string> + <string name="console_copy_done">Copiados %1$d bytes para a área de transferência</string> + <string name="console_copy_start">Toque e arraste\nou use as teclas direcionais\npara selecionar a área a copiar</string> + <string name="console_menu_close">Fechar</string> + <string name="console_menu_copy">Copiar</string> + <string name="console_menu_paste">Colar</string> + <string name="console_menu_portforwards">Redirecionamento de portas</string> + <string name="console_menu_resize">Forçar Tamanho</string> + <string name="console_menu_urlscan">Detecção de URL</string> + <string name="button_yes">Sim</string> + <string name="button_no">Não</string> + <string name="portforward_local">Local</string> + <string name="portforward_remote">Remoto</string> + <string name="portforward_dynamic">Dinamico (SOCKS)</string> + <string name="portforward_pos">Criar redirecionamento de portas</string> + <string name="portforward_done">Redirecionamento de porta criado com sucesso</string> + <string name="portforward_problem">Problema ao criar redirecionamento de porta, talvez esteja a usar portas abaixo de 1024 ou a porta já esteja em uso?</string> + <string name="portforward_menu_add">Adicionar redirecionamento de porta</string> + <string name="hint_userhost">utilizador\@servidor</string> + <string name="list_format_error">Use o formato %1$s</string> + <string name="format_username">nome do utilizador</string> + <string name="format_hostname">endereço</string> + <string name="format_port">porto</string> + <string name="list_menu_pubkeys">Gerir Chaves Públicas</string> + <string name="list_menu_sortcolor">Ordenar por cor</string> + <string name="list_menu_sortname">Ordenar por nome</string> + <string name="list_menu_settings">Definições</string> + <string name="list_host_disconnect">Desconectar</string> + <string name="list_host_edit">Editar anfitrião</string> + <string name="list_host_portforwards">Editar redirecionamento de portas</string> + <string name="list_host_delete">Eliminar anfitrião</string> + <string name="list_host_empty">Usar a caixa de ligação rápida\nabaixo para ligar a um anfitrião.</string> + <string name="list_rotation_default">Padrão</string> + <string name="list_rotation_land">Forçar panoramico</string> + <string name="list_rotation_port">Forçar retrato</string> + <string name="list_rotation_auto">Automática</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A seguido de Espaço</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Nenhum</string> + <string name="list_delkey_backspace">Retrocesso</string> + <string name="list_delkey_del">Apagar</string> + <string name="delete_message">Tem a certeza que deseja eliminar \'%1$s\'?</string> + <string name="delete_pos">Sim, apagar</string> + <string name="delete_neg">Cancelar</string> + <string name="wizard_agree">Aceitar</string> + <string name="wizard_next">Seguinte</string> + <string name="wizard_back">Retroceder</string> + <string name="terminal_no_hosts_connected">Nenhum anfitrião ligado actualmente</string> + <string name="terminal_connecting">A ligar a %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">Verificado anfitrião \'%1$s\' chave: %2$s</string> + <string name="terminal_failed">Verificação da chave do anfitrião falhou.</string> + <string name="terminal_using_s2c_algorithm">Algoritmo servidor-cliente: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Algoritmo cliente-servidor: %1$s %2$s</string> + <string name="terminal_using_algorithm">A usar algoritmo %1$s %2$s</string> + <string name="terminal_auth">A tentar autenticação</string> + <string name="terminal_auth_pass">A tentar autenticação por \'password\'</string> + <string name="terminal_auth_pass_fail">Autenticação pelo método \'password\' falhou</string> + <string name="terminal_auth_pubkey_any">A tentar autenticação de chave pública (pubkey) com todas as chaves públicas em memória</string> + <string name="terminal_auth_pubkey_invalid">A chave pública escolhida é inválida, tente escolher outra chave no editor de anfitriões</string> + <string name="terminal_auth_pubkey_specific">A tentar autenticação de chave pública (publickey) com uma chave pública específica</string> + <string name="terminal_auth_pubkey_fail">Autenticação pelo método de chave pública (publickey) com a chave \'%1$s\' falhou</string> + <string name="terminal_auth_ki">A tentar autenticação pelo método \'teclado-interactivo\'</string> + <string name="terminal_auth_ki_fail">Autenticação pelo método \'teclado-interactivo\' falhou</string> + <string name="terminal_auth_fail">[O seu anfitrião não suporta autenticação por \'password\' ou \'teclado-interactivo\'.]</string> + <string name="terminal_no_session">A sessão não será iniciada devido a preferência do anfitrião.</string> + <string name="terminal_enable_portfoward">Permitir redirecionamento de porta: %1$s</string> + <string name="local_shell_unavailable">Falha! Shell local não está disponível neste telemóvel.</string> + <string name="notification_text">%1$s requer a sua atenção.</string> + <string name="no">Não</string> + <string name="with_confirmation">com confirmação</string> + <string name="yes">Sim</string> + <string name="exceptions_submit_message">Aparentemente o ConnectBot teve um problema na ultima vez que foi executado. Enviar relatório de erros para os programadores do ConnectBot?</string> + <string name="menu_colors_reset">Limpar</string> + <string name="app_is_running">O ConnectBot esta a ser executado</string> + <string name="color_red">vermelho</string> + <string name="color_green">verde</string> + <string name="color_blue">azul</string> + <string name="color_gray">cinzento</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-ro/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Un client SSH simplu, flexibil, open-source</string> + <string name="service_desc">Managementul conexiunilor si al cheilor publice</string> + <string name="title_hosts_list">Gazde</string> + <string name="title_pubkey_list">Chei publice</string> + <string name="title_port_forwards_list">Redirectări trafic</string> + <string name="title_host_editor">Editare gazdă</string> + <string name="title_help">Ajutor</string> + <string name="title_colors">Culori</string> + <string name="resolve_connect">Conectează-te</string> + <string name="resolve_entropy">Genereaza sursă entropie</string> + <string name="menu_insert">Adaugă gazdă</string> + <string name="menu_delete">Sterge gazdă</string> + <string name="menu_preferences">Setări</string> + <string name="help_intro">Selecteaza un subiect pentru a accesa mai multe informatii</string> + <string name="help_about">Despre ConnectBot</string> + <string name="help_keyboard">Tastatură</string> + <string name="pubkey_generate">Generează</string> + <string name="pubkey_import">Importă</string> + <string name="pubkey_delete">Șterge cheia</string> + <string name="pubkey_gather_entropy">Genereaza sursa entropie</string> + <string name="pubkey_touch_prompt">Apasa aceasta zona pentru a genera entropie: %1$d%% finalizat</string> + <string name="pubkey_touch_hint">Pentru a va asigura un grad inalt de stocasticitate in timpul generarii cheii, miscati cat mai aleator degetul in zona de mai jos</string> + <string name="pubkey_generating">Generare cheie ...</string> + <string name="pubkey_copy_private">Copiaza cheia privata</string> + <string name="pubkey_copy_public">Copiaza cheia publica</string> + <string name="pubkey_list_empty">Apasa \"Menu\" pentru a crea sau pentru a importa chei.</string> + <string name="pubkey_unknown_format">Format necunoscut</string> + <string name="pubkey_change_password">Schimbă parola</string> + <string name="pubkey_list_pick">Selecteaza de pe /card SD</string> + <string name="pubkey_import_parse_problem">A aparut o eroare in timpul citirii cheii private</string> + <string name="pubkey_unlock">Decripteaza cheia</string> + <string name="pubkey_failed_add">Parola gresita pentru cheia \'%1$s\'. Autenticitatea cererii nu poate fi verificata.</string> + <string name="pubkey_memory_load">Incarca in memorie</string> + <string name="pubkey_memory_unload">Sterge din memorie</string> + <string name="pubkey_load_on_start">Incarca cheia la start</string> + <string name="pubkey_confirm_use">Confirma alegerea inainte de folosirea cheii</string> + <string name="portforward_list_empty">Apasa \"Menu\" pentru a crea redirectari de trafic</string> + <string name="portforward_edit">Editeaza redirectari trafic</string> + <string name="portforward_delete">Sterge redirectari trafic</string> + <string name="prompt_nickname">Poreclă:</string> + <string name="prompt_nickname_hint_pubkey">Cheia mea</string> + <string name="prompt_source_port">Port sursă</string> + <string name="prompt_destination">Destinație</string> + <string name="prompt_old_password">Parola veche:</string> + <string name="prompt_password">Parolă:</string> + <string name="prompt_again">(din nou)</string> + <string name="prompt_type">Mod redirectare:</string> + <string name="prompt_password_can_be_blank">Nota: parola</string> + <string name="prompt_bits">Biți:</string> + <string name="prompt_pubkey_password">Parola pentru cheia \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Acceptați utilizarea cheii \'%1$s\' \nde către agentul de autentificare?</string> + <string name="host_verification_failure_warning_header">ATENTIE: IDENTITATEA SISTEMULUI CONECTAT S-A SCHIMBAT!</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-ru/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,212 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Простой и мощный SSH-клиент с открытым исходным кодом.</string> + <string name="service_desc">Управляет SSH-соединениями и загруженными публичными ключами</string> + <string name="title_hosts_list">Серверы</string> + <string name="title_pubkey_list">Публичные ключи</string> + <string name="title_port_forwards_list">Проброс портов</string> + <string name="title_host_editor">Изменить сервер</string> + <string name="title_help">Помощь</string> + <string name="title_colors">Настройка цветов</string> + <string name="resolve_connect">Подключиться</string> + <string name="resolve_entropy">Сбор случайных данных</string> + <string name="menu_insert">Добавить сервер</string> + <string name="menu_delete">Удалить сервер</string> + <string name="menu_preferences">Настройки</string> + <string name="help_intro">Выберите то, о чём Вы хотите узнать</string> + <string name="help_about">О ConnectBot</string> + <string name="help_keyboard">Клавиатура</string> + <string name="pubkey_generate">Генерировать</string> + <string name="pubkey_import">Импортировать</string> + <string name="pubkey_delete">Удалить ключ</string> + <string name="pubkey_gather_entropy">Сбор случайной информации</string> + <string name="pubkey_touch_prompt">Нажмите сюда для генерирования случайной информации: %1$d%% готово</string> + <string name="pubkey_touch_hint">Для использования случайной выборки во время генерации ключа - перемещайте палец в области экрана ниже.</string> + <string name="pubkey_generating">Генерирование пары ключей</string> + <string name="pubkey_copy_private">Копировать приватный ключ</string> + <string name="pubkey_copy_public">Копировать публичный ключ</string> + <string name="pubkey_list_empty">Выберите Меню для создания или импорта пары ключей</string> + <string name="pubkey_unknown_format">Неизвестный формат</string> + <string name="pubkey_change_password">Сменить пароль</string> + <string name="pubkey_list_pick">Загрузить с SD карты</string> + <string name="pubkey_import_parse_problem">Проблема при распозновании импортированного частного ключа</string> + <string name="pubkey_unlock">Разблокировать ключ</string> + <string name="pubkey_failed_add">Неверный пароль для ключа \'%1$s\'. Аутентификация не удалась</string> + <string name="pubkey_memory_load">Загрузить в память</string> + <string name="pubkey_memory_unload">Выгрузить из памяти</string> + <string name="pubkey_load_on_start">Загружать ключ при старте</string> + <string name="pubkey_confirm_use">Подтверждение перед использованием</string> + <string name="portforward_list_empty">Выберите Меню для переадресации порта</string> + <string name="portforward_edit">Правка переадресации порта</string> + <string name="portforward_delete">Удалить переадресацию порта</string> + <string name="prompt_nickname">Псевдоним:</string> + <string name="prompt_nickname_hint_pubkey">Мой рабочий ключ</string> + <string name="prompt_source_port">С порта</string> + <string name="prompt_destination">На порт</string> + <string name="prompt_old_password">Старый пароль:</string> + <string name="prompt_password">Пароль:</string> + <string name="prompt_again">(повторить)</string> + <string name="prompt_type">Тип переадресации</string> + <string name="prompt_password_can_be_blank">Поле для ввода пароля не может быть пустым</string> + <string name="prompt_bits">Размер в битах</string> + <string name="prompt_pubkey_password">Пароль для ключа \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Использовать ключ \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">ВНИМАНИЕ! ИДЕНТИФИКАЦИЯ УДАЛЕННОГО ХОСТА ЗАМЕНЕНА</string> + <string name="host_verification_failure_warning">Похоже есть возможность что вас ломают. Или кто то изменил ключ на удаленном хосте.</string> + <string name="prompt_host_disconnected">Хост отвалился.\nЗакрыть сессию ?</string> + <string name="prompt_continue_connecting">Хотите продолжить\nпопытки соединения?</string> + <string name="host_authenticity_warning">Подлинность хоста \'%1$s\' не может быть установлена</string> + <string name="host_fingerprint">Подпись (fingerprint) host-ключа для сервера %1$s - %2$s</string> + <string name="alert_passwords_do_not_match_msg">Пароли не совпадают!</string> + <string name="alert_wrong_password_msg">Неверный пароль!</string> + <string name="alert_key_corrupted_msg">Возможно частный ключ повреждён!</string> + <string name="alert_sdcard_absent">SD карта не вставлена!</string> + <string name="button_add">Добавить</string> + <string name="button_change">Изменить</string> + <string name="button_generate">Генерировать ключ</string> + <string name="button_resize">Изменить размер</string> + <string name="alert_disconnect_msg">Соединение потеряно</string> + <string name="pref_emulation_category">Эмулятор терминала</string> + <string name="pref_emulation_title">Режим эмуляции</string> + <string name="pref_emulation_summary">Режим эмуляции терминала для использования PTY соединений</string> + <string name="pref_scrollback_title">Размер прокрутки</string> + <string name="pref_scrollback_summary">Размер буфера прокруктки в памяти для каждой консоли</string> + <string name="pref_ui_category">Пользовательский интерфейс</string> + <string name="pref_rotation_title">Настройки ориентации экрана</string> + <string name="pref_rotation_summary">Настройки смены ориентации дисплея при пользовании клавиатурой</string> + <string name="pref_fullscreen_title">Полный экран</string> + <string name="pref_fullscreen_summary">Убирать область статуса во время работы с консолью</string> + <string name="pref_memkeys_title">Запомнить ключи в памяти</string> + <string name="pref_memkeys_summary">Держать ключи в памяти пока процессы работают</string> + <string name="pref_update_title">Проверка обновления</string> + <string name="pref_update_summary">Как часто проверять обновления для ConnectBot</string> + <string name="pref_conn_persist_title">Постоянные соединения</string> + <string name="pref_conn_persist_summary">Принудительно сохранять соединение в фоновом режиме.</string> + <string name="pref_keymode_title">Ярлыки папок</string> + <string name="pref_keymode_summary">Выберите, как использовать Alt вместо \'/\' и Shift вместо Tab</string> + <string name="pref_camera_title">Ярлык камеры</string> + <string name="pref_camera_summary">Выберите ярлык, запускаемый при нажатии клавиши камеры</string> + <string name="pref_keepalive_title">Держать экран включенным</string> + <string name="pref_keepalive_summary">Препятствовать отключению экрана при работе в консоли</string> + <string name="pref_wifilock_title">Держать Wi-Fi включенным</string> + <string name="pref_wifilock_summary">Препятствовать отключению Wi-Fi при активном сеансе</string> + <string name="pref_bumpyarrows_title">Настройки обратной связи при нажатии</string> + <string name="pref_bumpyarrows_summary">Вибросигнал при передаче клавиш управления курсором с трекбола; полезно при медленном соединении</string> + <string name="pref_bell_category">Настройки звукового сигнала в терминале</string> + <string name="pref_bell_title">Включить звонок</string> + <string name="pref_bell_volume_title">Громкость сигнала</string> + <string name="pref_bell_vibrate_title">Виброзвонок</string> + <string name="pref_bell_notification_title">Фоновые уведомления</string> + <string name="pref_bell_notification_summary">Включить уведомления для терминала работающего в фоновом процессе</string> + <string name="list_keymode_right">Для специальных функций использовать клавиши с правой стороны</string> + <string name="list_keymode_left">Использовать клавиши с левой стороны</string> + <string name="list_keymode_none">Отключить</string> + <string name="list_pubkeyids_none">Не использовать ключи</string> + <string name="list_pubkeyids_any">Использовать любую свободную клавишу</string> + <string name="hostpref_nickname_title">Псевдоним</string> + <string name="hostpref_color_title">Цвет для категории</string> + <string name="hostpref_fontsize_title">Размер шрифта</string> + <string name="hostpref_pubkeyid_title">Использовать аутентификацию по открытому ключу</string> + <string name="hostpref_authagent_title">Использовать SSH протокол для соединения</string> + <string name="hostpref_postlogin_title">Автоматизация после авторизации</string> + <string name="hostpref_postlogin_summary">Комманды, выполняемые на удаленной машине после подключения</string> + <string name="hostpref_compression_title">Сжатие</string> + <string name="hostpref_compression_summary">Это может быть полезным в медленных сетях</string> + <string name="hostpref_wantsession_title">Начать сеанс оболочки</string> + <string name="hostpref_wantsession_summary">Выключить для использования только переадресации портов</string> + <string name="hostpref_stayconnected_title">Держать подключение</string> + <string name="hostpref_stayconnected_summary">Пытаться переподключиться при отключении узла</string> + <string name="hostpref_delkey_title">Клавиша DEL</string> + <string name="hostpref_delkey_summary">Послать данный код при нажатие клавиши DEL</string> + <string name="hostpref_encoding_title">Кодировка</string> + <string name="hostpref_encoding_summary">Кодировка символов узла</string> + <string name="hostpref_connection_category">Настройки соединения</string> + <string name="hostpref_username_title">Имя пользователя</string> + <string name="hostpref_hostname_title">Узел</string> + <string name="hostpref_port_title">Порт</string> + <string name="bind_never">Не подключен</string> + <string name="bind_minutes">%1$s минут назад</string> + <string name="bind_hours">%1$s час(ов) назад</string> + <string name="bind_days">%1$s дней назад</string> + <string name="console_copy_done">Скопировано %1$d байт в буфер обмена</string> + <string name="console_copy_start">Для выделения области на экране используйте Touch and Drag или Directional Pad</string> + <string name="console_menu_close">Закрыть</string> + <string name="console_menu_copy">Копировать</string> + <string name="console_menu_paste">Вставить</string> + <string name="console_menu_portforwards">Перенаправления портов</string> + <string name="console_menu_resize">Зафиксировать размер</string> + <string name="console_menu_urlscan">Список URL</string> + <string name="button_yes">Да</string> + <string name="button_no">Нет</string> + <string name="portforward_local">Локальный</string> + <string name="portforward_remote">Удалённый</string> + <string name="portforward_dynamic">Динамический (SOCKS)</string> + <string name="portforward_pos">Создать перенаправление порта</string> + <string name="portforward_done">Перенаправление порта успешно завершено</string> + <string name="portforward_problem">Не удалось создать перенаправление порта. Может быть вы используете порты меньше чем 1024 или пор уже используется?</string> + <string name="portforward_menu_add">Добавить перенаправление порта</string> + <string name="hint_userhost">пользователь\@имяхоста</string> + <string name="list_format_error">Используйте формат %1$s</string> + <string name="format_username">имя пользователя</string> + <string name="format_hostname">имяхоста</string> + <string name="format_port">порт</string> + <string name="list_menu_pubkeys">Управление открытыми ключами</string> + <string name="list_menu_sortcolor">Сортировать по цвету</string> + <string name="list_menu_sortname">Сортировать по имени</string> + <string name="list_menu_settings">Настройки</string> + <string name="list_host_disconnect">Разорвать соединение</string> + <string name="list_host_edit">Редактировать хост</string> + <string name="list_host_portforwards">Редактировать перенаправление портов</string> + <string name="list_host_delete">Удалить хост</string> + <string name="list_host_empty">Для быстрого подключения к хосту используйте чекбокс внизу</string> + <string name="list_rotation_default">По умолчанию</string> + <string name="list_rotation_land">Только альбомная ориентация</string> + <string name="list_rotation_port">Только портретная ориетация</string> + <string name="list_rotation_auto">Автоматически</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A затем пробел</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Нет</string> + <string name="list_delkey_backspace">Backspace</string> + <string name="list_delkey_del">Удалить</string> + <string name="delete_message">Вы уверены, что хотите удалить \'%1$s\'?</string> + <string name="delete_pos">Да, удалить</string> + <string name="delete_neg">Отменить</string> + <string name="wizard_agree">Соглашаюсь</string> + <string name="wizard_next">Далее</string> + <string name="wizard_back">Назад</string> + <string name="terminal_no_hosts_connected">Нет подключенных узлов</string> + <string name="terminal_connecting">Подключение к %1$s:%2$d через %3$s</string> + <string name="terminal_sucess">Проверенный узел \'%1$s\' ключ: %2$s</string> + <string name="terminal_failed">Проверка ключа узла провалена</string> + <string name="terminal_using_s2c_algorithm">Алгоритм сервер-клиент: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Алгоритм клиент-сервер: %1$s %2$s</string> + <string name="terminal_using_algorithm">Используемый алгоритм: %1$s %2$s</string> + <string name="terminal_auth">Пытаюсь аутентифицироваться</string> + <string name="terminal_auth_pass">Попытка \'password\' авторизации</string> + <string name="terminal_auth_pass_fail">Неуспешная попытка \'password\' авторизации</string> + <string name="terminal_auth_pubkey_any">Попытка \'publickey\' авторизации с публичными ключами в памяти</string> + <string name="terminal_auth_pubkey_invalid">Выбранный открытый ключ неверен, выберите другой в редакторе узлов</string> + <string name="terminal_auth_pubkey_specific">Попытка \'publickey\' авторизации</string> + <string name="terminal_auth_pubkey_fail">Неуспешная авторизация \'publickey\' с ключом \'%1$s\'</string> + <string name="terminal_auth_ki">Попытка \'keyboard-interactive\' авторизации</string> + <string name="terminal_auth_ki_fail">Неуспешная авторизация</string> + <string name="terminal_auth_fail">Ваш хост не поддерживает \'password\' и \'keyboard-interactive\' типа авторизации</string> + <string name="terminal_no_session">Настройки хоста не позволяют запустить данную сессию</string> + <string name="terminal_enable_portfoward">Включить переадресацию порта: %1$s</string> + <string name="local_shell_unavailable">Ошибка! На этом телефоне отсутствует локальная оболочка.</string> + <string name="notification_text">%1$s требует внимания</string> + <string name="no">Нет</string> + <string name="with_confirmation">С подтверждением</string> + <string name="yes">Да</string> + <string name="exceptions_submit_message">Возможно, при последнем запуске программы возникла проблема. Отправить разработчикам отчет об ошибке?</string> + <string name="menu_colors_reset">Сбросить</string> + <string name="app_is_running">ConnectBot запущен</string> + <string name="color_red">красный</string> + <string name="color_green">зелёный</string> + <string name="color_blue">синий</string> + <string name="color_gray">серый</string> + <string name="image_description_connected">Подключено</string> + <string name="image_description_show_keyboard">Показать клавиатуру</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-sk/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,316 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Jednoduchý, výkonný, open-source SSH klient.</string> + <string name="service_desc">Spravuje SSH spojenia a načítané verejné kľúče</string> + <string name="auth_agent_service_desc">"Pracuje ako SSH-Agent pre iné aplikácie na tomto zarieadení"</string> + <string name="ssh_agent_permission_label">použíť SSH kľúče uložené vo Vašom SSH-Agentovi</string> + <string name="ssh_agent_permission_desc">Povolí aplikácií autentifikáciu SSH transakcií pomocou Vašich súkromných kľúčov uložených v aplikácii ConnectBot. + VEĽMI NEBEZPEČNÉ ak zneužité zlomyselnou aplikáciou.</string> + <string name="title_hosts_list">Hostitelia</string> + <string name="title_pubkey_list">Verejné kľúče</string> + <string name="title_port_forwards_list">Presmerovanie portov</string> + <string name="title_host_editor">Upraviť Hostiteľa</string> + <string name="title_help">Nápoveda</string> + <string name="title_colors">Farby</string> + <string name="resolve_connect">Pripojiť</string> + <string name="resolve_entropy">Získať entropiu</string> + <string name="menu_insert">Pridať hostiteľa</string> + <string name="menu_delete">Zmazať hostiteľa</string> + <string name="menu_preferences">Nastavenia</string> + <string name="help_intro">Prosím, vyberte si tému pre viac informácií o danom subjekte.</string> + <string name="help_about">O programe ConnectBot</string> + <string name="help_keyboard">Klávesnica</string> + <string name="pubkey_generate">Vygenerovať</string> + <string name="pubkey_import">Importovať</string> + <string name="pubkey_delete">Zmazať kľúč</string> + <string name="pubkey_gather_entropy">Získavanie entropie</string> + <string name="pubkey_touch_prompt">Dotknite sa plochy pre získanie náhodnosti: %1$d%% hotovo</string> + <string name="pubkey_touch_hint">Pre zabezpečenie náhodnosti počas generovania kľúča pohybujte prstom náhodne po ploche nižšie.</string> + <string name="pubkey_generating">"Generujem kľúčový pár…"</string> + <string name="pubkey_copy_private">Kopírovať súkromný kľúč</string> + <string name="pubkey_copy_public">Kopírovať verejný kľúč</string> + <string name="pubkey_list_empty">Ťukni na Menu pre vytvorenie\nalebo importovanie páru kľúčov.</string> + <string name="pubkey_unknown_format">Neznámy formát</string> + <string name="pubkey_change_password">Zmeniť heslo</string> + <string name="pubkey_list_pick">Vyberte z /sdcard</string> + <string name="pubkey_import_parse_problem">Chyba pri importe súkromného kľúča</string> + <string name="pubkey_unlock">Odomknúť kľúč</string> + <string name="pubkey_failed_add">Nesprávne heslo pre kľúč \'%1$s\'. Overenie zlyhalo.</string> + <string name="pubkey_memory_load">Nahrať do pamäte</string> + <string name="pubkey_memory_unload">Odstrániť z pamäte</string> + <string name="pubkey_load_on_start">Načítať kľúč pri štarte</string> + <string name="pubkey_confirm_use">Potvrdiť pred použitím</string> + <string name="portforward_list_empty">Ťukni na Menu pre vytvorenie\npresmerovania portov.</string> + <string name="portforward_edit">Upraviť presmerovanie portov</string> + <string name="portforward_delete">Zmazať smerovanie portu</string> + <string name="prompt_nickname">Prezývka:</string> + <string name="prompt_nickname_hint_pubkey">Môj pracovný kľúč</string> + <string name="prompt_source_port">Zdrojový port:</string> + <string name="prompt_destination">Cieľ:</string> + <string name="prompt_old_password">Staré heslo:</string> + <string name="prompt_password">Heslo:</string> + <string name="prompt_again">(znovu)</string> + <string name="prompt_type">Typ:</string> + <string name="prompt_password_can_be_blank">Poznámka: heslo nemôže byť prázdne</string> + <string name="prompt_bits">Veľkost v bitoch:</string> + <string name="prompt_pubkey_password">Heslo pre kľúč \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Povoliť vzdialenému hostitelovi\npoužíť kľúč \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">VAROVANIE! IDENTIFIKÁCIA VZDIALENÉHO HOSTITEĽA SA ZMENILA!</string> + <string name="host_verification_failure_warning">JE MOŽNÉ, ŽE IDE O NEKALÚ AKTIVITU!\nNiekto vás môže sledovať (man-in-the-middle útok)!\nTiež je možné, že kľúč hostiteľa bol zmenený.</string> + <string name="prompt_host_disconnected">Hostiteľ sa odpojil.\nUkončiť sedenie?</string> + <string name="prompt_continue_connecting">Naozaj chcete\npokračovať v pripájaní?</string> + <string name="host_authenticity_warning">Autenticita hostiteľa \'%1$s\' nemohla byť overená.</string> + <string name="host_fingerprint">Odtlačok kľúča hostiteľa %1$s je %2$s</string> + <string name="alert_passwords_do_not_match_msg">Heslo sa nezhoduje!</string> + <string name="alert_wrong_password_msg">Nesprávne heslo!</string> + <string name="alert_key_corrupted_msg">Súkromný kľúč vyzerá poškodene!</string> + <string name="alert_sdcard_absent">Nie je vložená SD karta!</string> + <string name="button_add">Pridať</string> + <string name="button_change">Zmeniť</string> + <string name="button_generate">Vygenerovať kľúč</string> + <string name="button_resize">Zmeniť veľkosť</string> + <string name="button_resize_reset">Prednastavená veľkosť</string> + <string name="alert_disconnect_msg">Spojenie stratené</string> + <string name="pref_emulation_category">Emulácia terminálu</string> + <string name="pref_emulation_title">Mód emulácie</string> + <string name="pref_emulation_summary">Použiť mód emulácie terminálu pri PTY spojeniach</string> + <string name="pref_scrollback_title">Veľkosť histórie</string> + <string name="pref_scrollback_summary">Veľkosť histórie uložená v pamäti pre každú konzolu</string> + <string name="pref_ui_category">Používateľské rozhranie</string> + <string name="pref_rotation_title">Mód otáčania</string> + <string name="pref_rotation_summary">Ako zmeniť rotáciu, keď sa zobrazí / skryje klávesnica</string> + <string name="pref_memkeys_title">Zapamätať kľúče v pamäti</string> + <string name="pref_memkeys_summary">Ponechať odomknuté kľúče v pamäti pokiaľ nie je ukončená služba na pozadí.</string> + <string name="pref_update_title">Kontrolovať aktualizácie</string> + <string name="pref_update_summary">Nastaviť maximálnu frekvenciu kontroly aktualizácií pre ConnectBot</string> + <string name="pref_conn_persist_title">Perzistentné pripojenia</string> + <string name="pref_conn_persist_summary">Vynútiť spojenie aj v pozadí</string> + <string name="pref_keymode_title">Skratky adresárov</string> + <string name="pref_keymode_summary">Vyberte ako použiť Alt pre \'/\' a Shift pre Tab</string> + <string name="pref_camera_title">Tlačidlo fotoaparát</string> + <string name="pref_camera_summary">Činnosť, ktorá sa vykoná po stlačení tlačidla fotoaparátu</string> + <string name="pref_volup_title">Tlačidlo hlasnejšie</string> + <string name="pref_volup_summary">Činnosť, ktorá sa vykoná po stlačení tlačidla hlasnejšie</string> + <string name="pref_voldn_title">Tlačidlo tichšie</string> + <string name="pref_voldn_summary">Činnosť, ktorá sa vykoná po stlačení tlačidla tichšie</string> + <string name="pref_search_title">Tlačidlo hľadať</string> + <string name="pref_search_summary">Činnosť, ktorá sa vykoná po stlačení tlačidla hľadať</string> + <string name="pref_keepalive_title">Ponechať obrazovku zapnutú</string> + <string name="pref_keepalive_summary">Zabrániť vypnutiu obrazovky pri práci s konzolou</string> + <string name="pref_wifilock_title">Ponechať Wi-Fi aktívne</string> + <string name="pref_wifilock_summary">Ponechať Wi-Fi aktívne pokiaľ je otvorené spojenie</string> + <string name="pref_bumpyarrows_title">Hrboľaté šípky</string> + <string name="pref_bumpyarrows_summary">Vibrovať pri posielaní kurzorových tlačidiel z trackballu; užitočné pre chybové spojenia</string> + <string name="pref_bell_category">Zvonček terminálu</string> + <string name="pref_bell_title">Akustický zvonček</string> + <string name="pref_bell_volume_title">Hlasitosť zvončeka</string> + <string name="pref_bell_vibrate_title">Vibrovať pri zvončeku</string> + <string name="pref_bell_notification_title">Upozornenia na pozadí</string> + <string name="pref_bell_notification_summary">Zobraziť upozorneni ak zazvoní zvonček terminálu bežiaceho v pozadí.</string> + <string name="list_keymode_right">Použite klávesy vpravo</string> + <string name="list_keymode_left">Použite klávesy vľavo</string> + <string name="list_keymode_none">Vypnúť</string> + <string name="list_pubkeyids_none">Nepoužívať kľúče</string> + <string name="list_pubkeyids_any">Použiť ktorýkoľvek odomknutý kľúč</string> + <string name="hostpref_nickname_title">Prezývka</string> + <string name="hostpref_color_title">Farebná kategória</string> + <string name="hostpref_fontsize_title">Veľkosť písma (bodov)</string> + <string name="hostpref_pubkeyid_title">Použiť verejný kľúč pre autentifikáciu</string> + <string name="hostpref_authagent_title">Použiť SSH autorizačného agenta</string> + <string name="hostpref_postlogin_title">Automatizácia po prihlásení</string> + <string name="hostpref_postlogin_summary">Príkazy, ktoré sa spustia na vzdialenom serveri po prihlásení</string> + <string name="hostpref_compression_title">Kompresia</string> + <string name="hostpref_compression_summary">Môže pomôcť pri pomalých sieťach</string> + <string name="hostpref_wantsession_title">Spustiť sedenie shellu</string> + <string name="hostpref_wantsession_summary">Vypnite túto možnosť ak chcete len presmerovať porty</string> + <string name="hostpref_stayconnected_title">Zostať pripojený</string> + <string name="hostpref_stayconnected_summary">Znovu sa pripojiť pri odpojení</string> + <string name="hostpref_delkey_title">Klávesa DEL</string> + <string name="hostpref_delkey_summary">Kód stlačenej DEL klávesy</string> + <string name="hostpref_encoding_title">Kódovanie</string> + <string name="hostpref_encoding_summary">Kódovanie znakov hostiteľa</string> + <string name="hostpref_connection_category">Nastavenia pripojenia</string> + <string name="hostpref_username_title">Používateľské meno</string> + <string name="hostpref_hostname_title">Hostiteľ</string> + <string name="hostpref_port_title">Port</string> + <string name="hostpref_x11_forwarding">"Presmerovanie X11"</string> + <string name="hostpref_wantx11forward_title">"Zapnúť presmerovanie X11"</string> + <string name="hostpref_wantx11forward_summary">"Sedenia X11 budú presmerované na hostiteľa a port uvedený nižšie"</string> + <string name="hostpref_x11host_title">"Hostiteľ pre presmerovanie X11"</string> + <string name="hostpref_x11port_title">"Port pre presmerovanie X11"</string> + <string name="bind_never">Nikdy nepripojený</string> + <string name="bind_minutes">Pred %1$s minútami</string> + <string name="bind_hours">Pred %1$s hodinami</string> + <string name="bind_days">Pred %1$s dňami</string> + <string name="console_copy_done">%1$d bajtov skopírovaných do schránky</string> + <string name="console_copy_start">Pre výber kopírovanej oblasti \nsa dotknite a ťahajte\nalebo použite smerové tlačidlo</string> + <string name="console_menu_close">Zatvoriť</string> + <string name="console_menu_copy">Kopírovať</string> + <string name="console_menu_paste">Vložiť</string> + <string name="console_menu_portforwards">Presmerovanie portov</string> + <string name="console_menu_resize">Vynútiť veľkosť</string> + <string name="console_menu_urlscan">Nájsť URL</string> + <string name="console_menu_screencapture">Snímka obrazovky</string> + <string name="console_menu_download">"Prevziať súbor"</string> + <string name="console_menu_upload">"Odoslať súbor"</string> + <string name="button_yes">Áno</string> + <string name="button_no">Nie</string> + <string name="portforward_local">Lokálny</string> + <string name="portforward_remote">Vzdialený</string> + <string name="portforward_dynamic">Dynamický (SOCKS)</string> + <string name="portforward_pos">Vytvoriť presmerovanie portu</string> + <string name="portforward_done">Premerovanie portu úspešne vytvorené</string> + <string name="portforward_problem">Chyba pri vytvorení presmerovania portu, možno používate port menší ako 1024 alebo je už obsadený?</string> + <string name="portforward_menu_add">Pridať presmerovanie portu</string> + <string name="hint_userhost">používateľ\@hostiteľ</string> + <string name="list_format_error">Použite formát \"%1$s\"</string> + <string name="format_username">používateľ</string> + <string name="format_hostname">hostiteľ</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Spravovať verejné kľúče</string> + <string name="list_menu_sortcolor">Usporiadať podľa farby</string> + <string name="list_menu_sortname">Usporiadať podľa názvu</string> + <string name="list_menu_settings">Nastavenia</string> + <string name="list_host_disconnect">Odpojiť</string> + <string name="list_host_edit">Upraviť nastavenia hostiteľa</string> + <string name="list_host_portforwards">Upraviť presmerovanie portov</string> + <string name="list_host_delete">Zmazať hostiteľa</string> + <string name="list_host_empty">Použite pole rýchleho pripojenia\nnižšie pre pripojenie k hostiteľovi.</string> + <string name="list_rotation_default">Predvolené</string> + <string name="list_rotation_land">Vynútiť na šírku</string> + <string name="list_rotation_port">Vynútiť na výšku</string> + <string name="list_rotation_auto">Automaticky</string> + <string name="list_hwbutton_screen_capture">Snímka obrazovky</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A , potom medzerník</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Klávesa Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Žiadny</string> + <string name="list_delkey_backspace">Backspace</string> + <string name="list_delkey_del">Delete</string> + <string name="delete_message">Naozaj chcete zmazať \'%1$s\'?</string> + <string name="delete_pos">Áno, vymazať</string> + <string name="delete_neg">Zrušiť</string> + <string name="wizard_agree">Súhlasím</string> + <string name="wizard_next">Ďalej</string> + <string name="wizard_back">Späť</string> + <string name="terminal_no_hosts_connected">Žiadny hostiteľ nie je pripijený</string> + <string name="terminal_connecting">Pripájanie k %1$s:%2$d cez %3$s</string> + <string name="terminal_sucess">Hostiteľ overený \'%1$s\' kľúč: %2$s</string> + <string name="terminal_failed">Overenie kľúča hostiteľa neúspešné.</string> + <string name="terminal_using_s2c_algorithm">Server-klient algoritmus: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Klient-server algoritmus: %1$s %2$s</string> + <string name="terminal_using_algorithm">Použitie algoritmu: %1$s %2$s</string> + <string name="terminal_auth">Pokus o overenie</string> + <string name="terminal_auth_pass">Pokus o overenie heslom</string> + <string name="terminal_auth_pass_fail">Overenie heslom neúspešné</string> + <string name="terminal_auth_pubkey_any">Pokus o overenie verejným kľúčom z pamäti</string> + <string name="terminal_auth_pubkey_invalid">Vybraný verejný kľúč je neplatný, skúste zvoliť kľúč v editore hostiteľov</string> + <string name="terminal_auth_pubkey_specific">Pokus o overenie konkrétnym verejným kľúčom</string> + <string name="terminal_auth_pubkey_fail">Overenie verejným kľúčom \'%1$s\' zlyhalo</string> + <string name="terminal_auth_ki">Pokus o overenie cez interaktívnu klávesnicu</string> + <string name="terminal_auth_ki_fail">Overenie cez interaktívnu klávesnicu zlyhalo</string> + <string name="terminal_auth_fail">[Váš hostiteľ nepodporuje overenie heslom alebo overenie cez interaktívnu klávesnicu.]</string> + <string name="terminal_no_session">Sedenie nebude spustené z dôvodu nastavenia hostiteľa.</string> + <string name="terminal_enable_portfoward">Zapnúť presmerovanie portu: %1$s</string> + <string name="local_shell_unavailable">Chyba! Lokálny shell je nedostupný na tomto telefóne.</string> + <string name="notification_text">%1$s vyžaduje vašu pozornosť.</string> + <string name="no">Nie</string> + <string name="with_confirmation">S potvrdením</string> + <string name="yes">Áno</string> + <string name="exceptions_submit_message">Ostatné spustenie ConnectBot asi skončilo chybou. Zaslať chýbovú správu vývojárom ConnectBot?</string> + <string name="menu_colors_reset">Pôvodné</string> + <string name="app_is_running">ConnectBot je spustený</string> + <string name="color_red">červená</string> + <string name="color_green">zelená</string> + <string name="color_blue">modrá</string> + <string name="color_gray">sivá</string> + <string name="button_close">Zavrieť</string> + <string name="pref_custom_keymap_title">Prispôsobenie klávesnice</string> + <string name="pref_custom_keymap_summary">Presmerovanie vybraných kláves na podporovaných zariadeniach</string> + <string name="pref_custom_keymap_full">plnohodnotná klávesnica</string> + <string name="pref_custom_keymap_disabled">vypnuté</string> + <string name="resize_error_title">Chyba pri zmene veľkosti</string> + <string name="resize_error_width_height">Šírka a výška musia byť väčšie ako 0</string> + <string name="pref_screen_capture_category">Snímka obrazovky</string> + <string name="pref_screen_capture_folder">Cesta pre snímku obrazovky</string> + <string name="pref_screen_capture_folder_summary">Priečinok, kam sa budú ukladať snímky obrazovky</string> + <string name="pref_screen_capture_popup">Správa o snímke obrazovky</string> + <string name="pref_screen_capture_popup_summary">Zobraziť vyskakovacie okno pri úspešnej snímke obrazovky</string> + <string name="screen_capture">Snímka obrazovky</string> + <string name="screenshot_success_title">Snímka obrazovky úspešná</string> + <string name="screenshot_saved_as">Snímka obrazovky bola uložená do</string> + <string name="screenshot_error_title">Chyba pri snímke obrazvky</string> + <string name="screenshot_not_saved_as">Snímka obrazovky nemohla byť uložená do</string> + <string name="pref_picker_string">Obsah okna Sym</string> + <string name="pref_picker_string_summary">Sada znakov do dialógového okna na výber znaku</string> + <string name="pref_picker_keep_open">Ponechať okno Sym otvorené</string> + <string name="pref_picker_keep_open_summary">Iba tlačidlo zrušiť zavrie dialógové okno na výber znaku</string> + <string name="pref_file_transfer_category">Prenos súborov</string> + <string name="pref_file_dialog_title">Výber súbora</string> + <string name="pref_file_dialog_summary">Formulár na výber súborov a priečinkov</string> + <string name="pref_file_dialog_builtin">zabudovaný</string> + <string name="error_starting_app">Nepodarilo sa spustiť %1$s</string> + <string name="file_chooser_select_file">Vybrať súbor %1s</string> + <string name="select_for_download">na prevzatie</string> + <string name="select_for_upload">na odoslanie</string> + <string name="select_for_key_import">na import kľúča</string> + <string name="location">Umiestnenie</string> + <string name="cant_read_folder">Chyba pri čítaní priečinka.</string> + <string name="nnew">Nové</string> + <string name="select">Vybrať</string> + <string name="file_name">Názov súbora:</string> + <string name="cancel">Zrušiť</string> + <string name="save">Uložiť</string> + <string name="new_file">Nový súbor</string> + <string name="no_data">Žiadne dáta</string> + <string name="pref_download_folder">Priečinok pre preberanie</string> + <string name="pref_download_folder_summary">Cesta pre ukladanie prevzatých súborov</string> + <string name="pref_remote_upload_folder">Vzdialený priečinok pre odosielanie</string> + <string name="pref_remote_upload_folder_summary">Vzdialená cesta pre odosielanie súborov</string> + <string name="pref_upload_dest_prompt">Pýtať sa na vzdialené umiestnenie</string> + <string name="pref_upload_dest_prompt_summary">Zadávať vzdialený nazov alebo cestu pre odosielaný súbor</string> + <string name="pref_background_file_transfer">Prenos súborov na pozadí</string> + <string name="pref_background_file_transfer_summary">Odosielanie a preberanie súborov uskutočniť na pozadí.</string> + <string name="transfer_downloading">"Preberanie súborov…"</string> + <string name="transfer_downloading_file">Preberanie súbora: %1$s</string> + <string name="transfer_download_complete">Preberanie ukončené</string> + <string name="transfer_download_failed">Chyba pri preberaní:%1$s</string> + <string name="transfer_select_remote_download_title">Prevziať súbor(y)</string> + <string name="transfer_select_remote_download_desc">Cesty k vzdialeným súborom na prevzatie (jeden na riadok)</string> + <string name="transfer_select_remote_upload_dest_title">Umiestnenie odosielaného súbora</string> + <string name="transfer_select_remote_upload_dest_desc">Vzdialené umiestnenie pre:</string> + <string name="transfer_button_download">Prevziať</string> + <string name="transfer_button_upload">Odoslať</string> + <string name="transfer_uploading">"Odosielanie súborov…"</string> + <string name="transfer_uploading_file">Odosielanie súbora: %1$s</string> + <string name="transfer_upload_complete">Odosielanie ukončené</string> + <string name="transfer_upload_failed">Chyba pri odosielaní:%1$s</string> + <string name="pubkey_export_private">"Exportovať súkromný kľúč"</string> + <string name="pubkey_export_public">"Exportovať verejný kľúč"</string> + <string name="pubkey_public_save_as">Uložiť verejný kľúč</string> + <string name="pubkey_public_save_as_desc">Názov súboru (s cestou) pre uloženie verejného kľúča</string> + <string name="pubkey_private_save_as">Uložiť súkromný kľúč</string> + <string name="pubkey_private_save_as_desc">Názov súboru (s cestou) pre uloženie súkromného kľúča</string> + <string name="pubkey_public_export_success">Verejný kľúč bol uložený ako %1$s</string> + <string name="pubkey_public_export_problem">Chyba pri exporte verejného kľúča</string> + <string name="pubkey_private_export_success">Súkromný kľúč bol uložený ako %1$s</string> + <string name="pubkey_private_export_problem">Chyba pri exporte súkromného kľúča</string> + <string name="pref_debug_category">Nastavenia pre vývoj</string> + <string name="pref_debug_keycodes">Zobrazovať kódy kláves</string> + <string name="pref_debug_keycodes_summary">Zobrazovať kódy stlačených kláves v termináli</string> + <string name="keycode_pressed">Kód stlačenej klávesy</string> + <string name="pref_extended_longpress">Rozšírené menu dlhého stlačenia</string> + <string name="pref_extended_longpress_summary">Zobraziť možnosti vstupu v menu dlhého stlačenia</string> + <string name="longpress_select_action">Vybrať akciu</string> + <string name="longpress_enable_full_screen_mode">Zapnúť režim celej obrazovky</string> + <string name="longpress_disable_full_screen_mode">Vypnúť režim celej obrazovky</string> + <string name="longpress_change_font_size">Zmeniť veľkosť písma</string> + <string name="longpress_arrows_dialog">Šípky</string> + <string name="longpress_ctrl_dialog">CTRL+?</string> + <string name="longpress_fkeys_dialog">Funkčné klávesy</string> + <string name="longpress_sym_dialog">Výber znaku</string> + <string name="pref_ctrl_string">Obsah okna Ctrl</string> + <string name="pref_ctrl_string_summary">Sada znakov na výber kombinácie CTRL+?</string> + <string name="fullscreen">Celá obrazovka</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-sl/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,189 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Enostaven, močan, odprtokodni SSH odjemalec.</string> + <string name="service_desc">Vzdržuje SSH povezave in naložene javne ključe</string> + <string name="title_hosts_list">Gostitelji</string> + <string name="title_pubkey_list">Javni ključi</string> + <string name="title_port_forwards_list">Posredovana vrata</string> + <string name="title_host_editor">Urejanje gostitelja</string> + <string name="title_help">Pomoč</string> + <string name="title_colors">Barve</string> + <string name="resolve_connect">Poveži</string> + <string name="resolve_entropy">Zberi entropijo</string> + <string name="menu_insert">Dodaj gostitelja</string> + <string name="menu_delete">Odstrani gostitelja</string> + <string name="menu_preferences">Možnosti</string> + <string name="help_intro">Izberite temo spodaj za več informacij o določeni zadevi.</string> + <string name="help_about">O ConnectBotu</string> + <string name="help_keyboard">Tipkovnica</string> + <string name="pubkey_generate">Ustvari</string> + <string name="pubkey_import">Uvozi javni ključ</string> + <string name="pubkey_delete">Izbriši ključ</string> + <string name="pubkey_gather_entropy">Zbiranje entropije</string> + <string name="pubkey_touch_prompt">Dotaknite to polje za zbiranje naključnih vrednosti: %1$d%% končano</string> + <string name="pubkey_touch_hint">Da bi zagotovili naključnost med ustvarjanjem ključa, naključno premikajte prst po polju spodaj.</string> + <string name="pubkey_generating">Ustvarjanje para ključev</string> + <string name="pubkey_copy_private">Kopirajte zasebni ključ</string> + <string name="pubkey_copy_public">Kopirajte javni ključ</string> + <string name="pubkey_list_empty">Dotaknite \"Meni\" za ustvarjanje\nali uvažanje para ključev</string> + <string name="pubkey_unknown_format">Neznana vrsta</string> + <string name="pubkey_change_password">Spremenite geslo</string> + <string name="pubkey_list_pick">Izberite iz /sdcard</string> + <string name="pubkey_import_parse_problem">Problem pri razčlenjevanju uvoženega zasebnega ključa</string> + <string name="pubkey_unlock">Odkleni ključ</string> + <string name="pubkey_failed_add">Napačno geslo za ključ \'%1$s. Overitev spodletela.</string> + <string name="pubkey_memory_load">Naloži v spomin</string> + <string name="pubkey_memory_unload">Razloži s spomina</string> + <string name="pubkey_load_on_start">Naloži ključ ob začetku</string> + <string name="pubkey_confirm_use">Potrdi pred uporabo</string> + <string name="portforward_list_empty">Dotakni \"Meni\" za ustvarjanje\nposredovanih vrat.</string> + <string name="portforward_edit">Urejaj posredovana vrata</string> + <string name="portforward_delete">Izbriši posredovana vrata</string> + <string name="prompt_nickname">Vzdevek:</string> + <string name="prompt_nickname_hint_pubkey">Moj delovni ključ</string> + <string name="prompt_source_port">Izvorna vrata:</string> + <string name="prompt_destination">Cilj:</string> + <string name="prompt_old_password">Staro geslo:</string> + <string name="prompt_password">Geslo:</string> + <string name="prompt_again">(ponovno)</string> + <string name="prompt_type">Vrsta:</string> + <string name="prompt_password_can_be_blank">Opomba: geslo je lahko prazno</string> + <string name="prompt_bits">Biti:</string> + <string name="prompt_pubkey_password">Geslo za ključ \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Dovoli oddaljenemu gostitelju\nuporabo ključa \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">OPOZORILO: ISTOVETENJE ODDALJENEGA GOSTITELJA SE JE SPREMENILO!</string> + <string name="host_verification_failure_warning">MOŽNO JE, DA NEKDO POČNE NEKAJ ZLOBNEGA!\nNekdo vam lahko prisluškuje (napad s posrednikom)!\nMožno pa je tudi, da se je spremenil ključ gostitelja.</string> + <string name="prompt_host_disconnected">Gostitelj je prekinil povezavo.\nZaprem sejo?</string> + <string name="prompt_continue_connecting">Ali ste prepričani, da želite\nnadaljevati s povezovanjem?</string> + <string name="host_authenticity_warning">Istovetnost gostitelja \'%1$s\' ni mogoče ugotoviti.</string> + <string name="host_fingerprint">Ključ gostitelja %1$s ima zgoščeno vrednost %2$s</string> + <string name="alert_passwords_do_not_match_msg">Gesla se ne ujemajo!</string> + <string name="alert_wrong_password_msg">Napačno geslo!</string> + <string name="alert_key_corrupted_msg">Zasebni ključ izgleda pokvarjen!</string> + <string name="alert_sdcard_absent">Kartica SD ni vstavljena!</string> + <string name="button_add">Dodaj</string> + <string name="button_change">Spremeni</string> + <string name="button_generate">Ustvari ključ</string> + <string name="button_resize">Spremeni velikost</string> + <string name="alert_disconnect_msg">Povezava prekinjena</string> + <string name="pref_emulation_category">Posnemanje terminala</string> + <string name="pref_emulation_title">Način posnemanja</string> + <string name="pref_emulation_summary">Način posnemanja terminala za uporabo za PTY povezave</string> + <string name="pref_scrollback_title">Velikost pomnjenja vrstic</string> + <string name="pref_scrollback_summary">Velikost medpomnilnika pomnjenih vrstic ohraniti v spomnu za vsako konzolo</string> + <string name="pref_ui_category">Uporabniški vmesnik</string> + <string name="pref_rotation_title">Način za sukanje</string> + <string name="pref_rotation_summary">Kako spremeniti sukanje, ko tipkovnica skoči ven/noter</string> + <string name="pref_fullscreen_title">Celozaslonski način</string> + <string name="pref_fullscreen_summary">Skrij vrstico stanja, ko v konzoli</string> + <string name="pref_memkeys_title">Zapomni ključe v spominu</string> + <string name="pref_memkeys_summary">Hrani odklenjene ključe v spomnu dokler storitev v zaledju ni zaključena</string> + <string name="pref_update_title">Pregled posodobitev</string> + <string name="pref_update_summary">Nastavite največjo pogostost za preverjanje posodobitev za ConnectBota</string> + <string name="pref_conn_persist_title">Obstojne povezave</string> + <string name="pref_conn_persist_summary">Prisili povezave, da ostanejo povezane v ozadju</string> + <string name="pref_keymode_title">Bližnjice mape</string> + <string name="pref_keymode_summary">Izberite kako uporabiti Alt za \'/\' ter Shift za Tab</string> + <string name="pref_camera_title">Bližnjica kamere</string> + <string name="pref_camera_summary">Izberite, katera bližnjica se sproži, ko se pritisne gumb kamere</string> + <string name="pref_keepalive_title">Ohrani zaslon dejaven</string> + <string name="pref_keepalive_summary">Prepreči ugašanje zaslona med delom v konzoli</string> + <string name="pref_wifilock_title">Ohrani Wi-Fi dejaven</string> + <string name="pref_wifilock_summary">Prepreči ugašanje Wi-Fija med dejavno sejo</string> + <string name="pref_bumpyarrows_title">Izbočene puščice</string> + <string name="pref_bell_category">Zvonec terminala</string> + <string name="pref_bell_title">Slišen zvonec</string> + <string name="pref_bell_volume_title">Glasnost zvonca</string> + <string name="pref_bell_vibrate_title">Vibriraj ob zvoncu</string> + <string name="pref_bell_notification_title">Obvestila ozadja</string> + <string name="list_keymode_left">Uporabi ključe z leve strani</string> + <string name="list_keymode_none">Onemogoči</string> + <string name="list_pubkeyids_none">Ne uporabljaj ključev</string> + <string name="list_pubkeyids_any">Uporabi kateregakoli odklenjenega ključa</string> + <string name="hostpref_nickname_title">Vzdevek</string> + <string name="hostpref_color_title">Barvna kategorija</string> + <string name="hostpref_fontsize_title">Velikost pisave (pt)</string> + <string name="hostpref_pubkeyid_title">Uporabi overitev z javnim ključem</string> + <string name="hostpref_authagent_title">Uporabi SSH overitvenega agenta</string> + <string name="hostpref_compression_title">Stiskanje</string> + <string name="hostpref_compression_summary">To vam lahko pomaga pri počasnejših omrežjih</string> + <string name="hostpref_wantsession_title">Začni sejo lupine</string> + <string name="hostpref_stayconnected_title">Ostanite povezani</string> + <string name="hostpref_stayconnected_summary">Poskusi se ponovno povezati, če se prekine povezava</string> + <string name="hostpref_delkey_title">Tipka DEL</string> + <string name="hostpref_delkey_summary">Poslana koda tipke, ko je tipka DEL pritisnjena</string> + <string name="hostpref_encoding_title">Kodiranje</string> + <string name="hostpref_encoding_summary">Kodiranje znakov za gostitelja</string> + <string name="hostpref_connection_category">Nastavitve povezave</string> + <string name="hostpref_username_title">Uporabniško ime</string> + <string name="hostpref_hostname_title">Gostitelj</string> + <string name="hostpref_port_title">Vrata</string> + <string name="bind_never">Nikoli povezani</string> + <string name="bind_minutes">%1$s minut nazaj</string> + <string name="bind_hours">%1$s ur nazaj</string> + <string name="bind_days">%1$s dni nazaj</string> + <string name="console_menu_close">Zapri</string> + <string name="console_menu_copy">Kopiraj</string> + <string name="console_menu_paste">Prilepi</string> + <string name="console_menu_portforwards">Posredovanje vrat</string> + <string name="button_yes">Da</string> + <string name="button_no">Ne</string> + <string name="portforward_local">Krajevno</string> + <string name="portforward_remote">Oddaljeno</string> + <string name="portforward_pos">Ustvari posredovanje vrat</string> + <string name="portforward_done">Uspešno ustvarjeno posredovanje vrat</string> + <string name="portforward_menu_add">Dodaj posredovanje vrat</string> + <string name="hint_userhost">uporabnik\@gostitelj</string> + <string name="list_format_error">Uporabi vrsto %1$s</string> + <string name="format_username">Uporabniško ime</string> + <string name="format_hostname">ime gostitelja</string> + <string name="format_port">vrata</string> + <string name="list_menu_pubkeys">Upravljanje z javnimi ključi</string> + <string name="list_menu_sortcolor">Razvrsti po barvi</string> + <string name="list_menu_sortname">Razvrsti po imenu</string> + <string name="list_menu_settings">Nastavitve</string> + <string name="list_host_disconnect">Prekini povezavo</string> + <string name="list_host_edit">Urejaj gostitelja</string> + <string name="list_host_portforwards">Urejaj posredovanja vrat</string> + <string name="list_host_delete">Izbriši gostitelja</string> + <string name="list_rotation_default">Privzeto</string> + <string name="list_rotation_land">Prisili ležeče</string> + <string name="list_rotation_port">Prisili pokončno</string> + <string name="list_rotation_auto">Samodejno</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A nato Space</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Nič</string> + <string name="list_delkey_backspace">Vračalka</string> + <string name="list_delkey_del">Delete</string> + <string name="delete_message">Ali ste prepričani, da želite izbrisati \'%1$s\'?</string> + <string name="delete_pos">Da, izbriši.</string> + <string name="delete_neg">Prekliči</string> + <string name="wizard_agree">Se strinjam</string> + <string name="wizard_next">Naprej</string> + <string name="wizard_back">Nazaj</string> + <string name="terminal_no_hosts_connected">Trenutno ni noben gostitelj povezan</string> + <string name="terminal_connecting">Povezujem se na %1$s:%2$d preko %3$s</string> + <string name="terminal_sucess">Preverjen gostitelj \'%1$s\' ključ: %2$s</string> + <string name="terminal_failed">Preverjanje ključa gostitelja spodletelo.</string> + <string name="terminal_using_s2c_algorithm">Strežnik - odjemalec algoritem: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Odjemalec - strežnik algoritem: %1$s %2$s</string> + <string name="terminal_using_algorithm">Uporabljam algoritem: %1$s %2$s</string> + <string name="terminal_auth">Poskušam se overit</string> + <string name="terminal_auth_pass">Poskušam overitev z geslom</string> + <string name="terminal_auth_pass_fail">Overitev z geslom spodletela</string> + <string name="terminal_auth_pubkey_fail">Spodletela avtentikacijska metoda \'publickey\' z ključem \'%1$s\'</string> + <string name="terminal_auth_fail">[Vaš gostitelj ne podpira \'password\' ali \'keyboard-interactive\' avtentikacije.]</string> + <string name="notification_text">%1$s želi vašo pozornost.</string> + <string name="no">Ne</string> + <string name="with_confirmation">S potrditvijo</string> + <string name="yes">Da</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> + <string name="menu_colors_reset">Ponastavi</string> + <string name="app_is_running">ConnectBot je dejaven</string> + <string name="color_red">rdeča</string> + <string name="color_green">zelena</string> + <string name="color_blue">modra</string> + <string name="color_gray">siva</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-sv/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Enkel och kraftfull SSH-klient baserad på öppen källkod.</string> + <string name="service_desc">Upprätthåller SSH-anslutningar och laddade publika nycklar</string> + <string name="title_hosts_list">Värddatorer</string> + <string name="title_pubkey_list">Publika nycklar</string> + <string name="title_port_forwards_list">Vidarebefordring av portar</string> + <string name="title_host_editor">Redigera värddator</string> + <string name="title_help">Hjälp</string> + <string name="title_colors">Färger</string> + <string name="resolve_connect">Anslut</string> + <string name="resolve_entropy">Samla in entropi</string> + <string name="menu_insert">Lägg till värd</string> + <string name="menu_delete">Ta bort värd</string> + <string name="menu_preferences">Inställningar</string> + <string name="help_intro">Var god välj ett ämne nedan som du skulle vilja ha mer information om.</string> + <string name="help_about">Om ConnectBot</string> + <string name="help_keyboard">Tangentbord</string> + <string name="pubkey_generate">Generera</string> + <string name="pubkey_import">Importera</string> + <string name="pubkey_delete">Ta bort nyckel</string> + <string name="pubkey_gather_entropy">Samlar in entropi</string> + <string name="pubkey_touch_prompt">Rör vid rutan för att samla in slumpdata: %1$d%% klart</string> + <string name="pubkey_touch_hint">För att försäkra dig om att nyckeln som skapas är slumpmässig, rör fingret slumpmässigt över skärmen.</string> + <string name="pubkey_generating">"Genererar nyckelpar…"</string> + <string name="pubkey_copy_private">Kopiera privat nyckel</string> + <string name="pubkey_copy_public">Kopiera publik nyckel</string> + <string name="pubkey_list_empty">Tryck på Meny för att\nskapa eller importera nyckelpar</string> + <string name="pubkey_unknown_format">Okänt format</string> + <string name="pubkey_change_password">Ändra lösenord</string> + <string name="pubkey_list_pick">Välj från /sdcard</string> + <string name="pubkey_import_parse_problem">Svårigheter med att tyda den importerade privata nyckeln</string> + <string name="pubkey_unlock">Lås upp nyckel</string> + <string name="pubkey_failed_add">Felaktigt lösenord för nyckeln \'%1$s\'. Autentiseringen misslyckades.</string> + <string name="pubkey_memory_load">Ladda in i minnet</string> + <string name="pubkey_memory_unload">Ladda ur minnet</string> + <string name="pubkey_load_on_start">Ladda nyckel från start</string> + <string name="pubkey_confirm_use">Bekräfta innan användning</string> + <string name="portforward_list_empty">Rör vid Menu för att skapa\nvidarebefodringar av portar.</string> + <string name="portforward_edit">Ändra vidarebefordring av port</string> + <string name="portforward_delete">Ta bort vidarebefodring av port</string> + <string name="prompt_nickname">Namn:</string> + <string name="prompt_nickname_hint_pubkey">Min jobbnyckel</string> + <string name="prompt_source_port">Inkommande portnummer:</string> + <string name="prompt_destination">Destination:</string> + <string name="prompt_old_password">Gammalt lösenord:</string> + <string name="prompt_password">Lösenord:</string> + <string name="prompt_again">(igen)</string> + <string name="prompt_type">Typ:</string> + <string name="prompt_password_can_be_blank">Notis: lösenordet kan vara blankt</string> + <string name="prompt_bits">Bitar:</string> + <string name="prompt_pubkey_password">Lösenord för nyckel \'%1$s\'</string> + <string name="prompt_allow_agent_to_use_key">Tillåt fjärrvärd att\nanvända nyckel \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">VARNING: IDENTIFIERING AV FJÄRRVÄRD HAR ÄNDRATS!</string> + <string name="host_verification_failure_warning">MÖJLIGT INTRÅNGSFÖRSÖK!\nNågon skulle kunna avlyssna dig nu (man-in-the-middle attack)!\nDet är även möjligt att värdnyckeln just har ändrats.</string> + <string name="prompt_host_disconnected">Värden har kopplat ner anslutningen.\nStäng?</string> + <string name="prompt_continue_connecting">Är du säker att du vill\nfortsätta att ansluta?</string> + <string name="host_authenticity_warning">Identiteten av värden \'%1$s\' går ej att fastställa.</string> + <string name="host_fingerprint">Värd %1$s nyckel-fingeravtryck är %2$s</string> + <string name="alert_passwords_do_not_match_msg">Lösenorden överenstämmer inte med varandra!</string> + <string name="alert_wrong_password_msg">Felaktigt lösenord!</string> + <string name="alert_key_corrupted_msg">Privata nyckeln ser ut att vara korrupt!</string> + <string name="alert_sdcard_absent">SD-kort ej isatt!</string> + <string name="button_add">Lägg till</string> + <string name="button_change">Ändra</string> + <string name="button_generate">Generera nyckel</string> + <string name="button_resize">Ändra storlek</string> + <string name="alert_disconnect_msg">Anslutningen förlorad</string> + <string name="pref_emulation_category">Terminalemulering</string> + <string name="pref_emulation_title">Emuleringsläge</string> + <string name="pref_emulation_summary">Emuleringsläge för PTY-anslutningar</string> + <string name="pref_scrollback_title">Textbufferstorlek</string> + <string name="pref_scrollback_summary">Storlek på textbuffer för varje konsol</string> + <string name="pref_ui_category">Användargränssnitt</string> + <string name="pref_rotation_title">Rotationsläge</string> + <string name="pref_rotation_summary">Hur rotation skall ändras när tangentbord aktiveras/avaktiveras</string> + <string name="pref_fullscreen_title">Helskärm</string> + <string name="pref_fullscreen_summary">Göm status medan konsol visas</string> + <string name="pref_memkeys_title">Kom ihåg nycklar</string> + <string name="pref_memkeys_summary">Behåll olåsta nycklar i minnet tills bakände-tjänst avslutas</string> + <string name="pref_update_title">Uppdateringskontroll</string> + <string name="pref_update_summary">Intervall för att söka efter ConnectBot-uppdateringar</string> + <string name="pref_conn_persist_title">Kvarstående anslutningar</string> + <string name="pref_conn_persist_summary">Tvinga anslutningar att fortsätta i bakgrunden</string> + <string name="pref_keymode_title">Genvägar för katalog</string> + <string name="pref_keymode_summary">Välj hur Alt används för \'/\' och Shift för Tab</string> + <string name="pref_camera_title">Genväg för kamera</string> + <string name="pref_camera_summary">Välj genväg för kamera-knappen</string> + <string name="pref_keepalive_title">Håll skärmen aktiv</string> + <string name="pref_keepalive_summary">Håll skärmen aktiv medan konsolen används</string> + <string name="pref_wifilock_title">Håll trådlöst nätverk aktivt</string> + <string name="pref_wifilock_summary">Hindra att trådlöst nätverk slås av under en aktiv session</string> + <string name="pref_bumpyarrows_title">Aktiva piltangenter</string> + <string name="pref_bumpyarrows_summary">Vibrera när piltangenter sänds från pekdon; bra för långsamma anslutningar</string> + <string name="pref_bell_category">Terminal-ljud</string> + <string name="pref_bell_title">Aktivt</string> + <string name="pref_bell_volume_title">Ljudvolym</string> + <string name="pref_bell_vibrate_title">Vibrera</string> + <string name="pref_bell_notification_title">Bakgrundsmeddelanden</string> + <string name="pref_bell_notification_summary">Skicka meddelande när en terminal som körs i bakgrunden skickar ljudsignal.</string> + <string name="list_keymode_right">Använd högerknapparna</string> + <string name="list_keymode_left">Använd vänsterknapparna</string> + <string name="list_keymode_none">Avaktivera</string> + <string name="list_pubkeyids_none">Använd inte knapparna</string> + <string name="list_pubkeyids_any">Använd valfri olåst nyckel</string> + <string name="hostpref_nickname_title">Smeknamn</string> + <string name="hostpref_color_title">Färgkategori</string> + <string name="hostpref_fontsize_title">Teckenstorlek</string> + <string name="hostpref_pubkeyid_title">Använd publik nyckelverifiering</string> + <string name="hostpref_authagent_title">Använd SSH-verifieringsagent</string> + <string name="hostpref_postlogin_title">Automatisering efter inloggning</string> + <string name="hostpref_postlogin_summary">Kommandon att köras på fjärrservern när verifierad</string> + <string name="hostpref_compression_title">Kompression</string> + <string name="hostpref_compression_summary">Detta kan hjälpa på långsammare nätverk</string> + <string name="hostpref_wantsession_title">Starta shell-session</string> + <string name="hostpref_wantsession_summary">Inaktivera denna inställning för att bara använda vidarebefodring av portar</string> + <string name="hostpref_stayconnected_title">Fortsätt vara ansluten</string> + <string name="hostpref_stayconnected_summary">Försök återansluta till värden om frånkopplad</string> + <string name="hostpref_delkey_title">DEL-tangent</string> + <string name="hostpref_delkey_summary">Tangentkoden som sänds när DEL-tangenten trycks ner</string> + <string name="hostpref_encoding_title">Teckenkodning</string> + <string name="hostpref_encoding_summary">Teckenkodning för värddatorn</string> + <string name="hostpref_connection_category">Anslutningsinställningar</string> + <string name="hostpref_username_title">Användarnamn</string> + <string name="hostpref_hostname_title">Värd</string> + <string name="hostpref_port_title">Port</string> + <string name="bind_never">Aldrig ansluten</string> + <string name="bind_minutes">%1$s minuter sedan</string> + <string name="bind_hours">%1$s timmar sendan</string> + <string name="bind_days">%1$s dagar sedan</string> + <string name="console_copy_done">Kopierade %1$d bytes till urklippshanteraren.</string> + <string name="console_copy_start">Tryck och drag\neller använd bollen\nför att markera en yta för kopiering</string> + <string name="console_menu_close">Stäng</string> + <string name="console_menu_copy">Kopiera</string> + <string name="console_menu_paste">Klistra in</string> + <string name="console_menu_portforwards">Vidarebefodring av port</string> + <string name="console_menu_resize">Fast storlek</string> + <string name="console_menu_urlscan">URL-sökning</string> + <string name="button_yes">Acceptera</string> + <string name="button_no">Neka</string> + <string name="portforward_local">Lokal</string> + <string name="portforward_remote">Fjärr</string> + <string name="portforward_dynamic">Dynamisk (SOCKS)</string> + <string name="portforward_pos">Skapa vidarebefodring av port</string> + <string name="portforward_done">Vidarebefodring av port skapad.</string> + <string name="portforward_problem">Lyckades inte att skapa en vidarebefodring av port, är den under 1024 eller används den kanske?</string> + <string name="portforward_menu_add">Lägg till vidarebefodring av port.</string> + <string name="hint_userhost">användarnamn\@värdnamn</string> + <string name="list_format_error">Använd formatet %1$s</string> + <string name="format_username">användarnamn</string> + <string name="format_hostname">värdnamn</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Hantera publika nycklar</string> + <string name="list_menu_sortcolor">Sortera efter färg</string> + <string name="list_menu_sortname">Sortera efter namn</string> + <string name="list_menu_settings">Inställningar</string> + <string name="list_host_disconnect">Koppla ner</string> + <string name="list_host_edit">Inställningar för värd</string> + <string name="list_host_portforwards">Ändra vidarebefodringar av portar</string> + <string name="list_host_delete">Ta bort värd</string> + <string name="list_host_empty">Använd snabbanslutningen\nnedan för att ansluta till en värd.</string> + <string name="list_rotation_default">Förvalt värde</string> + <string name="list_rotation_land">Tvinga horisontellt läge</string> + <string name="list_rotation_port">Tvinga vertikalt läge</string> + <string name="list_rotation_auto">Automatiskt</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A sen Space</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Ingen</string> + <string name="list_delkey_backspace">Baksteg</string> + <string name="list_delkey_del">Ta bort</string> + <string name="delete_message">Är du säker att du vill ta bort \'%1$s\'?</string> + <string name="delete_pos">Ja, ta bort</string> + <string name="delete_neg">Avbryt</string> + <string name="wizard_agree">Godkänn</string> + <string name="wizard_next">Nästa</string> + <string name="wizard_back">Tillbaka</string> + <string name="terminal_no_hosts_connected">Inga värdar anslutna</string> + <string name="terminal_connecting">Ansluter till %1$s:%2$d via %3$s</string> + <string name="terminal_sucess">Verifierad värd \'%1$s\' nyckel: %2$s</string> + <string name="terminal_failed">Verifikation av värd-nyckeln misslyckades.</string> + <string name="terminal_using_s2c_algorithm">Server-till-klient algoritm: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Klient-till-server algoritm: %1$s %2$s</string> + <string name="terminal_using_algorithm">Använder algoritm: %1$s %2$s</string> + <string name="terminal_auth">Försöker att autentisera</string> + <string name="terminal_auth_pass">Försöker med \'password\' autentisering</string> + <string name="terminal_auth_pass_fail">Autentiseringsmetoden \'password\' misslyckades</string> + <string name="terminal_auth_pubkey_any">Försöker \'publik nyckel\' verifiering med en nyckel från det lokala minnet</string> + <string name="terminal_auth_pubkey_invalid">Vald publik nyckel är ogiltig, försök välj ny nyckel i värd redigerare</string> + <string name="terminal_auth_pubkey_specific">Försöker \'publik nyckel\' verifiera med en specifik publik nyckel</string> + <string name="terminal_auth_pubkey_fail">Verifierings metod \'publik nyckel\' med nyckel \'%1$s\' misslyckades</string> + <string name="terminal_auth_ki">Försöker med \'keyboard-interactive\' autentisering</string> + <string name="terminal_auth_ki_fail">Autentiseringsmetoden \'keyboard-interactive\' misslyckades</string> + <string name="terminal_auth_fail">[Din värd stödjer inte \'password\' eller \'keyboard-interactive\' autentiseringsmetoderna]</string> + <string name="terminal_no_session">Session kommer inte att startas på grund av värd önskemål.</string> + <string name="terminal_enable_portfoward">Aktivera vidarebefodring av port: %1$s</string> + <string name="local_shell_unavailable">Misslyckande! Lokal shell är otillgänglig på denna telefon</string> + <string name="notification_text">%1$s vill ha din uppmärksamhet.</string> + <string name="no">Nej</string> + <string name="with_confirmation">Med bekräftelse</string> + <string name="yes">Ja</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> + <string name="menu_colors_reset">Återställ</string> + <string name="app_is_running">ConnectBot är igång</string> + <string name="color_red">röd</string> + <string name="color_green">grön</string> + <string name="color_blue">blå</string> + <string name="color_gray">grå</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-tr/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,214 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Basit, güçlü, açık kaynak kodlu SSH client</string> + <string name="service_desc">SSH bağlantılarını ve yüklenmiş açık-anahtarları muhafaza eder</string> + <string name="title_hosts_list">Hostlar</string> + <string name="title_pubkey_list">Açık-anahtarlar</string> + <string name="title_port_forwards_list">Port yönlendirme</string> + <string name="title_host_editor">Host\'u Düzenle</string> + <string name="title_help">Yardım</string> + <string name="title_colors">Renkler</string> + <string name="resolve_connect">Bağlan</string> + <string name="resolve_entropy">Rastgele girdi topla</string> + <string name="menu_insert">Host ekle</string> + <string name="menu_delete">Host\'u sil</string> + <string name="menu_preferences">Seçenekler</string> + <string name="help_intro">Özel bir konu hakkinda daha fazla bilgi için lütfen aşağıdaki ilgili konuyu seçiniz.</string> + <string name="help_about">ConnectBot Hakkında</string> + <string name="help_keyboard">Klavye</string> + <string name="pubkey_generate">Oluştur</string> + <string name="pubkey_import">Harici dosyadan aktar</string> + <string name="pubkey_delete">Anahtarı Sil</string> + <string name="pubkey_gather_entropy">Entropi Toplanıyor</string> + <string name="pubkey_touch_prompt">Rastgele girdi toplamak için bu kutuya dokun: %1$d%% oluşturuldu</string> + <string name="pubkey_touch_hint">Anahtar oluşturmada gerekli rastgele girdi kaydedebilmemiz için parmağınızı aşağıdaki kutu üzerinde rastgele haraket ettiriniz.</string> + <string name="pubkey_generating">"Anahtar çifti oluşturuluyor…"</string> + <string name="pubkey_copy_private">Özel-anahtarı kopyala</string> + <string name="pubkey_copy_public">Umumi-anahtarı kopyala</string> + <string name="pubkey_list_empty">Anahtar-çiftini oluşturmak için\nveya dişardan eklemek için \"Menü\"ye dokunun.</string> + <string name="pubkey_unknown_format">Tanınmayan dosya formatı</string> + <string name="pubkey_change_password">Şifreyi değiştir</string> + <string name="pubkey_list_pick">/sdcard dan aktar</string> + <string name="pubkey_import_parse_problem">Dışardan eklenen özel-anahtarı okurken sorun oluştu</string> + <string name="pubkey_unlock">Anahtarın şifresini giriniz</string> + <string name="pubkey_failed_add">Anahtar \'%1$s\' için hatalı şifre verdiniz. Kimlik doğrulama başarısız oldu.</string> + <string name="pubkey_memory_load">Belleğe yükle</string> + <string name="pubkey_memory_unload">Bellekten kaldır</string> + <string name="pubkey_load_on_start">Başlangıçta anahtarı yükle</string> + <string name="pubkey_confirm_use">Kullanım öncesi doğrulama</string> + <string name="portforward_list_empty">Port yönlendirmesi oluşturmak için\n\"Menü\"ye dokunun</string> + <string name="portforward_edit">Port yönlendirmeyi düzenle</string> + <string name="portforward_delete">Port yönlendirmeyi sil</string> + <string name="prompt_nickname">Rumuz:</string> + <string name="prompt_nickname_hint_pubkey">Umumi-anahtar rumuzu</string> + <string name="prompt_source_port">Kaynak kapı:</string> + <string name="prompt_destination">Hedef (Anasistem:Kapı):</string> + <string name="prompt_old_password">Eski şifre:</string> + <string name="prompt_password">Şifre:</string> + <string name="prompt_again">(tekrar)</string> + <string name="prompt_type">Tip:</string> + <string name="prompt_password_can_be_blank">Not: parola boş bırakılabilir</string> + <string name="prompt_bits">İkiller:</string> + <string name="prompt_pubkey_password">Anahtar \'%1$s\' için parola</string> + <string name="prompt_allow_agent_to_use_key">Uzak anasistemin \'%1$s\' anahtarını\nkullanmasına izin ver?</string> + <string name="host_verification_failure_warning_header">UYARI: UZAK ANASİSTEM KİMLİĞİ DEĞİŞMİŞ!</string> + <string name="host_verification_failure_warning">BİRİLERİNİN KÖTÜ BİRŞEYLER YAPIYOR OLMASI OLASI!\nBirileri şu anda sizi dinliyor olabilir (aradaki adam saldırısı)!\nSadece anasistem anahtarı da değişmiş olabilir.</string> + <string name="prompt_host_disconnected">Anasistem bağlantısı kesildi.\nOturumu kapat?</string> + <string name="prompt_continue_connecting">Bağlanmaya devam etmek\nistediğinize emin misiniz?</string> + <string name="host_authenticity_warning">Anasistem \'%1$s\' in gerçekliği doğrulanamadı.</string> + <string name="host_fingerprint">Anasistem %1$s anahtar parmakizi %2$s</string> + <string name="alert_passwords_do_not_match_msg">Parolalar uyuşmuyor!</string> + <string name="alert_wrong_password_msg">Yanlış parola!</string> + <string name="alert_key_corrupted_msg">Kişisel anahtar bozuk görünüyor</string> + <string name="alert_sdcard_absent">SD kart takılmamış!</string> + <string name="button_add">Ekle</string> + <string name="button_change">Değiştir</string> + <string name="button_generate">Anahtar Üret</string> + <string name="button_resize">Yeniden boyutlandır</string> + <string name="alert_disconnect_msg">Bağlantı Kesildi</string> + <string name="pref_emulation_category">Uçbirim öykünümü</string> + <string name="pref_emulation_title">Öykünüm kipi</string> + <string name="pref_emulation_summary">PTY bağlantıları için kullanılan uçbirim öykünüm kipi</string> + <string name="pref_scrollback_title">Geri kaydırma boyu</string> + <string name="pref_scrollback_summary">Her bir konsol için bellekte tutulacak geri kaydırma arabellek boyu</string> + <string name="pref_ui_category">Kullanıcı arayüzü</string> + <string name="pref_rotation_title">Dönme kipi</string> + <string name="pref_rotation_summary">Klavye saklandığında/açıldığında dönüş nasıl değişir</string> + <string name="pref_fullscreen_title">Tüm ekran</string> + <string name="pref_fullscreen_summary">Konsolda iken durum çubuğunu gizle</string> + <string name="pref_memkeys_title">Anahtarları bellekte tut</string> + <string name="pref_memkeys_summary">Kilidi açılmış anahtarları arkadaki hizmetler sonlanana kadar bellekte tut</string> + <string name="pref_update_title">Güncellemelere bak</string> + <string name="pref_update_summary">ConnectBot güncellemelerine bakmak için en fazla sıklığı ayarla</string> + <string name="pref_conn_persist_title">Bağlantıları sürekli tut</string> + <string name="pref_conn_persist_summary">Arkaplanda iken bağlantıları bağlı tutmaya zorla</string> + <string name="pref_keymode_title">Dizin kısayolları</string> + <string name="pref_keymode_summary">\'/\' için Alt ve Tab için Shift kullanımının nasıl olacağını seç</string> + <string name="pref_camera_title">Kamera kısayolu</string> + <string name="pref_camera_summary">Kamera düğmesine basıldığında hangi kısayolun tetikleneceğini seç</string> + <string name="pref_keepalive_title">Ekranı açık tut</string> + <string name="pref_keepalive_summary">Bir konsolda çalışırken ekranın kapanmasını engelle</string> + <string name="pref_wifilock_title">Wi-Fi etkin tut</string> + <string name="pref_wifilock_summary">Bir oturum etkinken Wi-Fi kapanmasını engelle</string> + <string name="pref_bumpyarrows_title">dalgalı oklar</string> + <string name="pref_bumpyarrows_summary">Okları izotop ile kullanırken titret; düşük bağlantılar için kullanışlıdır</string> + <string name="pref_bell_category">Terminal zili</string> + <string name="pref_bell_title">Sesli zil</string> + <string name="pref_bell_volume_title">Zil ses düzeyi</string> + <string name="pref_bell_vibrate_title">Titreşim</string> + <string name="pref_bell_notification_title">Arkaplan uyarıları</string> + <string name="pref_bell_notification_summary">Arka planda çalışan terminal zil sesinde uyarı gönder</string> + <string name="list_keymode_right">Sağ taraftaki tuşları kullan</string> + <string name="list_keymode_left">Sol taraftaki tuşları kullan</string> + <string name="list_keymode_none">Devre Dışı Bırak</string> + <string name="list_pubkeyids_none">Tuşları kullanma</string> + <string name="list_pubkeyids_any">Herhangi bir tuşu kullan</string> + <string name="hostpref_nickname_title">Rumuz</string> + <string name="hostpref_color_title">Renk kategorisi</string> + <string name="hostpref_fontsize_title">Yazıtipi boyutu (pt)</string> + <string name="hostpref_pubkeyid_title">Umumi-anahtar doğrulaması yap</string> + <string name="hostpref_authagent_title">SSH auth agent teyidi kullan</string> + <string name="hostpref_postlogin_title">post-login otomasyonu</string> + <string name="hostpref_postlogin_summary">Uzak sunucuya bağlanıldığında çalıştırılacak komutlar</string> + <string name="hostpref_compression_title">Sıkıştırma</string> + <string name="hostpref_compression_summary">Yavaş ağlarda yardımcı olabilir</string> + <string name="hostpref_wantsession_title">Shell oturumu başlat</string> + <string name="hostpref_wantsession_summary">Sadece port yönlendirmeyi kullanmak için bu seçeneği boş bırakın</string> + <string name="hostpref_stayconnected_title">Bağlı kal</string> + <string name="hostpref_stayconnected_summary">Bağlantı koparsa tekrar bağlanmayı dene</string> + <string name="hostpref_delkey_title">DEL tuşu</string> + <string name="hostpref_delkey_summary">DEL yani sil tuşuna basıldığında gönderilecek key kodu</string> + <string name="hostpref_encoding_title">Dil Kodlaması</string> + <string name="hostpref_encoding_summary">Sunucu karakter kodlaması</string> + <string name="hostpref_connection_category">Bağlantı ayarları</string> + <string name="hostpref_username_title">Kullanıcı Adı</string> + <string name="hostpref_hostname_title">Sunucu</string> + <string name="hostpref_port_title">Port</string> + <string name="bind_never">Daha önce bağlanılmadı</string> + <string name="bind_minutes">%1$s dakika önce</string> + <string name="bind_hours">%1$s saat önce</string> + <string name="bind_days">%1$s gün önce</string> + <string name="console_copy_done">%1$d byte panoya kopyalandı</string> + <string name="console_copy_start">Kopyalanacak alanı seçmek için dokun ve sürükle ya da pad kullan</string> + <string name="console_menu_close">Kapat</string> + <string name="console_menu_copy">Kopyala</string> + <string name="console_menu_paste">Yapıştır</string> + <string name="console_menu_portforwards">Port Yönlendirmeleri</string> + <string name="console_menu_resize">Ebat zorunlu</string> + <string name="console_menu_urlscan">URL Tara</string> + <string name="button_yes">Evet</string> + <string name="button_no">Hayır</string> + <string name="portforward_local">Yerel</string> + <string name="portforward_remote">Uzak</string> + <string name="portforward_dynamic">Dinamik (SOCKS)</string> + <string name="portforward_pos">Port yönlendirmesi oluştur</string> + <string name="portforward_done">Port yönlendirmesi başarıyla oluşturuldu</string> + <string name="portforward_problem">Port yönlendirmesi oluşturmada hata oldu, port 1024 altı yada meşgul bir port kullanmakdan kaynaklanabilir</string> + <string name="portforward_menu_add">Port yönlendirmesi ekle</string> + <string name="hint_userhost">kullanici\@sunucuadi</string> + <string name="list_format_error">%1$s formatında kullanın</string> + <string name="format_username">kullanıcı adı</string> + <string name="format_hostname">sunucu adı</string> + <string name="format_port">port</string> + <string name="list_menu_pubkeys">Umumi-anahtarlar Yönetimi</string> + <string name="list_menu_sortcolor">Rengine göre sırala</string> + <string name="list_menu_sortname">İsime göre sırala</string> + <string name="list_menu_settings">Ayarlar</string> + <string name="list_host_disconnect">Bağlantıyı kes</string> + <string name="list_host_edit">Sunucu düzenle</string> + <string name="list_host_portforwards">Port yönlendirmeleri düzenle</string> + <string name="list_host_delete">Sunucuyu sil</string> + <string name="list_host_empty">Sunucuya bağlanmak için\naşağıdaki hızlı bağlan kutucuğunu kullan</string> + <string name="list_rotation_default">Varsayılan</string> + <string name="list_rotation_land">Yatay zorunlu</string> + <string name="list_rotation_port">Dikey zorunlu</string> + <string name="list_rotation_auto">Otomatik</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A ardından Boşluk</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">Hiçbiri</string> + <string name="list_delkey_backspace">Sil</string> + <string name="list_delkey_del">Sil</string> + <string name="delete_message">\'%1$s\' silinecek onaylıyor musunuz?</string> + <string name="delete_pos">Evet, sil</string> + <string name="delete_neg">İptal Et</string> + <string name="wizard_agree">Kabul et</string> + <string name="wizard_next">İleri</string> + <string name="wizard_back">Geri dön</string> + <string name="terminal_no_hosts_connected">Hiçbir sunucuya bağlanılmadı</string> + <string name="terminal_connecting">%3$s ile %1$s:%2$d bağlanıyor</string> + <string name="terminal_sucess">Host doğrulaması \'%1$s\' anahtar: %2$s</string> + <string name="terminal_failed">Sunucu anahtarı doğrulaması başarısız oldu</string> + <string name="terminal_using_s2c_algorithm">Server-to-client s2c algoritması: %1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">Client-to-server c2s algoritması: %1$s %2$s</string> + <string name="terminal_using_algorithm">Kullanılan algoritma: %1$s %2$s</string> + <string name="terminal_auth">Kimlik doğrulaması yapılıyor</string> + <string name="terminal_auth_pass">\'Şifre\' doğrulaması yapılıyor</string> + <string name="terminal_auth_pass_fail">Kimlik doğrulama \'şifre\' başarısız</string> + <string name="terminal_auth_pubkey_any">Bellekteki herhangi bir umumi-anahtar ile \'umumi-anahtar\' doğrulaması yapılıyor</string> + <string name="terminal_auth_pubkey_invalid">Seçilen umumi-anahtar geçersiz, host düzenleyicideki anahtarı tekrar seçerek deneyiniz</string> + <string name="terminal_auth_pubkey_specific">yerel umumi-anahtar specific public key ile \'publickey\' doğrulaması yapılıyor</string> + <string name="terminal_auth_pubkey_fail">Anahtar \'%1$s\' ile \'publickey\' doğrulama işlemi başarısız</string> + <string name="terminal_auth_ki">\'Klavyeden karşılıklı\' kimlik doğrulaması deneniyor</string> + <string name="terminal_auth_ki_fail">\'Klavyeden karşılıklı\' kimlik doğrulaması işlemi başarısız</string> + <string name="terminal_auth_fail">[Hostunuz \'şifre\' veya \'klavyeden karşılıklı\' kimlik doğrulamasını desteklemiyor.]</string> + <string name="terminal_no_session">Sunucu tercihleri sebebiyle oturum başlatılamıyor</string> + <string name="terminal_enable_portfoward">Port yönlendirmesini etkinleştir: %1$s</string> + <string name="local_shell_unavailable">Başarısız! Yerel shell bu telefonda kullanılamıyor.</string> + <string name="notification_text">%1$s sizi uyarıyor</string> + <string name="no">Hayır</string> + <string name="with_confirmation">teyitli</string> + <string name="yes">Evet</string> + <string name="exceptions_submit_message">ConnectBot son çalıştırıldığında sorunla karşılaştı. Hata raporunu ConnectBot geliştiricilerine iletmek ister misiniz?</string> + <string name="menu_colors_reset">Sıfırla</string> + <string name="app_is_running">ConnectBot çalışıyor</string> + <string name="color_red">kırmızı</string> + <string name="color_green">yeşil</string> + <string name="color_blue">mavi</string> + <string name="color_gray">gri</string> + <string name="colors_fg">ÖR:</string> + <string name="color_bg">AR:</string> + <string name="image_description_connected">Bağlandı.</string> + <string name="image_description_show_keyboard">Klavye göster.</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-uk/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">Простий та потужний SSH клієнт з відкритим кодом</string> + <string name="title_hosts_list">Вузли</string> + <string name="title_pubkey_list">Відкриті ключі</string> + <string name="title_port_forwards_list">Переадресація портів</string> + <string name="title_host_editor">Змінити вузол</string> + <string name="title_help">Допомога</string> + <string name="title_colors">Кольори</string> + <string name="resolve_connect">Підключитись</string> + <string name="menu_insert">Додати вузол</string> + <string name="menu_delete">Вилучити вузол</string> + <string name="menu_preferences">Налаштування</string> + <string name="help_intro">Для додаткової інформації виберіть топік</string> + <string name="help_about">Про ConnectBot</string> + <string name="help_keyboard">Клавіатура</string> + <string name="pubkey_generate">Генерувати</string> + <string name="pubkey_import">Імпортувати</string> + <string name="pubkey_delete">Вилучити ключ</string> + <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> + <string name="pubkey_change_password">Змінити пароль</string> + <string name="pubkey_list_pick">Завантажити з SD карти</string> + <string name="pubkey_unlock">Розблокувати ключ</string> + <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-v11/styles.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <style name="NoTitle" parent="android:Theme.Holo"> + <item name="android:windowContentOverlay">@null</item> + <item name="android:windowActionBarOverlay">true</item> + <item name="android:actionBarStyle">@style/SolidActionBar</item> + </style> + + <style name="SolidActionBar" parent="android:Widget.Holo.ActionBar"> + <item name="android:background">#222222</item> + </style> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-v14/styles.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <style name="NoTitle" parent="android:Theme.DeviceDefault"> + <item name="android:windowContentOverlay">@null</item> + <item name="android:windowActionBarOverlay">true</item> + <item name="android:actionBarStyle">@style/SolidActionBar</item> + </style> + + <style name="SolidActionBar" parent="android:Widget.Holo.ActionBar"> + <item name="android:background">#222222</item> + </style> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-vi/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title_hosts_list">Máy chủ</string> + <string name="title_help">Trợ giúp</string> + <string name="title_colors">Màu sắc</string> + <string name="resolve_connect">Kết nối</string> + <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> + <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> + <string name="list_format_error">Use the format %1$s</string> + <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-zh-rCN/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">简洁、强大、开源的SSH客户端</string> + <string name="service_desc">维护SSH连接及已装载的公钥</string> + <string name="title_hosts_list">主机</string> + <string name="title_pubkey_list">公钥</string> + <string name="title_port_forwards_list">端口转发</string> + <string name="title_host_editor">编辑主机</string> + <string name="title_help">帮助</string> + <string name="title_colors">颜色</string> + <string name="resolve_connect">连接</string> + <string name="resolve_entropy">收集杂乱数</string> + <string name="menu_insert">添加主机</string> + <string name="menu_delete">删除主机</string> + <string name="menu_preferences">设置</string> + <string name="help_intro">请在下面主题中选择一个以查看更多内容</string> + <string name="help_about">关于ConnectBot</string> + <string name="help_keyboard">键盘</string> + <string name="pubkey_generate">产生</string> + <string name="pubkey_import">导入</string> + <string name="pubkey_delete">删除密钥</string> + <string name="pubkey_gather_entropy">正在收集用户熵</string> + <string name="pubkey_touch_prompt">触摸方框来收集随机数:%1$d%完成</string> + <string name="pubkey_touch_hint">请在方框内随机移动手指来生成随机密钥</string> + <string name="pubkey_generating">正在产生密钥配对</string> + <string name="pubkey_copy_private">复制私钥</string> + <string name="pubkey_copy_public">复制公钥</string> + <string name="pubkey_list_empty">点击\"菜单\"来创建或者导入密钥对</string> + <string name="pubkey_unknown_format">未知格式</string> + <string name="pubkey_change_password">更改密码</string> + <string name="pubkey_list_pick">从/sdcard导入</string> + <string name="pubkey_import_parse_problem">导入私钥的时候出现问题</string> + <string name="pubkey_unlock">解锁密钥</string> + <string name="pubkey_failed_add">验证失败,\'%1$s\'密钥密码错误</string> + <string name="pubkey_memory_load">载入到内存</string> + <string name="pubkey_memory_unload">从内存中移除</string> + <string name="pubkey_load_on_start">启动时自动载入公钥</string> + <string name="pubkey_confirm_use">使用前确认</string> + <string name="portforward_list_empty">点击「菜单」来创建端口转发</string> + <string name="portforward_edit">编辑转发端口</string> + <string name="portforward_delete">删除端口转发</string> + <string name="prompt_nickname">昵称:</string> + <string name="prompt_nickname_hint_pubkey">我的工作密钥</string> + <string name="prompt_source_port">源端口:</string> + <string name="prompt_destination">目标端口:</string> + <string name="prompt_old_password">旧密码:</string> + <string name="prompt_password">新密码:</string> + <string name="prompt_again">确认新密码</string> + <string name="prompt_type">转发类型</string> + <string name="prompt_password_can_be_blank">注意:密码可以为空</string> + <string name="prompt_bits">位数:</string> + <string name="prompt_pubkey_password">密钥「%1$s」的密码</string> + <string name="prompt_allow_agent_to_use_key">允许远程主机使用\'%1$s\'密钥?</string> + <string name="host_verification_failure_warning_header">警告:远程主机身份标识已经改变</string> + <string name="host_verification_failure_warning">可能某人正在做非善意的事情\n可能有人正在偷听你的会话(中间人攻击)\n但也许仅仅是主密匙(host key)已被更改,你确信如此?</string> + <string name="prompt_host_disconnected">主机已经断开。\n是否关闭本次对话?</string> + <string name="prompt_continue_connecting">是否要继续连接?</string> + <string name="host_authenticity_warning">主机「%1$s」的验证无法建立</string> + <string name="host_fingerprint">主机 %1$s 密钥指纹是 %2$s</string> + <string name="alert_passwords_do_not_match_msg">密码不匹配!</string> + <string name="alert_wrong_password_msg">密码错误</string> + <string name="alert_key_corrupted_msg">私钥似乎已破坏</string> + <string name="alert_sdcard_absent">没有插入SD卡!</string> + <string name="button_add">添加</string> + <string name="button_change">修改</string> + <string name="button_generate">生成密钥</string> + <string name="button_resize">改变窗口大小</string> + <string name="alert_disconnect_msg">连接中断</string> + <string name="pref_emulation_category">模拟终端</string> + <string name="pref_emulation_title">仿真模式</string> + <string name="pref_emulation_summary">设置使用PTY连接时的终端模式</string> + <string name="pref_scrollback_title">回滚长度</string> + <string name="pref_scrollback_summary">在内存中为每个控制台保留的回滚缓存长度</string> + <string name="pref_ui_category">用户界面</string> + <string name="pref_rotation_title">循环模式</string> + <string name="pref_rotation_summary">当键盘打开或关闭时屏幕如何旋转(水平或竖直)</string> + <string name="pref_fullscreen_title">全屏</string> + <string name="pref_fullscreen_summary">处于控制台时隐藏状态栏</string> + <string name="pref_memkeys_title">在内存中记录密钥</string> + <string name="pref_memkeys_summary">保留解锁的密匙于内存中直到后台服务停止</string> + <string name="pref_update_title">检查更新</string> + <string name="pref_update_summary">设置检查ConnectBot更新的最大频率</string> + <string name="pref_conn_persist_title">保持联机</string> + <string name="pref_conn_persist_summary">切换到后台时强制保持连接</string> + <string name="pref_keymode_title">目录快捷方式</string> + <string name="pref_keymode_summary">选择如何使用 Alt 代表 /,Shift 代表 Tab</string> + <string name="pref_camera_title">摄像快捷键</string> + <string name="pref_camera_summary">选择照相键按下时触发的快捷功能</string> + <string name="pref_keepalive_title">保持屏幕唤醒</string> + <string name="pref_keepalive_summary">终端运行时禁止屏幕休眠</string> + <string name="pref_wifilock_title">保持WI-FI激活</string> + <string name="pref_wifilock_summary">会话运行时禁止Wi-Fi关闭</string> + <string name="pref_bumpyarrows_title">触摸反馈</string> + <string name="pref_bumpyarrows_summary">轨迹球发出模拟方向键时振动; (对滞后连接特别有用)</string> + <string name="pref_bell_category">终端响铃</string> + <string name="pref_bell_title">响铃</string> + <string name="pref_bell_volume_title">铃声音量</string> + <string name="pref_bell_vibrate_title">响铃时振动</string> + <string name="pref_bell_notification_title">背景通知</string> + <string name="pref_bell_notification_summary">当终端在后台响铃时发出通知</string> + <string name="list_keymode_right">使用右边键盘</string> + <string name="list_keymode_left">使用左边键盘</string> + <string name="list_keymode_none">禁用</string> + <string name="list_pubkeyids_none">不使用密匙</string> + <string name="list_pubkeyids_any">使用解锁密匙</string> + <string name="hostpref_nickname_title">昵称</string> + <string name="hostpref_color_title">颜色类型</string> + <string name="hostpref_fontsize_title">字型大小 (pt)</string> + <string name="hostpref_pubkeyid_title">使用公钥验证</string> + <string name="hostpref_authagent_title">使用 SSH 认证</string> + <string name="hostpref_postlogin_title">登录后自动运行</string> + <string name="hostpref_postlogin_summary">登录后在远程服务器上自动运行命令</string> + <string name="hostpref_compression_title">压缩</string> + <string name="hostpref_compression_summary">此选项对低速网络会有帮助</string> + <string name="hostpref_wantsession_title">开始Shell会话</string> + <string name="hostpref_wantsession_summary">仅仅对端口转发禁用偏好设置</string> + <string name="hostpref_stayconnected_title">保持连接</string> + <string name="hostpref_stayconnected_summary">断线重连</string> + <string name="hostpref_delkey_title">DEL键</string> + <string name="hostpref_delkey_summary">按下DEL键时发送给服务器的键值</string> + <string name="hostpref_encoding_title">编码</string> + <string name="hostpref_encoding_summary">主机的字符编码</string> + <string name="hostpref_connection_category">连接设置</string> + <string name="hostpref_username_title">用户名</string> + <string name="hostpref_hostname_title">主机</string> + <string name="hostpref_port_title">端口</string> + <string name="bind_never">尚未连接</string> + <string name="bind_minutes">已连接 %1$s 分钟</string> + <string name="bind_hours">已连接 %1$s 小时</string> + <string name="bind_days">已连接 %1$s 天</string> + <string name="console_copy_done">已复制%1$d位</string> + <string name="console_copy_start">点击拖动\n或使用触摸板\n来选择要复制的区域</string> + <string name="console_menu_close">关闭</string> + <string name="console_menu_copy">复制</string> + <string name="console_menu_paste">粘贴</string> + <string name="console_menu_portforwards">端口转发</string> + <string name="console_menu_resize">指定大小</string> + <string name="console_menu_urlscan">URL 地址扫描</string> + <string name="button_yes">确认</string> + <string name="button_no">取消</string> + <string name="portforward_local">本地</string> + <string name="portforward_remote">远端</string> + <string name="portforward_dynamic">动态套接字(SOCKS)</string> + <string name="portforward_pos">创建端口转发</string> + <string name="portforward_done">创建端口转发成功</string> + <string name="portforward_problem">创建端口转发失败,检查你选择的端口是否小于1024或该端口已被占用</string> + <string name="portforward_menu_add">添加端口转发</string> + <string name="hint_userhost">用户名\@主机名</string> + <string name="list_format_error">使用%1$s格式</string> + <string name="format_username">用户名</string> + <string name="format_hostname">主机名</string> + <string name="format_port">端口</string> + <string name="list_menu_pubkeys">管理公钥</string> + <string name="list_menu_sortcolor">按颜色排序</string> + <string name="list_menu_sortname">按名称排序</string> + <string name="list_menu_settings">设置</string> + <string name="list_host_disconnect">断开连接</string> + <string name="list_host_edit">编辑主机</string> + <string name="list_host_portforwards">编辑端口转发</string> + <string name="list_host_delete">删除主机</string> + <string name="list_host_empty">使用下面的快速连接框连接主机</string> + <string name="list_rotation_default">默认</string> + <string name="list_rotation_land">强制横屏显示</string> + <string name="list_rotation_port">强制竖屏显示</string> + <string name="list_rotation_auto">自动</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A 然后 Space</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc 键</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">无</string> + <string name="list_delkey_backspace">退格键</string> + <string name="list_delkey_del">删除</string> + <string name="delete_message">确定要删除\'%1$s\'吗?</string> + <string name="delete_pos">是,删除</string> + <string name="delete_neg">取消</string> + <string name="wizard_agree">同意</string> + <string name="wizard_next">下一页</string> + <string name="wizard_back">返回</string> + <string name="terminal_no_hosts_connected">当前没有连接主机</string> + <string name="terminal_connecting">正在通过%3$s连接到 %1$s:%2$d</string> + <string name="terminal_sucess">验证主机 %1$s 键值: %2$s</string> + <string name="terminal_failed">主机验证失败</string> + <string name="terminal_using_s2c_algorithm">服务器到客户端算法:%1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">客户端到服务器算法:%1$s %2$s</string> + <string name="terminal_using_algorithm">使用算法:%1$s %2$s</string> + <string name="terminal_auth">尝试验证</string> + <string name="terminal_auth_pass">尝试进行用户口令认证</string> + <string name="terminal_auth_pass_fail">密码验证失败</string> + <string name="terminal_auth_pubkey_any">尝试使用保存在内存中的公匙进行用户认证</string> + <string name="terminal_auth_pubkey_invalid">所选公钥失效,请在主机中重新选择</string> + <string name="terminal_auth_pubkey_specific">正在以公钥认证方式认证所指定的公钥</string> + <string name="terminal_auth_pubkey_fail">公钥%1$s认证失败</string> + <string name="terminal_auth_ki">尝试键盘交互式认证</string> + <string name="terminal_auth_ki_fail">键盘交互式认证失败</string> + <string name="terminal_auth_fail">[该主机不支持用户口令认证或键盘交互式认证]</string> + <string name="terminal_no_session">由于主机设定不起动该会话</string> + <string name="terminal_enable_portfoward">启用端口转发:%1$s</string> + <string name="local_shell_unavailable">失败! 本地Shell在该手机上不可用</string> + <string name="notification_text">%1$s 需要你的注意</string> + <string name="no">不</string> + <string name="with_confirmation">需要确认</string> + <string name="yes">确定</string> + <string name="exceptions_submit_message">ConnectBot上次运行时出现异常, 是否提交报告至ConnectBot开发者?</string> + <string name="menu_colors_reset">重置</string> + <string name="app_is_running">ConnectBot 正在运行</string> + <string name="color_red">红色</string> + <string name="color_green">绿色</string> + <string name="color_blue">蓝色</string> + <string name="color_gray">灰色</string> + <string name="colors_fg">前景色:</string> + <string name="color_bg">背景色:</string> + <string name="image_description_connected">已连接。</string> + <string name="image_description_key_is_locked">密钥已锁。</string> + <string name="image_description_toggle_control_character">切换控制字符。</string> + <string name="image_description_send_escape_character">发送转义字符。</string> + <string name="image_description_show_keyboard">显示键盘。</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-zh-rHK/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values-zh-rTW/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,216 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_desc">簡單、強大、開放原始碼的SSH用戶端</string> + <string name="service_desc">管理SSH連線及載入公鑰</string> + <string name="title_hosts_list">主機列表</string> + <string name="title_pubkey_list">公鑰</string> + <string name="title_port_forwards_list">連接埠轉址</string> + <string name="title_host_editor">編輯主機資訊</string> + <string name="title_help">說明</string> + <string name="title_colors">顏色</string> + <string name="resolve_connect">連線</string> + <string name="resolve_entropy">收集用戶熵</string> + <string name="menu_insert">新增主機</string> + <string name="menu_delete">刪除主機</string> + <string name="menu_preferences">設定</string> + <string name="help_intro">請在下面主題中選擇一個以查看更多內容。</string> + <string name="help_about">關於ConnectBot</string> + <string name="help_keyboard">鍵盤</string> + <string name="pubkey_generate">產生</string> + <string name="pubkey_import">匯入</string> + <string name="pubkey_delete">刪除金鑰</string> + <string name="pubkey_gather_entropy">正在收集用戶熵</string> + <string name="pubkey_touch_prompt">觸摸方框來收集隨機數:%1$d%完成</string> + <string name="pubkey_touch_hint">由於金鑰產生的時候需要隨機資訊,請在下面的方框中隨意移動您的手指。</string> + <string name="pubkey_generating">正在產生金鑰對</string> + <string name="pubkey_copy_private">複製私鑰</string> + <string name="pubkey_copy_public">複製公鑰</string> + <string name="pubkey_list_empty">按「選單」鍵來建立\n或匯入金鑰對。</string> + <string name="pubkey_unknown_format">未知格式</string> + <string name="pubkey_change_password">更改密碼</string> + <string name="pubkey_list_pick">從/sdcard選擇</string> + <string name="pubkey_import_parse_problem">匯入私鑰的時候發生問題</string> + <string name="pubkey_unlock">未鎖定金鑰</string> + <string name="pubkey_failed_add">驗證失敗,錯誤的的金鑰密碼「%1$s」</string> + <string name="pubkey_memory_load">讀取到記憶體中</string> + <string name="pubkey_memory_unload">從記憶體中移除</string> + <string name="pubkey_load_on_start">在啟動的時候載入金鑰</string> + <string name="pubkey_confirm_use">使用前確認</string> + <string name="portforward_list_empty">按「選單」鍵來建立連接埠轉址</string> + <string name="portforward_edit">編輯連接埠轉址</string> + <string name="portforward_delete">刪除連接埠轉址</string> + <string name="prompt_nickname">暱稱:</string> + <string name="prompt_nickname_hint_pubkey">我的工作金鑰</string> + <string name="prompt_source_port">來源連接埠:</string> + <string name="prompt_destination">目的連接埠:</string> + <string name="prompt_old_password">舊密碼:</string> + <string name="prompt_password">密碼:</string> + <string name="prompt_again">(再輸入一遍密碼)</string> + <string name="prompt_type">轉址類型:</string> + <string name="prompt_password_can_be_blank">注意:密碼可以為空</string> + <string name="prompt_bits">位數:</string> + <string name="prompt_pubkey_password">公鑰「%1$s」的密碼</string> + <string name="prompt_allow_agent_to_use_key">允許遠端主機來\n使用金鑰 \'%1$s\'?</string> + <string name="host_verification_failure_warning_header">警告:遠端主機的鑑別已經變更!</string> + <string name="host_verification_failure_warning">可能某人正在做非善意的事情!\n可能有人正在側錄您的連線(中間攻擊法)\n但也許僅僅是主機金鑰已被變更,您確信如此?</string> + <string name="prompt_host_disconnected">主機已經中斷。\n是否關閉本次連線階段?</string> + <string name="prompt_continue_connecting">是否要繼續連線?</string> + <string name="host_authenticity_warning">主機「%1$s」的驗證無法建立</string> + <string name="host_fingerprint">主機 %1$s 金鑰指紋是 %2$s</string> + <string name="alert_passwords_do_not_match_msg">密碼不符!</string> + <string name="alert_wrong_password_msg">錯誤的密碼!</string> + <string name="alert_key_corrupted_msg">私鑰已經損壞!</string> + <string name="alert_sdcard_absent">沒有插入SD卡!</string> + <string name="button_add">新增</string> + <string name="button_change">變更</string> + <string name="button_generate">產生金鑰</string> + <string name="button_resize">調整大小</string> + <string name="alert_disconnect_msg">連線中斷</string> + <string name="pref_emulation_category">終端模擬器</string> + <string name="pref_emulation_title">終端機類型</string> + <string name="pref_emulation_summary">設置使用PTY連接時的終端模式</string> + <string name="pref_scrollback_title">回溯記憶體大小</string> + <string name="pref_scrollback_summary">在記憶體中為每個控制台保留的回溯緩衝大小</string> + <string name="pref_ui_category">使用者介面</string> + <string name="pref_rotation_title">螢幕旋轉模式</string> + <string name="pref_rotation_summary">當鍵盤視窗出現或隱藏時要如何改變螢幕顯示</string> + <string name="pref_fullscreen_title">全螢幕</string> + <string name="pref_fullscreen_summary">當在控制台時隱藏狀態列</string> + <string name="pref_memkeys_title">將金鑰儲存在記憶體</string> + <string name="pref_memkeys_summary">保持記憶體中的金鑰是解鎖狀態,直到背景服務結束</string> + <string name="pref_update_title">檢查更新</string> + <string name="pref_update_summary">將ConnectBot的檢查更新頻率設為最大</string> + <string name="pref_conn_persist_title">保持連線</string> + <string name="pref_conn_persist_summary">在背景執行時仍保持連線狀態</string> + <string name="pref_keymode_title">快捷鍵</string> + <string name="pref_keymode_summary">選擇如何使用Alt來叫出\'/\'和用Shift呼叫Tab</string> + <string name="pref_camera_title">照相快捷鍵</string> + <string name="pref_camera_summary">選擇當照相按鈕按下時將要觸發的快捷鍵</string> + <string name="pref_keepalive_title">保持螢幕亮度</string> + <string name="pref_keepalive_summary">當在執行控制台時不關閉螢幕</string> + <string name="pref_wifilock_title">保持Wi-Fi連線</string> + <string name="pref_wifilock_summary">連線階段未結束前,避免Wi-Fi關閉</string> + <string name="pref_bumpyarrows_title">觸覺方向鍵</string> + <string name="pref_bumpyarrows_summary">當用軌跡球發出模擬方向鍵時振動; 對延遲連線特別有用</string> + <string name="pref_bell_category">終端鈴聲</string> + <string name="pref_bell_title">響鈴</string> + <string name="pref_bell_volume_title">鈴聲音量</string> + <string name="pref_bell_vibrate_title">振動同時響鈴</string> + <string name="pref_bell_notification_title">背景通知</string> + <string name="pref_bell_notification_summary">當背景終端響鈴時發出通知。</string> + <string name="list_keymode_right">使用右側按鍵</string> + <string name="list_keymode_left">使用左側按鍵</string> + <string name="list_keymode_none">停用</string> + <string name="list_pubkeyids_none">不使用公鑰</string> + <string name="list_pubkeyids_any">使用解鎖金鑰</string> + <string name="hostpref_nickname_title">暱稱</string> + <string name="hostpref_color_title">顏色類型</string> + <string name="hostpref_fontsize_title">字型大小 (pt)</string> + <string name="hostpref_pubkeyid_title">使用公鑰驗證</string> + <string name="hostpref_authagent_title">使用 SSH 認證</string> + <string name="hostpref_postlogin_title">登入後自動執行</string> + <string name="hostpref_postlogin_summary">每次驗證後在遠端伺服器上執行的命令</string> + <string name="hostpref_compression_title">壓縮</string> + <string name="hostpref_compression_summary">此選項對低速網路會有幫助</string> + <string name="hostpref_wantsession_title">開始Shell連線階段</string> + <string name="hostpref_wantsession_summary">僅僅連接埠轉址停用偏好設定</string> + <string name="hostpref_stayconnected_title">保持連線</string> + <string name="hostpref_stayconnected_summary">斷線後與主機重新連線</string> + <string name="hostpref_delkey_title">DEL鍵</string> + <string name="hostpref_delkey_summary">當DEL按下時觸發的按鍵</string> + <string name="hostpref_encoding_title">編碼</string> + <string name="hostpref_encoding_summary">主機的字元編碼</string> + <string name="hostpref_connection_category">連線設定</string> + <string name="hostpref_username_title">使用者名稱</string> + <string name="hostpref_hostname_title">主機</string> + <string name="hostpref_port_title">連接埠</string> + <string name="bind_never">從未連線</string> + <string name="bind_minutes">已連接 %1$s 分鐘</string> + <string name="bind_hours">已連接 %1$s 小時</string> + <string name="bind_days">已連接 %1$s 天</string> + <string name="console_copy_done">複製 %1$d 位元組到剪貼簿</string> + <string name="console_copy_start">滑動手指\n或使用軌跡球\n選擇要複製的區域</string> + <string name="console_menu_close">關閉</string> + <string name="console_menu_copy">複製</string> + <string name="console_menu_paste">貼上</string> + <string name="console_menu_portforwards">連接埠轉址</string> + <string name="console_menu_resize">字體大小</string> + <string name="console_menu_urlscan">URL掃描</string> + <string name="button_yes">是</string> + <string name="button_no">否</string> + <string name="portforward_local">本機</string> + <string name="portforward_remote">遠端</string> + <string name="portforward_dynamic">動態(SOCKS)</string> + <string name="portforward_pos">建立連接埠轉址</string> + <string name="portforward_done">成功建立連接埠轉址</string> + <string name="portforward_problem">新增連接埠時發生問題,可能您使用1024以下的埠或是埠被佔用?</string> + <string name="portforward_menu_add">新增連接埠轉址</string> + <string name="hint_userhost">使用者名稱\@主機名稱</string> + <string name="list_format_error">使用%1$s格式</string> + <string name="format_username">使用者名稱</string> + <string name="format_hostname">主機名稱</string> + <string name="format_port">連接埠</string> + <string name="list_menu_pubkeys">管理金鑰</string> + <string name="list_menu_sortcolor">按顏色排序</string> + <string name="list_menu_sortname">按名字排序</string> + <string name="list_menu_settings">設定</string> + <string name="list_host_disconnect">中斷連線</string> + <string name="list_host_edit">編輯主機</string> + <string name="list_host_portforwards">編輯連接埠轉址</string> + <string name="list_host_delete">刪除主機</string> + <string name="list_host_empty">使用下面的快速連接框連接主機</string> + <string name="list_rotation_default">預設值</string> + <string name="list_rotation_land">強制橫屏顯示</string> + <string name="list_rotation_port">強制竪屏顯示</string> + <string name="list_rotation_auto">自動</string> + <string name="list_hwbutton_ctrlaspace">Ctrl+A 然後 Space</string> + <string name="list_hwbutton_ctrla">Ctrl+A</string> + <string name="list_hwbutton_esc">Esc</string> + <string name="list_hwbutton_esc_a">Esc+A</string> + <string name="list_hwbutton_none">無</string> + <string name="list_delkey_backspace">退格</string> + <string name="list_delkey_del">刪除</string> + <string name="delete_message">您確定要刪除 鑰 \'%1$s\'</string> + <string name="delete_pos">是,刪除</string> + <string name="delete_neg">取消</string> + <string name="wizard_agree">同意</string> + <string name="wizard_next">下一步</string> + <string name="wizard_back">返回</string> + <string name="terminal_no_hosts_connected">目前沒有已連接主機</string> + <string name="terminal_connecting">連接到 %1$s:%2$d,通過 %3$s</string> + <string name="terminal_sucess">驗證主機 \'%1$s\' 金鑰: %2$s</string> + <string name="terminal_failed">主機驗證失敗</string> + <string name="terminal_using_s2c_algorithm">伺服器到用戶端算法:%1$s %2$s</string> + <string name="terminal_using_c2s_algorithm">用戶端到伺服器算法:%1$s %2$s</string> + <string name="terminal_using_algorithm">使用演算法:%1$s %2$s</string> + <string name="terminal_auth">嘗試驗證</string> + <string name="terminal_auth_pass">嘗試 \'password\' 認證</string> + <string name="terminal_auth_pass_fail">認證方法 \'password\' 失敗</string> + <string name="terminal_auth_pubkey_any">嘗試 \'publickey\' 認證暨記憶體中任何公鑰</string> + <string name="terminal_auth_pubkey_invalid">所選擇的公鑰無法使用,請在主機編輯中嘗試重新選擇</string> + <string name="terminal_auth_pubkey_specific">嘗試 \'publickey\' 認證暨指定公鑰</string> + <string name="terminal_auth_pubkey_fail">認證方法 \'password\' 暨金鑰 \'%1$s\' 失敗</string> + <string name="terminal_auth_ki">嘗試 \'keyboard-interactive\' 認證</string> + <string name="terminal_auth_ki_fail">認證方法 \'keyboard-interactive\' 失敗</string> + <string name="terminal_auth_fail">[您的主機不支援 \'password\' 或 \'keyboard-interactive\' 驗證機制。]</string> + <string name="terminal_no_session">因為主機的相關設置,不會啓動會話。</string> + <string name="terminal_enable_portfoward">啓用連接埠轉址:%1$s</string> + <string name="local_shell_unavailable">失敗!此手機本機Shell不可用。</string> + <string name="notification_text">%1$s 需要您的注意。</string> + <string name="no">否</string> + <string name="with_confirmation">已確認過</string> + <string name="yes">是</string> + <string name="exceptions_submit_message">ConnectBot在上次執行時出現異常。請回報給ConnectBot開發者?</string> + <string name="menu_colors_reset">重設</string> + <string name="color_red">紅</string> + <string name="color_green">綠</string> + <string name="color_blue">藍</string> + <string name="color_gray">灰</string> + <string name="colors_fg">前景:</string> + <string name="color_bg">背景:</string> + <string name="image_description_connected">已連線。</string> + <string name="image_description_key_is_locked">金鑰已鎖定。</string> + <string name="image_description_toggle_control_character">切換控制字元</string> + <string name="image_description_send_escape_character">送出escape字元。</string> + <string name="image_description_show_keyboard">顯示鍵盤。</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values/arrays.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string-array name="list_emulation_modes" translatable="false"> + <item>xterm-color</item> + <item>xterm-256color</item> + <item>xterm</item> + <item>vt100</item> + <item>ansi</item> + <item>screen</item> + </string-array> + + <string-array name="list_5250_encryption_modes" translatable="false"> + <item>NONE</item> + <item>SSLv2</item> + <item>SSLv3</item> + <item>TLS</item> + </string-array> + + <string-array name="list_rotation" translatable="false"> + <item>@string/list_rotation_default</item> + <item>@string/list_rotation_land</item> + <item>@string/list_rotation_port</item> + <item>@string/list_rotation_auto</item> + </string-array> + + <string-array name="list_rotation_values" translatable="false"> + <item>Default</item> + <item>Force landscape</item> + <item>Force portrait</item> + <item>Automatic</item> + </string-array> + + <string-array name="list_hwbutton" translatable="false"> + <item>@string/list_hwbutton_ctrl</item> + <item>@string/list_hwbutton_esc</item> + <item>@string/list_hwbutton_tab</item> + <item>@string/list_hwbutton_screen_capture</item> + <item>@string/list_hwbutton_ctrlaspace</item> + <item>@string/list_hwbutton_ctrla</item> + <item>@string/list_hwbutton_esc_a</item> + <item>@string/list_hwbutton_monitor</item> + <item>@string/list_hwbutton_soft_function_keys</item> + <item>@string/list_hwbutton_increase_fontsize</item> + <item>@string/list_hwbutton_decrease_fontsize</item> + <item>@string/list_hwbutton_none</item> + </string-array> + + <!-- must match PreferenceConstants --> + <string-array name="list_hwbutton_values" translatable="false"> + <item>CTRL</item> + <item>Esc</item> + <item>Tab</item> + <item>Screen Capture</item> + <item>Ctrl+A then Space</item> + <item>Ctrl+A</item> + <item>Esc+A</item> + <item>Monitor Key</item> + <item>Soft Function Keypad</item> + <item>Increase Font Size</item> + <item>Decrease Font Size</item> + <item>None</item> + </string-array> + + <string-array name="list_colors" translatable="false"> + <item>@string/color_red</item> + <item>@string/color_green</item> + <item>@string/color_blue</item> + <item>@string/color_gray</item> + </string-array> + + <string-array name="list_color_values" translatable="false"> + <item>red</item> + <item>green</item> + <item>blue</item> + <item>gray</item> + </string-array> + + <string-array name="list_keymode" translatable="false"> + <item>@string/list_keymode_right</item> + <item>@string/list_keymode_left</item> + <item>@string/list_keymode_none</item> + </string-array> + + <string-array name="list_keymode_values" translatable="false"> + <item>Use right-side keys</item> + <item>Use left-side keys</item> + <item>none</item> + </string-array> + + <string-array name="list_pubkeyids" translatable="false"> + <item>@string/list_pubkeyids_none</item> + <item>@string/list_pubkeyids_any</item> + </string-array> + + <string-array name="list_pubkeyids_value" translatable="false"> + <item>-2</item> + <item>-1</item> + </string-array> + + <string-array name="list_authagent" translatable="false"> + <item>@string/no</item> + <item>@string/with_confirmation</item> + <item>@string/yes</item> + </string-array> + + <string-array name="list_authagent_values" translatable="false"> + <item>no</item> + <item>confirm</item> + <item>yes</item> + </string-array> + + <string-array name="list_portforward_types" translatable="false"> + <item>@string/portforward_local</item> + <item>@string/portforward_remote</item> + <item>@string/portforward_dynamic</item> + </string-array> + + <string-array name="list_wizard_topics" translatable="false"> + <item>About</item> + <item>Hints</item> + <item>PhysicalKeyboard</item> + <item>5250Keys</item> + <item>ScreenGestures</item> + <item>VirtualKeyboard</item> + </string-array> + + <string-array name="list_delkey" translatable="false"> + <item>@string/list_delkey_del</item> + <item>@string/list_delkey_backspace</item> + </string-array> + + <string-array name="list_delkey_values" translatable="false"> + <item>del</item> + <item>backspace</item> + </string-array> + + <string-array name="file_dialog" translatable="false"> + <item>@string/pref_file_dialog_builtin</item> + <item>OI File Manager</item> + <item>AndExplorer</item> + </string-array> + + <string-array name="file_dialog_values" translatable="false"> + <item>built-in</item> + <item>OI</item> + <item>AE</item> + </string-array> + + <string-array name="list_custom_keymap" translatable="false"> + <item>@string/pref_custom_keymap_disabled</item> + <item>@string/pref_custom_keymap_full</item> + <item>ASUS Transformer Pad Series Mobile Dock</item> + <item>Samsung Captivate Glide (SGH-i927)</item> + <item>Samsung Captivate Glide (SGH-i927) ICS</item> + <item>Sony Ericsson Xperia (mini) pro</item> + </string-array> + + <string-array name="list_custom_keymap_values" translatable="false"> + <item>none</item> + <item>full</item> + <item>asus_tf</item> + <item>sgh_i927</item> + <item>sgh_i927_ics</item> + <item>se_xppro</item> + </string-array> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values/notrans.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources> + <string name="app_name" translatable="false">510 ConnectBot</string> + <string name="copyright_info" translatable="false">Copyright © 2014 by 510 Software Group. Release under the GPLv3 or later.</string> + <string name="copyright_location" translatable="false">You can view the full text of the license at https://www.gnu.org/licenses/gpl.txt</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values/strings.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,705 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="app_desc">"Simple, powerful, open-source SSH client."</string> + <string name="service_desc">"Maintains SSH connections and loaded pubkeys"</string> + <string name="auth_agent_service_desc">"Acts as an ssh-agent for other Android Apps on the device"</string> + + <string name="ssh_agent_permission_label">use SSH keys stored in your SSH Agent</string> + <string name="ssh_agent_permission_desc">Allows the application to authenticate SSH transactions using your private keys stored in ConnectBot. + VERY DANGEROUS if used by a malicious application.</string> + + <!-- Window title for the Host List --> + <string name="title_hosts_list">"Hosts"</string> + <!-- Window title for the Pubkeys List --> + <string name="title_pubkey_list">"Pubkeys"</string> + <!-- Window title for the Port Forwards List --> + <string name="title_port_forwards_list">"Port forwards"</string> + <!-- Window title when editing host details --> + <string name="title_host_editor">"Edit Host"</string> + <!-- Window title for Help index --> + <string name="title_help">"Help"</string> + <!-- Window title for color list editing screen --> + <string name="title_colors">"Colors"</string> + + <string name="resolve_connect">"Connect"</string> + <!-- Menu selection where user must move finger randomly over an area to gather entropy (collect random bits) --> + <string name="resolve_entropy">"Gather Entropy"</string> + + <string name="menu_insert">"Add Host"</string> + <string name="menu_delete">"Delete Host"</string> + <string name="menu_preferences">"Preferences"</string> + + <string name="help_intro">"Please select a topic below for more information on a particular subject."</string> + <string name="help_about">"About ConnectBot"</string> + <string name="help_keyboard">"Keyboard"</string> + + <string name="pubkey_generate">"Generate"</string> + <string name="pubkey_import">"Import"</string> + <string name="pubkey_delete">"Delete key"</string> + <!-- Dialog title when user must move finger randomly over an area to gather entropy (collect random bits) --> + <string name="pubkey_gather_entropy">"Gathering Entropy"</string> + <string name="pubkey_touch_prompt">"Touch this box to gather randomness: %1$d%% done"</string> + <string name="pubkey_touch_hint">"In order to assure randomness during the key generation, move your finger randomly over the box below."</string> + <string name="pubkey_generating">"Generating key pair…"</string> + <string name="pubkey_copy_private">"Copy private key"</string> + <string name="pubkey_copy_public">"Copy public key"</string> + <!-- Note that the '\n' just splits lines, so it's actually "create or import" --> + <string name="pubkey_list_empty">"Tap \"Menu\" to create"\n"or import key pairs."</string> + <string name="pubkey_unknown_format">"Unknown format"</string> + <string name="pubkey_change_password">"Change password"</string> + <string name="pubkey_list_pick">"Pick from /sdcard"</string> + <string name="pubkey_import_parse_problem">"Problem parsing imported private key"</string> + <string name="pubkey_unlock">"Unlock key"</string> + <string name="pubkey_failed_add">"Bad password for key '%1$s'. Authentication failed."</string> + <string name="pubkey_memory_load">"Load into memory"</string> + <string name="pubkey_memory_unload">"Unload from memory"</string> + <string name="pubkey_load_on_start">"Load key on start"</string> + <!-- Pubkey preference asking user whether the key use should be confirmed via prompt before it can be used for authentication --> + <string name="pubkey_confirm_use">"Confirm before use"</string> + + <!-- Note that the '\n' splits lines, so it's actually "create port forwards" --> + <string name="portforward_list_empty">"Tap \"Menu\" to create"\n"port forwards."</string> + <string name="portforward_edit">"Edit port forward"</string> + <string name="portforward_delete">"Delete port forward"</string> + + <string name="prompt_nickname">"Nickname:"</string> + <!-- An example string that could be used as a nickname for a pubkey. --> + <string name="prompt_nickname_hint_pubkey">"My work key"</string> + <!-- The source TCP port for port forwards. --> + <string name="prompt_source_port">"Source port:"</string> + <!-- The "host:port" combination used for port forward destinations. --> + <string name="prompt_destination">"Destination:"</string> + <string name="prompt_old_password">"Old password:"</string> + <string name="prompt_password">"Password:"</string> + <!-- Added after a "Password:" prompt to indicate user needs to confirm entry. --> + <string name="prompt_again">"(again)"</string> + <!-- Label for the user to select port forward type. --> + <string name="prompt_type">"Type:"</string> + <string name="prompt_password_can_be_blank">"Note: password can be blank"</string> + <!-- Prompt for the size of the private key in bits. --> + <string name="prompt_bits">"Bits:"</string> + + <!-- Prompt for the password to unlock a certain pubkey. --> + <string name="prompt_pubkey_password">"Password for key '%1$s'"</string> + + <!-- Prompt for whether to allow SSH Authentication Agent to use the specified key. Note that the '\n' means split the line so it's actually "host to use key" --> + <string name="prompt_allow_agent_to_use_key">"Allow remote host to"\n"use key '%1$s'?"</string> + + <!-- The header of the warning a user gets when the host key has changed. Note that this can be a very serious attack, so we try to be as "loud" to the user as possible. --> + <string name="host_verification_failure_warning_header">"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!"</string> + <!-- The body of the warning a user gets when the host key has changed. Note that this can be a very serious attack, so we try to be as "loud" to the user as possible. --> + <string name="host_verification_failure_warning">"IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"\n"Someone could be eavesdropping on you right now (man-in-the-middle attack)!"\n"It is also possible that the host key has just been changed."</string> + + <!-- Prompt user gets when the remote host has disconnected unexpectedly. --> + <string name="prompt_host_disconnected">"Host has disconnected."\n"Close session?"</string> + <!-- Prompt user must answer yes or no to when the remote host fails verification of encryption fingerprint --> + <string name="prompt_continue_connecting">"Are you sure you want"\n"to continue connecting?"</string> + + <!-- Sent to user when the remote public encryption key fingerprint doesn't match the local database --> + <string name="host_authenticity_warning">"The authenticity of host '%1$s' can't be established."</string> + <!-- First field is encryption algorithm. Second is the actual fingerprint in hex digits --> + <string name="host_fingerprint">"Host %1$s key fingerprint is %2$s"</string> + + <!-- tn5250 strings --> + <string name="host_cert_version">"Version: "</string> + <string name="host_cert_serial">"Serial Number: "</string> + <string name="host_cert_algorithm">"Signature Algorithm: "</string> + <string name="host_cert_issuer">"Issuer: "</string> + <string name="host_cert_from">"Valid From: "</string> + <string name="host_cert_to">"Valid To: "</string> + <string name="host_cert_dn">"Subject DN: "</string> + <string name="host_cert_publickey">"Public Key: "</string> + <string name="host_certificate">"The certificate is %1$s"</string> + <string name="prompt_accept_certificate">"Unknown Certificate - Do you accept it?"</string> + <string name="prompt_save_certificate">"Do you want to save this certificate?"</string> + <string name="prompt_sys_request">"Enter sys-request string"</string> + + <string name="alert_passwords_do_not_match_msg">"Passwords do not match!"</string> + <string name="alert_wrong_password_msg">"Wrong password!"</string> + <string name="alert_key_corrupted_msg">"Private key appears corrupt!"</string> + <string name="alert_sdcard_absent">"SD card is not inserted!"</string> + + <!-- Add a new item (e.g., host or pubkey) to the list. --> + <string name="button_add">"Add"</string> + <!-- Change an existing item's (e.g., host or pubkey) details. --> + <string name="button_change">"Change"</string> + <!-- Button that begins the generation of a public key pair. --> + <string name="button_generate">"Generate Key"</string> + <!-- Button that resizes the screen to the user-specified dimensions. --> + <string name="button_resize">"Resize"</string> + <!-- Button that resets to default size --> + <string name="button_resize_reset">"Default size"</string> + + <string name="alert_disconnect_msg">"Connection Lost"</string> + + + <!-- The category title for terminal emulation preferences. --> + <string name="pref_emulation_category">"Terminal emulation"</string> + + <!-- Name for the emulation terminal type preference. --> + <string name="pref_emulation_title">"Emulation mode"</string> + <!-- Description of the emulation terminal type preference. --> + <string name="pref_emulation_summary">"Terminal emulation mode to use for PTY connections"</string> + + <!-- Name for the scrollback size preference --> + <string name="pref_scrollback_title">"Scrollback size"</string> + <!-- Description of the scrollback size preference --> + <string name="pref_scrollback_summary">"Size of scrollback buffer to keep in memory for each console"</string> + + <!-- The category title for user interface preferences --> + <string name="pref_ui_category">"User interface"</string> + + <!-- Name for the rotation mode preference --> + <string name="pref_rotation_title">"Rotation mode"</string> + <!-- Summary for the rotation mode preference --> + <string name="pref_rotation_summary">"How to change rotation when keyboard popped in/out"</string> + + <!-- Name for the full screen preference --> + <string name="pref_fullscreen_title">"Full screen"</string> + <!-- Summary for the full screen preference --> + <string name="pref_fullscreen_summary">"Start terminal in full screen mode"</string> + + <!-- Name for the shifted numbers are f-keys preference --> + <string name="pref_shiftfkeys_title">"Shift+num are F-keys"</string> + <!-- Summary for the shifted numbers are f-keys preference --> + <string name="pref_shiftfkeys_summary">"On hardware keyboards, number keys send F1-F10 with shift"</string> + + <!-- Name for the ctrl'ed numbers are f-keys preference --> + <string name="pref_ctrlfkeys_title">"Ctrl+num are F-keys"</string> + <!-- Summary for the ctrl'ed numbers are f-keys preference --> + <string name="pref_ctrlfkeys_summary">"On software keyboards, number keys send F1-F10 with ctrl"</string> + + <!-- Name for the memorize keys preference --> + <string name="pref_memkeys_title">"Remember keys in memory"</string> + <!-- Summary for the memorize keys preference --> + <string name="pref_memkeys_summary">"Keep unlocked keys in memory until backend service is terminated"</string> + + <!-- Name for the update check preference --> + <string name="pref_update_title">"Update check"</string> + <!-- Summary for the update check preference --> + <string name="pref_update_summary">"Set the maximum frequency to check for ConnectBot updates"</string> + + <!-- Name for the preference that forces the service to stay running in the background.--> + <string name="pref_conn_persist_title">"Persist connections"</string> + <!-- Summary for the preference that forces the service to stay running in the background. --> + <string name="pref_conn_persist_summary">"Force connections to stay connected while in background"</string> + + <!-- Name for the keyboard shortcuts preference --> + <string name="pref_keymode_title">"Directory shortcuts"</string> + <!-- Summary for the keyboard shortcuts preference --> + <string name="pref_keymode_summary">"Select how to use Alt for '/' and Shift for Tab"</string> + + <!-- Name for the camera shortcut usage preference --> + <string name="pref_camera_title">"Camera button"</string> + <string name="pref_camera_summary">"Action triggered by pressing the camera button"</string> + + <!-- Name for the volup shortcut usage preference --> + <string name="pref_volup_title">"Volume up button"</string> + <string name="pref_volup_summary">"Action triggered by pressing the volume up button"</string> + + <!-- Name for the volup shortcut usage preference --> + <string name="pref_voldn_title">"Volume down button"</string> + <string name="pref_voldn_summary">"Action triggered by pressing the volume down button"</string> + + <!-- Name for the search shortcut usage preference --> + <string name="pref_search_title">"Search button"</string> + <string name="pref_search_summary">"Action triggered by pressing the search button"</string> + + <!-- Name for the ptt shortcut usage preference --> + <string name="pref_ptt_title">"PTT (L2) button"</string> + <string name="pref_ptt_summary">"Action triggered by pressing the ptt button"</string> + + <!-- Name for the keep screen on preference --> + <string name="pref_keepalive_title">"Keep screen awake"</string> + <!-- Summary for the camera shortcut usage preference --> + <string name="pref_keepalive_summary">"Prevent the screen from turning off when working in a console"</string> + + <!-- Name for the Wi-Fi lock preference --> + <string name="pref_wifilock_title">"Keep Wi-Fi active"</string> + <!-- Summary for the Wi-Fi lock preference --> + <string name="pref_wifilock_summary">"Prevent Wi-Fi from turning off when a session is active"</string> + + <!-- Name for the haptic feedback (bumpy arrow) preference --> + <string name="pref_bumpyarrows_title">"Bumpy arrows"</string> + <!-- Summary for the haptic feedback (bumpy arrow) preference --> + <string name="pref_bumpyarrows_summary">"Vibrate when sending arrow keys from trackball; useful for laggy connections"</string> + + <!-- Category title for the Terminal Bell preferences --> + <string name="pref_bell_category">"Terminal bell"</string> + + <!-- Checkbox preference title for the audible terminal bell feature --> + <string name="pref_bell_title">"Audible bell"</string> + + <!-- Title for the slider preference to set the volume --> + <string name="pref_bell_volume_title">"Bell volume"</string> + + <!-- Checkbox preference title for the vibrate on terminal bell feature --> + <string name="pref_bell_vibrate_title">"Vibrate on bell"</string> + + <!-- Checkbox preference title for the receive notifications on terminal bell feature --> + <string name="pref_bell_notification_title">"Background notifications"</string> + <!-- Brief summary of the feature that is enabled when the checkbox preference for the receive notifications on terminal bell feature is checked --> + <string name="pref_bell_notification_summary">"Send notification when a terminal running in the background sounds a bell."</string> + + <!-- Preference selection to indicate use of right side of keyboard for special shortcuts. --> + <string name="list_keymode_right">"Use right-side keys"</string> + <!-- Preference selection to indicate use of left side of keyboard for special shortcuts. --> + <string name="list_keymode_left">"Use left-side keys"</string> + <!-- Preference selection to indicate never to use special shortcut keys. --> + <string name="list_keymode_none">"Disable"</string> + + <!-- Preference to not use pubkeys to authenticate to this host. --> + <string name="list_pubkeyids_none">"Do not use keys"</string> + <!-- Preference to use any pubkey to authenticate to this host. --> + <string name="list_pubkeyids_any">"Use any unlocked key"</string> + + <!-- Host nickname field preference title --> + <string name="hostpref_nickname_title">"Nickname"</string> + + <!-- Host color category preference title --> + <string name="hostpref_color_title">"Color category"</string> + + <!-- Host's default font size when opening the terminal in points (pt) --> + <string name="hostpref_fontsize_title">"Font size (pt)"</string> + + <!-- Host's use fixed size --> + <string name="hostpref_fixed_size_title">"Fixed screen size"</string> + <string name="hostpref_fixed_size_summary">"Compute font size from screen size"</string> + <string name="hostpref_fixed_width_title">"Screen width (columns)"</string> + <string name="hostpref_fixed_height_title">"Screen height (rows)"</string> + + <!-- Host pubkey usage preference title --> + <string name="hostpref_pubkeyid_title">"Use pubkey authentication"</string> + + <!-- Preference title for the SSH Authentication Agent Forwarding for a host connection --> + <string name="hostpref_authagent_title">"Use SSH auth agent"</string> + + <!-- Host post-login automation preference title --> + <string name="hostpref_postlogin_title">"Post-login automation"</string> + <!-- Host post-login automation preference summary --> + <string name="hostpref_postlogin_summary">"Commands to run on remote server once authenticated"</string> + + <!-- Host compression preference title --> + <string name="hostpref_compression_title">"Compression"</string> + <!-- Summary for compression preference --> + <string name="hostpref_compression_summary">"This may help with slower networks"</string> + + <!-- HTTP Proxy preference title --> + <string name="hostpref_httpproxy_title">"Use HTTP Proxy"</string> + <!-- Summary for compression preference --> + <string name="hostpref_httpproxy_summary">"The host:port of an HTTP proxy"</string> + + <!-- Setting for whether we want a session to start up when we connect to a host --> + <string name="hostpref_wantsession_title">"Start shell session"</string> + <!-- Summary for field asking whether a shell session should be started up upon connection or not --> + <string name="hostpref_wantsession_summary">"Disable this preference to only use port forwards"</string> + + <!-- Setting for whether the host should be reconnected to automatically upon disconnect --> + <string name="hostpref_stayconnected_title">"Stay connected"</string> + <!-- Summary for preference asking whether the host should be reconnected to when it disconnects --> + <string name="hostpref_stayconnected_summary">"Try to reconnect to host if disconnected"</string> + + <!-- Setting for what key code is sent to the server when DEL key is pressed. --> + <string name="hostpref_delkey_title">"DEL Key"</string> + <!-- Summary for field asking what key code is sent to the server when DEL key is pressed. --> + <string name="hostpref_delkey_summary">"The key code sent when DEL key is pressed"</string> + + <!-- Host character encoding preference title --> + <string name="hostpref_encoding_title">"Encoding"</string> + <!-- Host character encoding preference summary --> + <string name="hostpref_encoding_summary">"Character encoding for the host"</string> + + <!-- Host preference category title for connection settings --> + <string name="hostpref_connection_category">"Connection settings"</string> + + <!-- Username field title for host editor preference --> + <string name="hostpref_username_title">"Username"</string> + + <!-- Hostname field title for host editor preference --> + <string name="hostpref_hostname_title">"Host"</string> + + <!-- Port field title for host editor preference --> + <string name="hostpref_port_title">"Port"</string> + + <!-- Monitor field title for host editor preference --> + <string name="hostpref_monitor_title">"Monitor Init String"</string> + <string name="hostpref_monitor_summary">"String to pass to the monitor process"</string> + + <!-- Override global emulation (terminal type) host editor preference --> + <string name="hostpref_emulation_title">"Emulation mode"</string> + <string name="hostpref_emulation_summary">"Override global emulation mode / answerback string"</string> + + <!-- 5250 --> + <string name="hostpref_5250_settings">"5250 Settings"</string> + <string name="hostpref_5250_encryption_title">"Host 5250 Encryption"</string> + <string name="hostpref_5250_library_title">"LIBRARY"</string> + <string name="hostpref_5250_menu_title">"MENU"</string> + <string name="hostpref_5250_program_title">"PROGRAM"</string> + + <!-- Host preference category title for x11 forwarding --> + <string name="hostpref_x11_forwarding">"X11 forwarding"</string> + + <!-- Enable x11 forwarding checkbox title for host editor preference --> + <string name="hostpref_wantx11forward_title">"Enable X11 forwarding"</string> + + <!-- Enable x11 forwarding checkbox summary for host editor preference --> + <string name="hostpref_wantx11forward_summary">"Forward X11 sessions to host and port specified below"</string> + + <!-- Hostname field title for x11 forwarding in host editor preference --> + <string name="hostpref_x11host_title">"X11 forwarding host"</string> + + <!-- Port field title for x11 forwarding in host editor preference --> + <string name="hostpref_x11port_title">"X11 forwarding port"</string> + + <!-- Displayed to indicate a host has never been connected to. --> + <string name="bind_never">"Never connected"</string> + <!-- The time that has elapsed since a host was connected to when it has been less than an hour. --> + <string name="bind_minutes">"%1$s minutes ago"</string> + <!-- The time that has elapsed since a host was connected to when it has been less than a day. --> + <string name="bind_hours">"%1$s hours ago"</string> + <!-- The time that has elapsed since a host was connected to when it has been a day or more. --> + <string name="bind_days">"%1$s days ago"</string> + + <!-- Message given when user copies from the terminal. --> + <string name="console_copy_done">"Copied %1$d bytes to clipboard"</string> + <!-- Instructions for how to copy from the terminal. The '\n' entries are to split lines to improve readability and prevent wrapping off the screen. --> + <string name="console_copy_start">"Touch and drag"\n"or use directional pad"\n"to select area to copy"</string> + + <!-- Button to close the disconnected terminal window. --> + <string name="console_menu_close">"Close"</string> + <!-- Button to begin copying from the terminal to the clipboard. --> + <string name="console_menu_copy">"Copy"</string> + <!-- Button to paste from the clipboard to the terminal. --> + <string name="console_menu_paste">"Paste"</string> + <!-- Button that brings user to the Port Forwards List. --> + <string name="console_menu_portforwards">"Port Forwards"</string> + <!-- Button that brings user to the terminal resizing dialog where they can force a size. --> + <string name="console_menu_resize">"Force Size"</string> + <!-- Button that brings up the list of URLs on the current screen --> + <string name="console_menu_urlscan">"URL Scan"</string> + <!-- Button that initiates screen capture --> + <string name="console_menu_screencapture">"Screen Capture"</string> + <!-- Button that lets user pick the file to download --> + <string name="console_menu_download">"Download File"</string> + <!-- Button that lets user pick the file to upload --> + <string name="console_menu_upload">"Upload File"</string> + + <!-- Button label to answer "Yes" to a yes/no prompt --> + <string name="button_yes">"Yes"</string> + <!-- Button label to answer "No" to a yes/no prompt --> + <string name="button_no">"No"</string> + + <!-- Selection for a "local" port forward. E.g., connections to a port listening locally is forwarded to the remote end's listening port. --> + <string name="portforward_local">"Local"</string> + <!-- Selection for a "remote" port forward. E.g., connections to a port listening remotely is forwarded to the local end's listening port. --> + <string name="portforward_remote">"Remote"</string> + <!-- Selection for a "dynamic" port forward. E.g., connections to a port listening locally is forwarded based on the SOCKS protocol to an arbitrary remote host and port. --> + <string name="portforward_dynamic">"Dynamic (SOCKS)"</string> + <!-- Button that commits the port forward to be made from the Port Forward Creation dialog. --> + <string name="portforward_pos">"Create port forward"</string> + + <string name="portforward_done">"Successfully created port forward"</string> + <string name="portforward_problem">"Problem creating port forward, maybe you're using ports under 1024 or port is already used?"</string> + + <string name="portforward_menu_add">"Add port forward"</string> + + <!-- The string to present in the quick-connect box to hint the user to the format for connecting to hosts. --> + <string name="hint_userhost">"user@hostname"</string> + + <!-- Hint given to user when the format they're using is incorrect in the quick-connect box. --> + <string name="list_format_error">"Use the format \"%1$s\""</string> + + <!-- Part of the formatting hints that will be used like: username@hostname:port --> + <string name="format_username">"user"</string> + <!-- Part of the formatting hints that will be used like: username@hostname:port --> + <string name="format_hostname">"host"</string> + <!-- Part of the formatting hints that will be used like: username@hostname:port --> + <string name="format_port">"port"</string> + + <string name="list_menu_pubkeys">"Manage Pubkeys"</string> + <!-- Selection choice to sort hosts by color. --> + <string name="list_menu_sortcolor">"Sort by color"</string> + <!-- Selection choice to sort hosts by nickname. --> + <string name="list_menu_sortname">"Sort by name"</string> + <string name="list_menu_settings">"Settings"</string> + + <string name="list_host_disconnect">"Disconnect"</string> + <string name="list_host_edit">"Edit host"</string> + <string name="list_host_portforwards">"Edit port forwards"</string> + <string name="list_host_delete">"Delete host"</string> + <!-- Note that the '\n' splits the lines so it's actually "quick-connect box below to connect" --> + <string name="list_host_empty">"Use the quick-connect box"\n"below to connect to a host."</string> + + <!-- Default screen rotation preference selection --> + <string name="list_rotation_default">"Default"</string> + <string name="list_rotation_land">"Force landscape"</string> + <string name="list_rotation_port">"Force portrait"</string> + <!-- Selection to indicate the rotation should be selected automatically based on the tilt sensor. --> + <string name="list_rotation_auto">"Automatic"</string> + + <!-- Selection to indicate pressing a hardware button should send Ctrl. --> + <string name="list_hwbutton_ctrl">"CTRL"</string> + <!-- Selection to indicate pressing a hardware button should send Esc. --> + <string name="list_hwbutton_esc">"Esc"</string> + <!-- Selection to indicate pressing a hardware button should send a Tab. --> + <string name="list_hwbutton_tab">"Tab"</string> + <!-- Selection to indicate pressing a hardware button should do a screen capture. --> + <string name="list_hwbutton_screen_capture">"Screen Capture"</string> + <!-- Selection to indicate pressing a hardware button should send "Ctrl then Space". --> + <string name="list_hwbutton_ctrlaspace">"Ctrl+A then Space"</string> + <!-- Selection to indicate pressing a hardware button should send "Ctrl+A". --> + <string name="list_hwbutton_ctrla">"Ctrl+A"</string> + <!-- Selection to indicate pressing a hardware button should send "Esc+A". --> + <string name="list_hwbutton_esc_a">"Esc+A"</string> + <!-- Selection to indicate pressing a hardware button should notify the monitor. --> + <string name="list_hwbutton_monitor">"Monitor Key"</string> + <!-- Selection to indicate pressing a hardware button should bring up the soft function key pad. --> + <string name="list_hwbutton_soft_function_keys">"Soft Function Keypad"</string> + <!-- Selection to indicate pressing a hardware button should increase font size. --> + <string name="list_hwbutton_increase_fontsize">"Increase Font Size"</string> + <!-- Selection to indicate pressing a hardware button should decrease font size. --> + <string name="list_hwbutton_decrease_fontsize">"Decrease Font Size"</string> + <!-- Selection to indicate pressing a hardware button should send nothing at all. --> + <string name="list_hwbutton_none">"None"</string> + + <!-- Name for the backspace character --> + <string name="list_delkey_backspace">"Backspace"</string> + <!-- Name for the ASCII DEL character --> + <string name="list_delkey_del">"Delete"</string> + + <string name="delete_message">"Are you sure you want to delete '%1$s'?"</string> + <string name="delete_pos">"Yes, delete"</string> + <string name="delete_neg">"Cancel"</string> + + <!-- Button to agree to license terms. --> + <string name="wizard_agree">"Agree"</string> + <!-- Button to go to the next page in the first time start-up wizard. --> + <string name="wizard_next">"Next"</string> + <!-- Button to go to the previous page in the first time start-up wizard. --> + <string name="wizard_back">"Back"</string> + + <string name="terminal_no_hosts_connected">"No hosts currently connected"</string> + + <!-- Displayed in terminal when attempting to connect to a host. The first two + variables are host:port and the third is the protocol (e.g., SSH) --> + <string name="terminal_connecting">"Connecting to %1$s:%2$d via %3$s"</string> + + <!-- Displays the host key to the user in the terminal --> + <string name="terminal_sucess">"Verified host '%1$s' key: %2$s"</string> + <string name="terminal_failed">"Host key verification failed."</string> + + <!-- Displayed on the terminal describing the cryptographic algorithm names --> + <string name="terminal_using_s2c_algorithm">"Server-to-client algorithm: %1$s %2$s"</string> + <!-- Displayed on the terminal describing the cryptographic algorithm names --> + <string name="terminal_using_c2s_algorithm">"Client-to-server algorithm: %1$s %2$s"</string> + <!-- Displayed on the terminal describing the cryptographic algorithm names --> + <string name="terminal_using_algorithm">"Using algorithm: %1$s %2$s"</string> + + <string name="terminal_auth">"Trying to authenticate"</string> + + <string name="terminal_auth_pass">"Attempting 'password' authentication"</string> + <string name="terminal_auth_pass_fail">"Authentication method 'password' failed"</string> + + <string name="terminal_auth_pubkey_any">"Attempting 'publickey' authentication with any in-memory public keys"</string> + <string name="terminal_auth_pubkey_invalid">"Selected public key is invalid, try reselecting key in host editor"</string> + <string name="terminal_auth_pubkey_specific">"Attempting 'publickey' authentication with a specific public key"</string> + <string name="terminal_auth_pubkey_fail">"Authentication method 'publickey' with key '%1$s' failed"</string> + + <string name="terminal_auth_ki">"Attempting 'keyboard-interactive' authentication"</string> + <string name="terminal_auth_ki_fail">"Authentication method 'keyboard-interactive' failed"</string> + + <string name="terminal_auth_fail">"[Your host doesn't support 'password' or 'keyboard-interactive' authentication.]"</string> + + <string name="terminal_no_session">"Session will not be started due to host preference."</string> + <string name="terminal_enable_portfoward">"Enable port forward: %1$s"</string> + + <string name="local_shell_unavailable">"Failure! Local shell is unavailable on this device."</string> + + <!-- Text sent to the user to alert them that a Terminal Bell is received in a background session --> + <string name="notification_text">"%1$s wants your attention."</string> + + <!-- Preference selection for SSH Authentication Agent to never use pubkeys --> + <string name="no">"No"</string> + <!-- Preference selection for SSH Authentication Agent to be able to use pubkeys "with confirmation" only --> + <string name="with_confirmation">"With confirmation"</string> + <!-- Preference selection for SSH Authentication Agent to be able to use pubkeys --> + <string name="yes">"Yes"</string> + + <!-- String displayed to user when they're asked to submit exceptions to the ConnectBot developers --> + <string name="exceptions_submit_message">"It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?"</string> + + <!-- Menu selection to reset colors to their defaults. --> + <string name="menu_colors_reset">"Reset"</string> + + <!-- Displayed in the notification bar that connections are active --> + <string name="app_is_running">"510 ConnectBot is running"</string> + + <string name="color_red">"red"</string> + <string name="color_green">"green"</string> + <string name="color_blue">"blue"</string> + <string name="color_gray">"gray"</string> + + <!-- Very short label indicating the thing next to it is "foreground color." --> + <string name="colors_fg">"FG":</string> + + <!-- Very short label indicating the thing next to it is "background color." --> + <string name="color_bg">"BG:"</string> + + <!-- Describes the image of the "connected to host" icon for accessibility purposes. --> + <string name="image_description_connected">"Connected."</string> + + <!-- Describes the icon of the "locked pubkey" icon for accessibility purposes. --> + <string name="image_description_key_is_locked">"Key is locked."</string> + + <!-- Describes the icon of the "send control character" button in the terminal view for + accessibility purposes. --> + <string name="image_description_toggle_control_character">Toggle control character.</string> + + <!-- Describes the icon of the "send escape character" button in the terminal view for + accessibility purposes. --> + <string name="image_description_send_escape_character">Send escape character.</string> + + <!-- Describes the icon of the "show keyboard" button in the terminal view for accessibility + purposes. --> + <string name="image_description_show_keyboard">Show keyboard.</string> + + <!-- Describes the icon of the "line input" button in the terminal view for accessibility + purposes --> + <string name="image_description_line_input">Single line input</string> + + <!-- Describes the icon of the "sym" button in the terminal view for accessibility + purposes --> + <string name="image_description_sym">Character picker window</string> + + <string name="button_close">Close</string> + + <!-- Keyboard customization --> + <string name="pref_custom_keymap_title">Custom Keymap</string> + <string name="pref_custom_keymap_summary">Remapping of certain keys on supported devices</string> + <string name="pref_custom_keymap_full">Full hardware keyboard</string> + <string name="pref_custom_keymap_disabled">disabled</string> + + <string name="resize_error_title">Error resizing screen</string> + <string name="resize_error_width_height">Width and height must be higher than 0</string> + <string name="dia_resize_x">x</string> + + <!-- Screen capture --> + <string name="pref_screen_capture_category">Screen Capture</string> + <string name="pref_screen_capture_folder">Screen capture path</string> + <string name="pref_screen_capture_folder_summary">Folder to save screen capture files</string> + <string name="pref_screen_capture_popup">Screen capture report</string> + <string name="pref_screen_capture_popup_summary">Display a pop-up window on successful screen capture</string> + <string name="screen_capture">Screen Capture</string> + <string name="screenshot_success_title">Screenshot successful</string> + <string name="screenshot_saved_as">Screenshot saved as</string> + <string name="screenshot_error_title">Error creating screenshot</string> + <string name="screenshot_not_saved_as">Could not save screenshot as</string> + + <!-- Character picker (Sym) dialog --> + <string name="pref_picker_string">Sym window contents</string> + <string name="pref_picker_string_summary">String of characters for the character picker dialog</string> + <string name="pref_picker_keep_open">Leave Sym window open</string> + <string name="pref_picker_keep_open_summary">Only the cancel button closes the picker dialog</string> + + <!-- File Dialog --> + <string name="pref_file_transfer_category">File Transfer</string> + <string name="pref_file_dialog_title">File selection</string> + <string name="pref_file_dialog_summary">Dialog for choosing files and directories</string> + <string name="pref_file_dialog_builtin">built-in</string> + <string name="error_starting_app">Error starting %1$s</string> + <string name="file_chooser_select_file">Select file %1$s</string> + <string name="select_for_download">for download</string> + <string name="select_for_upload">for upload</string> + <string name="select_for_key_import">for key import</string> + + <!-- com.lamerman.FileExplorer --> + <string name="location">Location</string> + <string name="cant_read_folder">Error reading folder.</string> + <string name="nnew">New</string> + <string name="select">Select</string> + <string name="file_name">File name:</string> + <string name="cancel">Cancel</string> + <string name="new_file">New file</string> + <string name="save">Save</string> + <string name="no_data">No Data</string> + <color name="gray">#ffff0000</color> + + <!-- File Transfer --> + <string name="pref_download_folder">Download folder</string> + <string name="pref_download_folder_summary">Path to save downloaded files</string> + <string name="pref_remote_upload_folder">Remote upload folder</string> + <string name="pref_remote_upload_folder_summary">Remote path to save uploaded files</string> + <string name="pref_upload_dest_prompt">Upload target prompt</string> + <string name="pref_upload_dest_prompt_summary">Prompt for remote destination of file uploads</string> + <string name="pref_background_file_transfer">Background file transfer</string> + <string name="pref_background_file_transfer_summary">Perform file downloads and uploads in background</string> + <string name="transfer_downloading">"Downloading file…"</string> + <string name="transfer_downloading_file">Downloading file: %1$s</string> + <string name="transfer_download_complete">Download complete</string> + <string name="transfer_download_failed">Error downloading file(s):%1$s</string> + <string name="transfer_select_remote_download_title">Download file(s)</string> + <string name="transfer_select_remote_download_desc">Enter paths of the remote files to download (one per line)</string> + <string name="transfer_select_remote_upload_dest_title">Upload destination</string> + <string name="transfer_select_remote_upload_dest_desc">Enter remote file name for:</string> + <string name="transfer_button_download">Download</string> + <string name="transfer_button_upload">Upload</string> + <string name="transfer_uploading">"Uploading file…"</string> + <string name="transfer_uploading_file">Uploading file: %1$s</string> + <string name="transfer_upload_complete">Upload complete</string> + <string name="transfer_upload_failed">Error uploading file(s):%1$s</string> + + <!-- Key export --> + <string name="pubkey_export_private">"Export private key"</string> + <string name="pubkey_export_public">"Export public key"</string> + <string name="pubkey_public_save_as">Save public key</string> + <string name="pubkey_public_save_as_desc">File name (full path) to save the public key</string> + <string name="pubkey_private_save_as">Save private key</string> + <string name="pubkey_private_save_as_desc">File name (full path) to save the private key</string> + <string name="pubkey_public_export_success">Public key saved as %1$s</string> + <string name="pubkey_public_export_problem">Error exporting public key</string> + <string name="pubkey_private_export_success">Private key saved as %1$s</string> + <string name="pubkey_private_export_problem">Error exporting private key</string> + + <!-- Debug --> + <string name="pref_debug_category">Debug settings</string> + <string name="pref_debug_keycodes">Print keycodes</string> + <string name="pref_debug_keycodes_summary">Print codes of keys pressed in terminal window</string> + <string name="keycode_pressed">Code of pressed key</string> + + <!-- Long Press Menu --> + <string name="pref_extended_longpress">Extended longpress menu</string> + <string name="pref_extended_longpress_summary">Show input dialogs in tap-and-hold menu</string> + <string name="longpress_select_action">Select Action</string> + <string name="longpress_enable_full_screen_mode">Enable full screen mode</string> + <string name="longpress_disable_full_screen_mode">Disable full screen mode</string> + <string name="longpress_change_font_size">Change font size</string> + <string name="longpress_arrows_dialog">Arrow keys</string> + <string name="longpress_fkeys_dialog">Function keys</string> + <string name="longpress_ctrl_dialog">CTRL+?</string> + <string name="longpress_sym_dialog">Character picker</string> + + <!-- Ctrl picker dialog --> + <string name="pref_ctrl_string">Ctrl window contents</string> + <string name="pref_ctrl_string_summary">String of characters for the CTRL+? combination</string> + + <string name="fullscreen">Fullscreen</string> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/values/styles.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources> + <style name="NoTitle" parent="android:Theme"> + <item name="android:windowNoTitle">true</item> + <item name="android:windowContentOverlay">@null</item> + </style> +</resources>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/xml/host_prefs.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,214 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + + <EditTextPreference + android:key="nickname" + android:title="@string/hostpref_nickname_title" + android:singleLine="true" + /> + + <ListPreference + android:key="color" + android:title="@string/hostpref_color_title" + android:entries="@array/list_colors" + android:entryValues="@array/list_color_values" + /> + + <EditTextPreference + android:key="fontsize" + android:title="@string/hostpref_fontsize_title" + android:inputType="number" + android:singleLine="true" + /> + + <CheckBoxPreference + android:key="fixed_size" + android:title="@string/hostpref_fixed_size_title" + android:summary="@string/hostpref_fixed_size_summary" + /> + + <EditTextPreference + android:key="fixed_width" + android:title="@string/hostpref_fixed_width_title" + android:defaultValue="80" + android:numeric="integer" + /> + + <EditTextPreference + android:key="fixed_height" + android:title="@string/hostpref_fixed_height_title" + android:defaultValue="25" + android:numeric="integer" + /> + + <ListPreference + android:key="pubkeyid" + android:title="@string/hostpref_pubkeyid_title" + android:entries="@array/list_pubkeyids" + android:entryValues="@array/list_pubkeyids_value" + /> + + <ListPreference + android:key="useauthagent" + android:title="@string/hostpref_authagent_title" + android:entries="@array/list_authagent" + android:entryValues="@array/list_authagent_values" + /> + + <EditTextPreference + android:key="postlogin" + android:title="@string/hostpref_postlogin_title" + android:summary="@string/hostpref_postlogin_summary" + /> + + <CheckBoxPreference + android:key="compression" + android:title="@string/hostpref_compression_title" + android:summary="@string/hostpref_compression_summary" + /> + + <EditTextPreference + android:key="httpproxy" + android:title="@string/hostpref_httpproxy_title" + android:summary="@string/hostpref_httpproxy_summary" + android:inputType="textUri" + /> + + <CheckBoxPreference + android:key="wantsession" + android:title="@string/hostpref_wantsession_title" + android:summary="@string/hostpref_wantsession_summary" + /> + + <CheckBoxPreference + android:key="stayconnected" + android:title="@string/hostpref_stayconnected_title" + android:summary="@string/hostpref_stayconnected_summary" + /> + + <ListPreference + android:key="delkey" + android:title="@string/hostpref_delkey_title" + android:summary="@string/hostpref_delkey_summary" + android:entries="@array/list_delkey" + android:entryValues="@array/list_delkey_values" + /> + + <ListPreference + android:key="encoding" + android:title="@string/hostpref_encoding_title" + android:summary="@string/hostpref_encoding_summary" + /> + + <PreferenceCategory + android:title="@string/hostpref_connection_category"> + + <EditTextPreference + android:key="username" + android:title="@string/hostpref_username_title" + android:singleLine="true" + /> + + <EditTextPreference + android:key="hostname" + android:title="@string/hostpref_hostname_title" + android:singleLine="true" + /> + + <EditTextPreference + android:key="port" + android:title="@string/hostpref_port_title" + android:numeric="integer" + /> + + <EditTextPreference + android:key="monitor" + android:title="@string/hostpref_monitor_title" + android:summary="@string/hostpref_monitor_summary" + android:singleLine="true" + /> + + <EditTextPreference + android:key="emulation" + android:title="@string/hostpref_emulation_title" + android:summary="@string/hostpref_emulation_summary" + android:singleLine="true" + /> + </PreferenceCategory> + + + <PreferenceCategory + android:key="5250" + android:title="@string/hostpref_5250_settings"> + + <ListPreference + android:key="encryption5250" + android:title="@string/hostpref_5250_encryption_title" + android:entries="@array/list_5250_encryption_modes" + android:entryValues="@array/list_5250_encryption_modes" + /> + + <EditTextPreference + android:key="library5250" + android:title="@string/hostpref_5250_library_title" + android:singleLine="true" + /> + + <EditTextPreference + android:key="menu5250" + android:title="@string/hostpref_5250_menu_title" + android:singleLine="true" + /> + + <EditTextPreference + android:key="program5250" + android:title="@string/hostpref_5250_program_title" + android:singleLine="true" + /> + </PreferenceCategory> + + + <PreferenceCategory + android:key="x11" + android:title="@string/hostpref_x11_forwarding"> + + <CheckBoxPreference + android:key="wantx11forward" + android:title="@string/hostpref_wantx11forward_title" + android:summary="@string/hostpref_wantx11forward_summary" + /> + + <EditTextPreference + android:key="x11host" + android:title="@string/hostpref_x11host_title" + android:singleLine="true" + /> + + <EditTextPreference + android:key="x11port" + android:title="@string/hostpref_x11port_title" + android:numeric="integer" + /> + + </PreferenceCategory> + +</PreferenceScreen>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/xml/preferences.xml Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,302 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2007 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + + <CheckBoxPreference + android:key="memkeys" + android:title="@string/pref_memkeys_title" + android:summary="@string/pref_memkeys_summary" + android:defaultValue="true" + /> + + <CheckBoxPreference + android:key="connPersist" + android:title="@string/pref_conn_persist_title" + android:summary="@string/pref_conn_persist_summary" + android:defaultValue="true" + /> + + <PreferenceCategory + android:title="@string/pref_emulation_category"> + + <ListPreference + android:key="emulation" + android:title="@string/pref_emulation_title" + android:summary="@string/pref_emulation_summary" + android:entries="@array/list_emulation_modes" + android:entryValues="@array/list_emulation_modes" + android:defaultValue="xterm-256color" + /> + + <EditTextPreference + android:key="scrollback" + android:title="@string/pref_scrollback_title" + android:summary="@string/pref_scrollback_summary" + android:defaultValue="140" + android:numeric="integer" + /> + + </PreferenceCategory> + + <PreferenceCategory + android:key="category_ui" + android:title="@string/pref_ui_category"> + + <ListPreference + android:key="rotation" + android:title="@string/pref_rotation_title" + android:summary="@string/pref_rotation_summary" + android:entries="@array/list_rotation" + android:entryValues="@array/list_rotation_values" + android:defaultValue="Default" + /> + + <CheckBoxPreference + android:key="shiftfkeys" + android:title="@string/pref_shiftfkeys_title" + android:summary="@string/pref_shiftfkeys_summary" + android:defaultValue="false" + /> + + <CheckBoxPreference + android:key="ctrlfkeys" + android:title="@string/pref_ctrlfkeys_title" + android:summary="@string/pref_ctrlfkeys_summary" + android:defaultValue="false" + /> + + <ListPreference + android:key="keymode" + android:title="@string/pref_keymode_title" + android:summary="@string/pref_keymode_summary" + android:entries="@array/list_keymode" + android:entryValues="@array/list_keymode_values" + android:defaultValue="Use right-side keys" + /> + + <ListPreference + android:key="camera" + android:title="@string/pref_camera_title" + android:summary="@string/pref_camera_summary" + android:entries="@array/list_hwbutton" + android:entryValues="@array/list_hwbutton_values" + android:defaultValue="Screen Capture" + /> + + <ListPreference + android:key="volup" + android:title="@string/pref_volup_title" + android:summary="@string/pref_volup_summary" + android:entries="@array/list_hwbutton" + android:entryValues="@array/list_hwbutton_values" + android:defaultValue="Soft Function Keypad" + /> + + <ListPreference + android:key="voldn" + android:title="@string/pref_voldn_title" + android:summary="@string/pref_voldn_summary" + android:entries="@array/list_hwbutton" + android:entryValues="@array/list_hwbutton_values" + android:defaultValue="Tab" + /> + + <ListPreference + android:key="search" + android:title="@string/pref_search_title" + android:summary="@string/pref_search_summary" + android:entries="@array/list_hwbutton" + android:entryValues="@array/list_hwbutton_values" + android:defaultValue="Esc" + /> + + <ListPreference + android:key="ptt" + android:title="@string/pref_ptt_title" + android:summary="@string/pref_ptt_summary" + android:entries="@array/list_hwbutton" + android:entryValues="@array/list_hwbutton_values" + android:defaultValue="Monitor Key" + /> + + <CheckBoxPreference + android:key="keepalive" + android:title="@string/pref_keepalive_title" + android:summary="@string/pref_keepalive_summary" + android:defaultValue="true" + /> + + <CheckBoxPreference + android:key="wifilock" + android:title="@string/pref_wifilock_title" + android:summary="@string/pref_wifilock_summary" + android:defaultValue="true" + /> + + <CheckBoxPreference + android:key="bumpyarrows" + android:title="@string/pref_bumpyarrows_title" + android:summary="@string/pref_bumpyarrows_summary" + android:defaultValue="true" + /> + + <CheckBoxPreference + android:key="extended_longpress" + android:title="@string/pref_extended_longpress" + android:summary="@string/pref_extended_longpress_summary" + android:defaultValue="false" + /> + + <EditTextPreference + android:key="ctrl_string" + android:title="@string/pref_ctrl_string" + android:summary="@string/pref_ctrl_string_summary" + android:defaultValue="ABCDEKLOQRWSTUXZ" + android:singleLine="true" + /> + + <EditTextPreference + android:key="picker_string" + android:title="@string/pref_picker_string" + android:summary="@string/pref_picker_string_summary" + android:defaultValue="~\\^()[]{}<>|/:_;,.!@#$%&*?\"'-+=" + android:singleLine="true" + /> + + <CheckBoxPreference + android:key="picker_keep_open" + android:title="@string/pref_picker_keep_open" + android:summary="@string/pref_picker_keep_open_summary" + android:defaultValue="false" + /> + + <ListPreference + android:key="list_custom_keymap" + android:title="@string/pref_custom_keymap_title" + android:summary="@string/pref_custom_keymap_summary" + android:entries="@array/list_custom_keymap" + android:entryValues="@array/list_custom_keymap_values" + android:defaultValue="none" + /> + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/pref_bell_category"> + + <CheckBoxPreference + android:key="bell" + android:title="@string/pref_bell_title" + android:defaultValue="true" + /> + + <com.five_ten_sg.connectbot.util.VolumePreference + android:key="bellVolume" + android:title="@string/pref_bell_volume_title" + /> + + <CheckBoxPreference + android:key="bellVibrate" + android:title="@string/pref_bell_vibrate_title" + android:defaultValue="true" + /> + + <CheckBoxPreference + android:key="bellNotification" + android:title="@string/pref_bell_notification_title" + android:summary="@string/pref_bell_notification_summary" + android:defaultValue="false" + /> + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/pref_screen_capture_category"> + + <EditTextPreference + android:key="screen_capture_folder" + android:title="@string/pref_screen_capture_folder" + android:summary="@string/pref_screen_capture_folder_summary" + android:inputType="text" + android:singleLine="true" + /> + + <CheckBoxPreference + android:key="screen_capture_popup" + android:title="@string/pref_screen_capture_popup" + android:summary="@string/pref_screen_capture_popup_summary" + android:defaultValue="true" + /> + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/pref_file_transfer_category"> + + <ListPreference + android:key="file_dialog" + android:title="@string/pref_file_dialog_title" + android:summary="@string/pref_file_dialog_summary" + android:entries="@array/file_dialog" + android:entryValues="@array/file_dialog_values" + android:defaultValue="built-in" + /> + + <EditTextPreference + android:key="download_folder" + android:title="@string/pref_download_folder" + android:summary="@string/pref_download_folder_summary" + android:inputType="text" + android:singleLine="true" + /> + + <EditTextPreference + android:key="remote_upload_folder" + android:title="@string/pref_remote_upload_folder" + android:summary="@string/pref_remote_upload_folder_summary" + android:inputType="text" + android:singleLine="true" + android:defaultValue="" + /> + + <CheckBoxPreference + android:key="upload_dest_prompt" + android:title="@string/pref_upload_dest_prompt" + android:summary="@string/pref_upload_dest_prompt_summary" + android:defaultValue="true" + /> + + <CheckBoxPreference + android:key="background_file_transfer" + android:title="@string/pref_background_file_transfer" + android:summary="@string/pref_background_file_transfer_summary" + android:defaultValue="true" + /> + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/pref_debug_category"> + + <CheckBoxPreference + android:key="debug_keycodes" + android:title="@string/pref_debug_keycodes" + android:summary="@string/pref_debug_keycodes_summary" + android:defaultValue="false" + /> + </PreferenceCategory> +</PreferenceScreen>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build.gradle Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,17 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + //classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle-experimental:0.4.0' + } +} + +allprojects { + repositories { + jcenter() + } +}
--- a/build.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project name="510Connectbot" default="help"> - - <!-- The local.properties file is created and updated by the 'android' tool. - It contains the path to the SDK. It should *NOT* be checked into - Version Control Systems. --> - <loadproperties srcFile="local.properties" /> - - <!-- The ant.properties file can be created by you. It is only edited by the - 'android' tool to add properties to it. - This is the place to change some Ant specific build properties. - Here are some properties you may want to change/update: - - source.dir - The name of the source directory. Default is 'src'. - out.dir - The name of the output directory. Default is 'bin'. - - For other overridable properties, look at the beginning of the rules - files in the SDK, at tools/ant/build.xml - - Properties related to the SDK location or the project target should - be updated using the 'android' tool with the 'update' action. - - This file is an integral part of the build system for your - application and should be checked into Version Control Systems. - - --> - <property file="ant.properties" /> - - <!-- The project.properties file is created and updated by the 'android' - tool, as well as ADT. - This file is an integral part of the build system for your - application and should be checked into Version Control Systems. --> - <loadproperties srcFile="project.properties" /> - - <!-- quick check on sdk.dir --> - <fail - message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" - unless="sdk.dir" - /> - - -<!-- extension targets. Uncomment the ones where you want to do custom work - in between standard targets --> -<!-- - <target name="-pre-build"> - </target> - <target name="-pre-compile"> - </target> - - /* This is typically used for code obfuscation. - Compiled code location: ${out.classes.absolute.dir} - If this is not done in place, override ${out.dex.input.absolute.dir} */ - <target name="-post-compile"> - </target> ---> - - <!-- Import the actual build file. - - To customize existing targets, there are two options: - - Customize only one target: - - copy/paste the target into this file, *before* the - <import> task. - - customize it to your needs. - - Customize the whole content of build.xml - - copy/paste the content of the rules files (minus the top node) - into this file, replacing the <import> task. - - customize to your needs. - - *********************** - ****** IMPORTANT ****** - *********************** - In all cases you must update the value of version-tag below to read 'custom' instead of an integer, - in order to avoid having your file be overridden by tools such as "android update project" - --> - <!-- version-tag: custom --> - <import file="${sdk.dir}/tools/ant/build.xml" /> - -<!-- Begin custom ConnectBot stuff --> - - <!-- Output directory for .po files. --> - <property name="locale.dir" value="locale" /> - - <!-- Default args to pass to a2po for .po generation. --> - <property name="a2po.args" value="--groups strings --template fortune/fortune.pot --layout 'fortune/fortune-%(locale)s.po'"/> - - <!-- File names for launchpad translations. --> - <property name="launchpad.export.file" value="launchpad-export.tar.gz"/> - <property name="launchpad.import.file" value="launchpad-import.tar.gz"/> - - <target name="-pre-build" depends="update-version"/> - - <target name="help"> - <!-- displays starts at col 13 - |13 80| --> - <echo>Android Ant Build. Available targets:</echo> - <echo> help: Displays this help.</echo> - <echo> clean: Removes output files created by other targets.</echo> - <echo> compile: Compiles project's .java files into .class files.</echo> - <echo> debug: Builds the application and signs it with a debug key.</echo> - <echo> release: Builds the application. The generated apk file must be</echo> - <echo> signed before it is published.</echo> - <echo> install: Installs/reinstalls the debug package onto a running</echo> - <echo> emulator or device.</echo> - <echo> If the application was previously installed, the</echo> - <echo> signatures must match.</echo> - <echo> uninstall: Uninstalls the application from a running emulator or</echo> - <echo> device.</echo> - <echo> translations-import: Import translations from a Launchpad-style</echo> - <echo> Rosetta translation.</echo> - <echo> translations-export: Export translations to a Launchpad-style</echo> - <echo> Rosetta translation.</echo> - - </target> - - <target name="update-version" description="Updates the Version.java file with current Mercurial revision"> - <echo>Updating resources with Mercurial revision and build date...</echo> - - <tstamp> - <format property="build.date" pattern="yyyy-MM-dd" /> - </tstamp> - - <!-- Get the version name from the android manifest, will en up in property ${manifest.android:versionName} --> - <xpath input="AndroidManifest.xml" expression="/manifest/@android:versionName" - output="manifest.version.name" /> - - <!-- find global id of the current mercurial commit --> - <exec executable="hg" outputproperty="hg.revision"> - <arg line="id --id"/> - </exec> - - <!-- write out to res/values/version.xml --> - <echo file="${resource.absolute.dir}/values/version.xml" encoding="utf8"><![CDATA[<?xml version="1.0" encoding="utf-8"?> -<resources> - <string name="msg_version" translatable="false">${ant.project.name} ${manifest.version.name} (${hg.revision} ${build.date})</string> -</resources> -]]></echo> - - <echo>Updated "msg_version" to: ${ant.project.name} ${manifest.version.name} (${hg.revision} ${build.date})</echo> - </target> - - <!-- Translations come from launchpad.net and are placed in the - locale/ subdirectory. --> - <target name="translations-import"> - <untar src="${launchpad.export.file}" dest="${locale.dir}" compression="gzip"/> - <exec executable="a2po" failonerror="true"> - <arg value="import"/> - <arg line="${a2po.args}"/> - </exec> - </target> - - <!-- Translations are to be uploaded to launchpad.net as a tar ball - created from the locale/ subdirectory. --> - <target name="translations-export"> - <exec executable="a2po" failonerror="true"> - <arg value="export"/> - <arg line="${a2po.args}"/> - </exec> - <tar destfile="${launchpad.import.file}" - compression="gzip" - basedir="${locale.dir}" - includes="**/*.pot **/*.po" /> - </target> - - <target name="-check-ndk"> - <fail - message="ndk.dir is missing. Make sure to put it in local.properties" - unless="ndk.dir" - /> - </target> - - <target name="native-build" depends="-check-ndk"> - <exec executable="${ndk.dir}/ndk-build" failonerror="true" /> - </target> - - <target name="native-clean" depends="-check-ndk"> - <exec executable="${ndk.dir}/ndk-build" failonerror="true"> - <arg value="clean" /> - </exec> - </target> - - <property name="lint" location="${android.tools.dir}/lint${bat}" /> - - <target name="lint-xml"> - <exec executable="${lint}"> - <arg value="--xml" /> - <arg value="lint-results.xml" /> - <arg path="${basedir}" /> - </exec> - </target> - - <target name="lint-html"> - <exec executable="${lint}"> - <arg value="--html" /> - <arg value="lint-results.html" /> - <arg path="${basedir}" /> - </exec> - </target> - -<!-- End custom ConnectBot stuff --> - -</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gradle/wrapper/gradle-wrapper.properties Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,6 @@ +#Wed Oct 21 11:34:03 PDT 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gradlew Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
--- a/help/Makefile Fri Jun 19 13:41:57 2015 -0700 +++ b/help/Makefile Thu Dec 03 11:23:55 2015 -0800 @@ -1,4 +1,4 @@ -a:=../assets/help +a:=../app/src/main/assets/help b:=../html all:
--- a/jni/Android.mk Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -include $(call all-subdir-makefiles)
--- a/jni/Application.mk Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -# Build both ARMv5TE and x86-32 machine code. -APP_ABI := armeabi x86
--- a/jni/Exec/Android.mk Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := com_google_ase_Exec -LOCAL_CFLAGS := -Werror -LOCAL_SRC_FILES := com_google_ase_Exec.cpp -LOCAL_LDLIBS := -llog - -include $(BUILD_SHARED_LIBRARY)
--- a/jni/Exec/com_google_ase_Exec.cpp Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "com_google_ase_Exec.h" - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <termios.h> -#include <unistd.h> - -#include "android/log.h" - -#define LOG_TAG "Exec" -#define LOG(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) - -void JNU_ThrowByName(JNIEnv * env, const char *name, const char *msg) { - jclass clazz = env->FindClass(name); - if (clazz != NULL) { - env->ThrowNew(clazz, msg); - } - env->DeleteLocalRef(clazz); -} - -char *JNU_GetStringNativeChars(JNIEnv * env, jstring jstr) { - if (jstr == NULL) { - return NULL; - } - jbyteArray bytes = 0; - jthrowable exc; - char *result = 0; - if (env->EnsureLocalCapacity(2) < 0) { - return 0; /* out of memory error */ - } - jclass Class_java_lang_String = env->FindClass("java/lang/String"); - jmethodID MID_String_getBytes = env->GetMethodID(Class_java_lang_String, "getBytes", "()[B"); - bytes = (jbyteArray) env->CallObjectMethod(jstr, MID_String_getBytes); - exc = env->ExceptionOccurred(); - if (!exc) { - jint len = env->GetArrayLength(bytes); - result = (char *) malloc(len + 1); - if (result == 0) { - JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0); - env->DeleteLocalRef(bytes); - return 0; - } - env->GetByteArrayRegion(bytes, 0, len, (jbyte *) result); - result[len] = 0; /* NULL-terminate */ - } else { - env->DeleteLocalRef(exc); - } - env->DeleteLocalRef(bytes); - return result; -} - -int jniGetFDFromFileDescriptor(JNIEnv * env, jobject fileDescriptor) { - jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor"); - jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor, - "descriptor", "I"); - return env->GetIntField(fileDescriptor, descriptor); -} - -static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, int *pProcessId) { - char *devname; - int ptm; - pid_t pid; - - ptm = open("/dev/ptmx", O_RDWR); // | O_NOCTTY); - if (ptm < 0) { - LOG("[ cannot open /dev/ptmx - %s ]\n", strerror(errno)); - return -1; - } - fcntl(ptm, F_SETFD, FD_CLOEXEC); - - if (grantpt(ptm) || unlockpt(ptm) || ((devname = (char *) ptsname(ptm)) == 0)) { - LOG("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); - return -1; - } - - pid = fork(); - if (pid < 0) { - LOG("- fork failed: %s -\n", strerror(errno)); - return -1; - } - - if (pid == 0) { - int pts; - - setsid(); - - pts = open(devname, O_RDWR); - if (pts < 0) - exit(-1); - - dup2(pts, 0); - dup2(pts, 1); - dup2(pts, 2); - - close(ptm); - - execl(cmd, cmd, arg0, arg1, NULL); - exit(-1); - } else { - *pProcessId = (int) pid; - return ptm; - } -} - -JNIEXPORT jobject JNICALL Java_com_google_ase_Exec_createSubprocess(JNIEnv * env, jclass clazz, - jstring cmd, jstring arg0, - jstring arg1, - jintArray processIdArray) { - char *cmd_8 = JNU_GetStringNativeChars(env, cmd); - char *arg0_8 = JNU_GetStringNativeChars(env, arg0); - char *arg1_8 = JNU_GetStringNativeChars(env, arg1); - - int procId; - int ptm = create_subprocess(cmd_8, arg0_8, arg1_8, &procId); - - if (processIdArray) { - int procIdLen = env->GetArrayLength(processIdArray); - if (procIdLen > 0) { - jboolean isCopy; - int *pProcId = (int *) env->GetPrimitiveArrayCritical(processIdArray, &isCopy); - if (pProcId) { - *pProcId = procId; - env->ReleasePrimitiveArrayCritical(processIdArray, pProcId, 0); - } - } - } - - jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor"); - jmethodID init = env->GetMethodID(Class_java_io_FileDescriptor, - "<init>", "()V"); - jobject result = env->NewObject(Class_java_io_FileDescriptor, init); - - if (!result) { - LOG("Couldn't create a FileDescriptor."); - } else { - jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor, - "descriptor", "I"); - env->SetIntField(result, descriptor, ptm); - } - - return result; -} - -JNIEXPORT void Java_com_google_ase_Exec_setPtyWindowSize(JNIEnv * env, jclass clazz, - jobject fileDescriptor, jint row, jint col, - jint xpixel, jint ypixel) { - int fd; - struct winsize sz; - - fd = jniGetFDFromFileDescriptor(env, fileDescriptor); - - if (env->ExceptionOccurred() != NULL) { - return; - } - - sz.ws_row = row; - sz.ws_col = col; - sz.ws_xpixel = xpixel; - sz.ws_ypixel = ypixel; - - ioctl(fd, TIOCSWINSZ, &sz); -} - -JNIEXPORT jint Java_com_google_ase_Exec_waitFor(JNIEnv * env, jclass clazz, jint procId) { - int status; - waitpid(procId, &status, 0); - int result = 0; - if (WIFEXITED(status)) { - result = WEXITSTATUS(status); - } - return result; -}
--- a/jni/Exec/com_google_ase_Exec.h Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include <jni.h> -/* Header for class com_google_ase_Exec */ - -#ifndef _Included_com_google_ase_Exec -#define _Included_com_google_ase_Exec -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: com_google_ase_Exec - * Method: createSubprocess - * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[I)Ljava/io/FileDescriptor; - */ - JNIEXPORT jobject JNICALL Java_com_google_ase_Exec_createSubprocess - (JNIEnv *, jclass, jstring, jstring, jstring, jintArray); - -/* - * Class: com_google_ase_Exec - * Method: setPtyWindowSize - * Signature: (Ljava/io/FileDescriptor;IIII)V - */ - JNIEXPORT void JNICALL Java_com_google_ase_Exec_setPtyWindowSize - (JNIEnv *, jclass, jobject, jint, jint, jint, jint); - -/* - * Class: com_google_ase_Exec - * Method: waitFor - * Signature: (I)I - */ - JNIEXPORT jint JNICALL Java_com_google_ase_Exec_waitFor(JNIEnv *, jclass, jint); - -/* - * Class: com_google_ase_Exec - * Method: register - * Signature: ()I - */ - JNIEXPORT jint JNICALL Java_com_google_ase_Exec_register(JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif
--- a/lint.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<lint> - <issue id="MissingTranslation" severity="warning" /> - <issue id="NewApi" severity="warning" /> -</lint> \ No newline at end of file
--- a/locale/.gitignore Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -*
--- a/project.properties Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -# Indicates whether an apk should be generated for each density. -split.density=false -# Project target. -target=android-16
--- a/res/anim/fade_out_delayed.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<alpha xmlns:android="http://schemas.android.com/apk/res/android" - android:fromAlpha="1.0" - android:toAlpha="0.0" - android:duration="500" - android:startOffset="1000" - android:fillAfter="true" - />
--- a/res/anim/fade_stay_hidden.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<alpha xmlns:android="http://schemas.android.com/apk/res/android" - android:fromAlpha="0.0" - android:toAlpha="0.0" - android:duration="500" - android:fillAfter="true" - />
--- a/res/anim/keyboard_fade_in.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<alpha xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:anim/accelerate_interpolator" - android:fromAlpha="0.0" - android:toAlpha="1.0" - android:duration="100" />
--- a/res/anim/keyboard_fade_out.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<alpha xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:anim/accelerate_interpolator" - android:fromAlpha="1.0" - android:toAlpha="0.0" - android:duration="100" />
--- a/res/anim/slide_left_in.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - <translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="300"/> - <!-- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> --> -</set>
--- a/res/anim/slide_left_out.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - <translate android:fromXDelta="0" android:toXDelta="-100%p" android:duration="300"/> - <!-- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> --> -</set>
--- a/res/anim/slide_right_in.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - <translate android:fromXDelta="-100%p" android:toXDelta="0" android:duration="300"/> - <!-- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> --> -</set>
--- a/res/anim/slide_right_out.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - <translate android:fromXDelta="0" android:toXDelta="100%p" android:duration="300"/> - <!-- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" /> --> -</set>
--- a/res/color/blue.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_selected="true" android:color="#000" /> - <item android:state_focused="true" android:color="#000" /> - <item android:state_pressed="true" android:color="#000" /> - <item android:color="#88f" /> -</selector>
--- a/res/color/green.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_selected="true" android:color="#000" /> - <item android:state_focused="true" android:color="#000" /> - <item android:state_pressed="true" android:color="#000" /> - <item android:color="#8f8" /> -</selector>
--- a/res/color/red.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_selected="true" android:color="#000" /> - <item android:state_focused="true" android:color="#000" /> - <item android:state_pressed="true" android:color="#000" /> - <item android:color="#f00" /> -</selector>
--- a/res/drawable/btn_close.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - - <item android:state_pressed="false" android:state_focused="false" - android:drawable="@+drawable/btn_close_normal" /> - - <item android:state_pressed="true" - android:drawable="@+drawable/btn_close_pressed" /> - - <item android:state_focused="true" - android:drawable="@+drawable/btn_close_selected" /> -</selector>
--- a/res/drawable/connected.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<selector - xmlns:android="http://schemas.android.com/apk/res/android"> - - <item - android:state_checked="true" - android:drawable="@android:drawable/presence_online" /> - - <item - android:state_expanded="true" - android:drawable="@android:drawable/presence_busy" /> - - <item - android:drawable="@android:drawable/presence_invisible" /> - -</selector>
--- a/res/drawable/pubkey.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<selector - xmlns:android="http://schemas.android.com/apk/res/android"> - - <item - android:state_checked="true" - android:drawable="@drawable/pubkey_unlocked" /> - - <item - android:drawable="@drawable/pubkey_locked" /> - -</selector> \ No newline at end of file
--- a/res/layout-land/item_host.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@android:id/content" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:padding="10dip" - > - - <ImageView - android:id="@android:id/icon" - android:src="@drawable/connected" - android:contentDescription="@string/image_description_connected" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:paddingTop="5dip" - /> - - <LinearLayout - android:orientation="horizontal" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - > - - <TextView - android:id="@android:id/text1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:singleLine="true" - android:ellipsize="end" - android:textAppearance="?android:attr/textAppearanceLarge" - /> - - <TextView - android:id="@android:id/text2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="10dip" - android:textAppearance="?android:attr/textAppearanceSmall" - /> - - - </LinearLayout> - -</RelativeLayout> \ No newline at end of file
--- a/res/layout-port/item_host.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@android:id/content" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:padding="10dip" - > - - <ImageView - android:id="@android:id/icon" - android:src="@drawable/connected" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:paddingTop="5dip" - android:contentDescription="@string/image_description_connected" - /> - - <TextView - android:id="@android:id/text1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingRight="20dip" - android:singleLine="true" - android:ellipsize="end" - android:textAppearance="?android:attr/textAppearanceLarge" - /> - - <TextView - android:id="@android:id/text2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:layout_below="@android:id/text1" - /> - - -</RelativeLayout> \ No newline at end of file
--- a/res/layout/act_colors.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> - - <TextView - android:text="@string/colors_fg" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:id="@+id/fg_label" - android:paddingTop="12dp" - /> - - <Spinner - android:id="@+id/fg" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@+id/fg_label" - /> - - <Spinner - android:id="@+id/bg" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignTop="@+id/fg" - android:layout_alignParentRight="true" - /> - - <TextView - android:text="@string/color_bg" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_toLeftOf="@+id/bg" - android:paddingTop="12dp" - /> - - <GridView - android:id="@+id/color_grid" - android:layout_height="fill_parent" - android:layout_width="fill_parent" - android:padding="10dp" - android:verticalSpacing="10dp" - android:horizontalSpacing="10dp" - android:numColumns="auto_fit" - android:columnWidth="60dp" - android:stretchMode="columnWidth" - android:gravity="center" - android:layout_below="@+id/fg" - android:stackFromBottom="true" android:minHeight="60dp"/> - -</RelativeLayout>
--- a/res/layout/act_console.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,185 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - > - - <TextView - android:id="@android:id/empty" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:text="@string/terminal_no_hosts_connected" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="center" - /> - - <ViewFlipper - android:id="@+id/console_flip" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - /> - - <RelativeLayout - android:id="@+id/console_password_group" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:padding="5dip" - android:background="#80000000" - android:fadingEdge="horizontal" - android:fadingEdgeLength="25dip" - android:visibility="gone" - > - - <TextView - android:id="@+id/console_password_instructions" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" - android:layout_width="fill_parent" - android:visibility="gone" - android:layout_marginBottom="5dip" - /> - - <EditText - android:id="@+id/console_password" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:inputType="textPassword" - android:singleLine="true" - android:layout_below="@+id/console_password_instructions" - /> - - </RelativeLayout> - - <RelativeLayout - android:id="@+id/console_boolean_group" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:padding="5dip" - android:background="#80000000" - android:fadingEdge="horizontal" - android:fadingEdgeLength="25dip" - android:visibility="gone" - > - - <TextView - android:id="@+id/console_prompt" - android:layout_height="wrap_content" - android:layout_width="fill_parent" - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <Button - android:id="@+id/console_prompt_no" - android:text="@string/button_no" - android:paddingTop="5dip" - android:paddingBottom="10dip" - android:paddingLeft="40dip" - android:paddingRight="40dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:layout_below="@+id/console_prompt" - android:clickable="false" - /> - - <Button - android:id="@+id/console_prompt_yes" - android:text="@string/button_yes" - android:paddingTop="5dip" - android:paddingBottom="10dip" - android:paddingLeft="40dip" - android:paddingRight="40dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toLeftOf="@+id/console_prompt_no" - android:layout_below="@+id/console_prompt" - /> - - </RelativeLayout> - - <RelativeLayout - android:id="@+id/keyboard_group" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:padding="15dip" - android:visibility="gone"> - - <ImageView - android:id="@+id/button_input" - android:paddingRight="15dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@+id/button_sym" - android:layout_alignParentBottom="true" - android:src="@+drawable/button_input" - android:contentDescription="@string/image_description_line_input" - /> - - <ImageView - android:id="@+id/button_keyboard" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_alignParentRight="true" - android:src="@+drawable/button_keyboard" - android:contentDescription="@string/image_description_show_keyboard" - /> - - <ImageView - android:id="@+id/button_ctrl" - android:paddingRight="15dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_alignParentBottom="true" - android:src="@+drawable/button_ctrl" - android:contentDescription="@string/image_description_toggle_control_character" - /> - - <ImageView - android:id="@+id/button_esc" - android:paddingRight="15dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@+id/button_ctrl" - android:layout_alignParentBottom="true" - android:src="@+drawable/button_esc" - android:contentDescription="@string/image_description_send_escape_character" - /> - - <ImageView - android:id="@+id/button_sym" - android:paddingRight="15dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_toRightOf="@+id/button_esc" - android:src="@+drawable/button_sym" - android:contentDescription="@string/image_description_sym" - /> - - </RelativeLayout> - -</RelativeLayout>
--- a/res/layout/act_generatepubkey.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<ScrollView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="wrap_content" - android:scrollbars="vertical" - android:layout_width="fill_parent"> - - <TableLayout - android:orientation="vertical" - android:layout_height="wrap_content" - android:paddingLeft="10dip" - android:paddingRight="10dip" - android:scrollbars="vertical" - android:layout_width="fill_parent"> - - <TableRow> - <TextView - android:text="@string/prompt_nickname" - android:paddingRight="10dip" - android:gravity="right|center_vertical" - android:textAppearance="?android:attr/textAppearanceMedium" /> - - <EditText - android:id="@+id/nickname" - android:hint="@string/prompt_nickname_hint_pubkey" - android:layout_height="wrap_content" - android:singleLine="true" - android:layout_weight="1" /> - </TableRow> - - <TableRow> - <TextView - android:text="@string/prompt_type" - android:paddingRight="10dip" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="bottom|right" - android:layout_gravity="center_vertical" /> - - <RadioGroup - android:id="@+id/key_type" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:checkedButton="@+id/rsa"> - - <RadioButton - android:id="@+id/rsa" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="RSA" /> - - <RadioButton - android:id="@+id/dsa" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="DSA" /> - - <RadioButton - android:id="@+id/ec" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="EC" /> - </RadioGroup> - </TableRow> - - <TableRow> - <TextView - android:text="@string/prompt_bits" - android:paddingRight="10dip" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="right|center_vertical" /> - - <EditText - android:id="@+id/bits" - android:inputType="number" - android:layout_height="wrap_content" - android:text="2048" - android:singleLine="true" - android:layout_weight="1" /> - </TableRow> - - <SeekBar - android:layout_height="wrap_content" - android:id="@+id/bits_slider" - android:layout_width="fill_parent" - android:paddingBottom="10dip" - android:max="3328" - android:progress="256" /> - - <TextView - android:text="@string/prompt_password_can_be_blank" - android:gravity="left" - android:layout_height="wrap_content" - android:layout_width="wrap_content" /> - - <TableRow> - <TextView - android:paddingRight="10dip" - android:gravity="right|center_vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" - android:text="@string/prompt_password" /> - - <EditText - android:id="@+id/password1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="textPassword" - android:singleLine="true" - android:layout_weight="1" /> - </TableRow> - - <TableRow> - <LinearLayout - android:paddingRight="10dip" - android:orientation="vertical" - android:gravity="right|center_vertical"> - - <TextView - android:gravity="right|bottom" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" - android:text="@string/prompt_password" /> - - <TextView - android:gravity="right|top" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:text="@string/prompt_again" /> - </LinearLayout> - - <EditText - android:id="@+id/password2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="textPassword" - android:singleLine="true" - android:layout_weight="1" /> - </TableRow> - - <CheckBox - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:id="@+id/unlock_at_startup" - android:text="@string/pubkey_load_on_start" /> - - <CheckBox - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:id="@+id/confirm_use" - android:text="@string/pubkey_confirm_use" /> - - <Button - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:id="@+id/save" - android:text="@string/pubkey_generate" - android:enabled="false" /> - </TableLayout> -</ScrollView>
--- a/res/layout/act_help.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<ScrollView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_weight="1" - > - - <LinearLayout - android:id="@+id/topics" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:gravity="center_horizontal" - > - - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:text="@string/msg_version" - android:paddingTop="2dip" - android:textAppearance="?android:attr/textAppearanceSmall" - android:gravity="right" - android:paddingRight="2dip" - /> - - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:text="@string/help_intro" - android:paddingTop="2dip" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="center_horizontal" - /> - - </LinearLayout> -</ScrollView>
--- a/res/layout/act_help_topic.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - > - - <com.five_ten_sg.connectbot.util.HelpTopicView - android:id="@+id/topic_text" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - /> - -</LinearLayout>
--- a/res/layout/act_hostlist.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - > - - <LinearLayout - android:id="@+id/transport_box" - android:orientation="horizontal" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_alignParentLeft="true" - > - - <Spinner - android:id="@+id/transport_selection" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_alignParentLeft="true" - /> - - <EditText - android:id="@+id/front_quickconnect" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:hint="username@hostname:port" - android:layout_toRightOf="@+id/transport_selection" - android:layout_alignParentBottom="true" - android:inputType="textEmailAddress" - /> - </LinearLayout> - - <ListView - android:id="@android:id/list" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:layout_above="@+id/transport_box" - /> - - <TextView - android:id="@android:id/empty" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:text="@string/list_host_empty" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="center" - android:layout_above="@+id/transport_box" - /> - -</RelativeLayout>
--- a/res/layout/act_portforwardlist.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - > - - <ListView android:id="@android:id/list" - android:layout_width="fill_parent" - android:layout_height="0dip" - android:layout_weight="1" - /> - - <TextView android:id="@android:id/empty" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:text="@string/portforward_list_empty" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="center" - /> -</LinearLayout>
--- a/res/layout/act_pubkeylist.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - > - - <ListView android:id="@android:id/list" - android:layout_width="fill_parent" - android:layout_height="0dip" - android:layout_weight="1" - /> - - <TextView android:id="@android:id/empty" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:text="@string/pubkey_list_empty" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="center" - /> -</LinearLayout>
--- a/res/layout/act_wizard.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:gravity="right" - > - - <ViewFlipper - android:id="@+id/wizard_flipper" - android:layout_width="fill_parent" - android:layout_height="0dip" - android:layout_weight="1" - /> - - <LinearLayout - android:orientation="horizontal" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:padding="5dip" - > - - <Button - android:id="@+id/action_prev" - android:layout_width="120dip" - android:layout_height="wrap_content" - android:drawableLeft="@drawable/ic_btn_back" - android:text="Cancel" - android:gravity="center" - /> - - <Button - android:id="@+id/action_next" - android:layout_width="120dip" - android:layout_height="wrap_content" - android:drawableRight="@drawable/ic_btn_next" - android:text="Agree" - android:gravity="center" - /> - - </LinearLayout> - -</LinearLayout>
--- a/res/layout/dia_changepassword.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingLeft="10dip" - android:paddingRight="10dip" - > - - <TableRow android:id="@+id/old_password_prompt"> - <TextView - android:text="@string/prompt_old_password" - android:paddingRight="10dip" - android:gravity="right|center_vertical" - android:textAppearance="?android:attr/textAppearanceMedium" - android:layout_width="wrap_content" - /> - - <EditText - android:id="@+id/old_password" - android:layout_width="200dip" - android:layout_height="wrap_content" - android:singleLine="true" - android:inputType="textPassword" - /> - </TableRow> - - <TableRow> - <TextView - android:text="@string/prompt_password" - android:paddingRight="10dip" - android:gravity="right|center_vertical" - android:textAppearance="?android:attr/textAppearanceMedium" - android:layout_width="wrap_content" - /> - - <EditText - android:id="@+id/password1" - android:layout_width="200dip" - android:layout_height="wrap_content" - android:singleLine="true" - android:inputType="textPassword" - /> - </TableRow> - - <TableRow> - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical" - android:gravity="right" - > - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/prompt_password" - android:paddingRight="10dip" - android:gravity="right|bottom" - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/prompt_again" - android:paddingRight="10dip" - android:gravity="right|top" - android:textAppearance="?android:attr/textAppearanceSmall" - /> - </LinearLayout> - - <EditText - android:id="@+id/password2" - android:layout_width="200dip" - android:layout_height="wrap_content" - android:singleLine="true" - android:inputType="textPassword" - /> - </TableRow> -</TableLayout>
--- a/res/layout/dia_gatherentropy.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="10dip" - android:paddingRight="10dip" - > - - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:text="@string/pubkey_touch_hint" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="center"/> - - <com.five_ten_sg.connectbot.util.EntropyView - android:id="@+id/entropy" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:background="#666666ff" - android:layout_marginBottom="10dip" - android:layout_marginTop="10dip" - android:drawingCacheQuality="auto"/> -</LinearLayout>
--- a/res/layout/dia_password.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="250dip" - android:layout_height="wrap_content" - android:orientation="vertical" - android:padding="10dip" - > - - <EditText - android:id="@android:id/text1" - android:layout_width="250dip" - android:singleLine="true" - android:layout_height="wrap_content" - android:inputType="textPassword" - android:hint="Password" - /> - -</LinearLayout> -
--- a/res/layout/dia_portforward.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="fill_parent" - android:layout_width="fill_parent" - android:scrollbars="vertical" - > - - <TableLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingLeft="10dip" - android:paddingRight="10dip" - > - - <TableRow> - <TextView - android:text="@string/prompt_nickname" - android:paddingRight="10dip" - android:gravity="right|center_vertical" - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <EditText - android:id="@+id/nickname" - android:hint="Internal Webserver" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:singleLine="true" - android:layout_weight="1" - /> - </TableRow> - - <TableRow> - <TextView - android:text="@string/prompt_type" - android:paddingRight="10dip" - android:gravity="right|center_vertical" - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <Spinner android:id="@+id/portforward_type" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:entries="@array/list_portforward_types" - android:prompt="@string/prompt_type" - android:layout_weight="1" - /> - </TableRow> - - <TableRow> - <TextView - android:text="@string/prompt_source_port" - android:paddingRight="10dip" - android:gravity="right|center_vertical" - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <EditText - android:id="@+id/portforward_source" - android:hint="8080" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_weight="1" - android:inputType="number" - /> - </TableRow> - - <TableRow> - <TextView - android:text="@string/prompt_destination" - android:paddingRight="10dip" - android:gravity="right|center_vertical" - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <EditText - android:id="@+id/portforward_destination" - android:hint="localhost:80" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_weight="1" - android:inputType="textEmailAddress" - /> - </TableRow> - </TableLayout> -</ScrollView>
--- a/res/layout/dia_resize.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="horizontal" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="10dip" - android:paddingRight="10dip" - > - - <EditText - android:id="@+id/width" - android:layout_width="100dip" - android:layout_height="wrap_content" - android:singleLine="true" - android:inputType="number" - /> - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/dia_resize_x" - android:paddingLeft="10dip" - android:paddingRight="10dip" - android:gravity="right|bottom" - android:textAppearance="?android:attr/textAppearanceLarge" - /> - - - <EditText - android:id="@+id/height" - android:layout_width="100dip" - android:layout_height="wrap_content" - android:singleLine="true" - android:inputType="number" - /> -</LinearLayout>
--- a/res/layout/file_dialog_main.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RelativeLayout android:id="@+id/relativeLayout01" - xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" android:layout_width="fill_parent" - android:layout_height="fill_parent"> - - <LinearLayout android:id="@+id/fdLinearLayoutList" - android:orientation="vertical" android:layout_width="fill_parent" - android:layout_height="wrap_content" android:layout_alignParentBottom="true"> - - <LinearLayout android:id="@+id/fdLinearLayoutSelect" - android:orientation="vertical" android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingLeft="10dp" - android:paddingRight="10dp" android:paddingBottom="5dp"> - - <LinearLayout android:orientation="horizontal" - android:layout_width="fill_parent" android:layout_height="fill_parent"> - <Button android:id="@+id/fdButtonNew" android:layout_height="wrap_content" - android:layout_width="0dip" android:layout_weight=".3" - android:text="@string/nnew"></Button> - <Button android:id="@+id/fdButtonSelect" android:layout_height="wrap_content" - android:layout_width="0dip" android:layout_weight=".6" - android:text="@string/select"></Button> - <Button android:id="@+id/fdButtonCancel" android:layout_height="wrap_content" - android:layout_width="0dip" android:layout_weight=".3" - android:text="@string/cancel"></Button> - </LinearLayout> - </LinearLayout> - - <LinearLayout android:id="@+id/fdLinearLayoutCreate" - android:orientation="vertical" android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingLeft="10dp" - android:paddingRight="10dp" android:paddingBottom="5dp"> - <TextView android:id="@+id/textViewFilename" android:text="@string/file_name" - android:layout_width="fill_parent" android:layout_height="wrap_content" /> - <EditText android:text="" android:id="@+id/fdEditTextFile" android:inputType="text" - android:layout_width="fill_parent" android:layout_height="wrap_content"></EditText> - - <LinearLayout android:orientation="horizontal" - android:layout_width="fill_parent" android:layout_height="fill_parent"> - <Button android:id="@+id/fdButtonCancelCreate" android:layout_height="wrap_content" - android:layout_width="0dip" android:layout_weight=".3" - android:text="@string/cancel"></Button> - <Button android:id="@+id/fdButtonCreate" android:layout_height="wrap_content" - android:layout_width="0dip" android:layout_weight=".7" - android:text="@string/new_file"></Button> - </LinearLayout> - </LinearLayout> - - </LinearLayout> - - <LinearLayout android:orientation="vertical" - android:layout_width="fill_parent" android:layout_height="fill_parent" - android:layout_above="@+id/fdLinearLayoutList"> - <TextView android:id="@+id/path" android:layout_width="fill_parent" - android:layout_height="wrap_content" /> - <ListView android:id="@android:id/list" android:layout_width="fill_parent" - android:layout_height="fill_parent" /> - <TextView android:id="@android:id/empty" - android:layout_width="fill_parent" android:layout_height="fill_parent" - android:text="@string/no_data" /> - </LinearLayout> - - - - -</RelativeLayout>
--- a/res/layout/file_dialog_row.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" android:layout_height="fill_parent"> - - <ImageView android:layout_alignParentLeft="true" android:id="@+id/fdrowimage" - android:layout_height="35dp" android:layout_width="wrap_content" - android:paddingRight="5dp" android:paddingLeft="3dp"></ImageView> - <TextView android:text="@+id/fdrowtext" android:layout_width="wrap_content" - android:id="@+id/fdrowtext" android:layout_toRightOf="@+id/fdrowimage" - android:layout_alignTop="@+id/fdrowimage" android:layout_alignBottom="@+id/fdrowimage" - android:gravity="center_vertical" android:layout_height="35dp" - android:textSize="23dp"></TextView> - -</RelativeLayout> \ No newline at end of file
--- a/res/layout/item_portforward.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="wrap_content" - android:orientation="vertical" - android:gravity="left|center_vertical" - android:layout_width="fill_parent" - android:padding="10dip" - > - - <TextView - android:id="@android:id/text1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceLarge" - android:text="Tunnel Nickname" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true" - /> - - <TextView - android:id="@android:id/text2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:text="Local port 8080 to 192.168.1.1:80" - android:layout_below="@android:id/text1" - /> - -</RelativeLayout>
--- a/res/layout/item_pubkey.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@android:id/content" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:padding="10dip"> - - <ImageView - android:id="@android:id/icon1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:src="@drawable/pubkey" - android:contentDescription="@string/image_description_key_is_locked" - android:layout_alignParentRight="true" - android:layout_alignParentTop="true" - android:layout_marginLeft="10dip"/> - - <TextView - android:id="@android:id/text1" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceLarge" - android:text="Key Example" - android:layout_alignParentLeft="true" - android:bufferType="normal" android:layout_width="wrap_content" android:layout_toLeftOf="@android:id/icon1"/> - - <TextView - android:id="@android:id/text2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:text="DSA 1024-bit" - android:layout_below="@android:id/text1" - /> - -</RelativeLayout>
--- a/res/layout/item_terminal.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - > - - <TextView - android:id="@+id/terminal_overlay" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceLarge" - android:background="#aa000000" - android:padding="10dip" - android:layout_centerInParent="true" - /> - -</RelativeLayout>
--- a/res/layout/string_picker.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- Copyright (C) 2008 The Android Open Source Project -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at -http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - --> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="horizontal" - android:layout_width="304dp" - android:layout_height="match_parent" - android:background="@drawable/keyboard_popup_panel_trans_background"> - - <GridView - android:id="@+id/stringPicker" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:padding="4dp" - android:verticalSpacing="8dp" - android:horizontalSpacing="8dp" - android:gravity="start" - android:drawSelectorOnTop="false" - android:numColumns="4" - android:columnWidth="48dp" - android:fadingEdge="none" - android:layout_gravity="center_vertical" - android:listSelector="#0000" - /> - - <Button - android:id="@+id/cancel" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="@drawable/btn_close" - android:layout_gravity="center_vertical" - /> -</LinearLayout>
--- a/res/layout/string_picker_button.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<Button xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:clickable="false" - android:focusable="false" - android:textAppearance="?android:attr/textAppearanceSmallInverse" - android:textColor="#FF000000" -/>
--- a/res/layout/wiz_eula.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<ScrollView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_weight="1" - > - - <LinearLayout - android:orientation="vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:padding="10dip" - > - - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:text="510 ConnectBot is a simple, powerful, open-source Secure Shell (SSH) client for your Android device." - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingTop="10dip" - android:text="It can manage several SSH sessions, create secure tunnels, and copy/paste between other apps." - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingTop="10dip" - android:text="@string/copyright_info" - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingTop="10dip" - android:autoLink="web" - android:text="@string/copyright_location" - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingTop="10dip" - android:text="@string/msg_version" - android:textAppearance="?android:attr/textAppearanceMedium" - /> - - </LinearLayout> - -</ScrollView>
--- a/res/values-af/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="title_hosts_list">Gashere</string> - <string name="title_pubkey_list">Publieke Sleutels</string> - <string name="title_port_forwards_list">Poort aansturings</string> - <string name="title_host_editor">Redigeer Gasheer</string> - <string name="title_help">Hulp</string> - <string name="title_colors">Kleure</string> - <string name="resolve_connect">Verbind</string> - <string name="menu_insert">Voeg Gasheer by</string> - <string name="menu_delete">Verwyder Gasheer</string> - <string name="menu_preferences">Voorkeure</string> - <string name="help_about">Aangaande ConnectBot</string> - <string name="help_keyboard">Sleutelbord</string> - <string name="pubkey_generate">Genereer</string> - <string name="pubkey_import">Voer in</string> - <string name="pubkey_delete">Verwyder sleutel</string> - <string name="pubkey_gather_entropy">Versamel Ewekansigheid</string> - <string name="pubkey_touch_prompt">Raak hierdie boks om ewekansigheid te versamel: %1$d%% voltooi</string> - <string name="pubkey_touch_hint">Om ewekansigheid te verseker gedurende die sleutel generering, beweeg u vinger ewekansig oor die boks hieronder.</string> - <string name="pubkey_copy_private">Dupliseer privaat sleutel</string> - <string name="pubkey_copy_public">Dupliseer publieke sleutel</string> - <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> - <string name="pubkey_unknown_format">Onbekende formaat</string> - <string name="pubkey_change_password">Verander wagwoord</string> - <string name="pubkey_list_pick">Kies van /sdcard</string> - <string name="pubkey_unlock">Ontsluit sleutel</string> - <string name="pubkey_memory_load">Laai na geheue</string> - <string name="pubkey_confirm_use">Bevestig voor gebruik</string> - <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> - <string name="portforward_edit">Redigeer poort aansturing</string> - <string name="portforward_delete">Verwyder poort aanstuur</string> - <string name="prompt_nickname">Bynaam:</string> - <string name="prompt_source_port">Oorsprong poort:</string> - <string name="prompt_destination">Bestemming:</string> - <string name="prompt_old_password">Ou wagwoord:</string> - <string name="prompt_password">Wagwoord:</string> - <string name="prompt_type">Tipe:</string> - <string name="prompt_password_can_be_blank">Nota: wagwoord kan leeg gelos word</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> -</resources>
--- a/res/values-ar/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">عميل SSH مفتوح المصدر و بسيط وقوي</string> - <string name="title_hosts_list">المخدمات</string> - <string name="title_pubkey_list">المفاتيح العامة</string> - <string name="title_port_forwards_list">تحويلات المنافذ</string> - <string name="title_host_editor">تعديل مخدم</string> - <string name="title_help">مساعدة</string> - <string name="title_colors">الألوان</string> - <string name="resolve_connect">اتصل</string> - <string name="menu_insert">اضافة مخدم</string> - <string name="menu_delete">حذف مخدم</string> - <string name="menu_preferences">التفضيلات</string> - <string name="help_intro">الرجاء اختار من الاسفل من اجل معلومات اكثر عن هذا الموضوع</string> - <string name="help_about">حول البرنامج</string> - <string name="help_keyboard">لوحة المفاتيح</string> - <string name="pubkey_generate">توليد</string> - <string name="pubkey_import">استيراد</string> - <string name="pubkey_delete">حذف المفتاح</string> - <string name="pubkey_touch_hint">للتاكد من العشوائية خلال توليد المفتاح , حرك اصبعك بشكل عشوائي فوق المربع في الاسفل</string> - <string name="pubkey_generating">جاري توليد المفتاح</string> - <string name="pubkey_copy_private">نسخ مفتاح خاص</string> - <string name="pubkey_copy_public">نسخ مفتاح عام</string> - <string name="pubkey_list_empty">"حدد القائمة لانشاء او استيراد المفاتيح"</string> - <string name="pubkey_unknown_format">صيغة غير معروفة</string> - <string name="pubkey_change_password">تغيير كلمة المرور</string> - <string name="pubkey_list_pick">اختار من بطاقة الذاكرة</string> - <string name="pubkey_import_parse_problem">مشكلة في تفسير المفتاح الخاص المستورد</string> - <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> - <string name="button_yes">نعم</string> - <string name="button_no">ﻻ</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="no">ﻻ</string> - <string name="yes">نعم</string> - <string name="exceptions_submit_message">الظاهر بان البرنامج واجه مشكلة في اخر جلسة عمل. هل ترغب بارسال تقرير لمطورين البرنامج؟</string> - <string name="menu_colors_reset">إعادة ضبط</string> - <string name="app_is_running">البرنامج يعمل</string> - <string name="color_red">أحمر</string> - <string name="color_green">أخضر</string> - <string name="color_blue">أزرق</string> - <string name="color_gray">رمادي</string> - <string name="image_description_connected">متصل</string> - <string name="image_description_key_is_locked">المفتاح مقفل</string> - <string name="image_description_show_keyboard">عرض لوحة المفاتيح</string> -</resources>
--- a/res/values-be/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> - <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> -</resources>
--- a/res/values-bg/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Прост, мощен SSH клиент с отворен код</string> - <string name="title_hosts_list">Хостове</string> - <string name="title_pubkey_list">Публични ключове</string> - <string name="title_port_forwards_list">Пренасочване на портове</string> - <string name="title_host_editor">Редактиране на хост</string> - <string name="title_help">Помощ</string> - <string name="title_colors">Цветове</string> - <string name="resolve_connect">Свързване</string> - <string name="menu_insert">Добавяне на хост</string> - <string name="menu_delete">Изтрий хост</string> - <string name="menu_preferences">Предпочитания</string> - <string name="help_about">Относно ConnectBot</string> - <string name="help_keyboard">Клавиатура</string> - <string name="pubkey_generate">Генериране</string> - <string name="pubkey_import">Импортиране</string> - <string name="pubkey_delete">Клавиш Delete</string> - <string name="pubkey_copy_private">Копира частния ключ</string> - <string name="pubkey_copy_public">Копира публичния ключ</string> - <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> - <string name="pubkey_unknown_format">Непознат формат</string> - <string name="pubkey_change_password">Промени паролата</string> - <string name="pubkey_list_pick">Избери от /sdcard</string> - <string name="pubkey_import_parse_problem">Проблем при прочитането на импортирания частен ключ</string> - <string name="pubkey_unlock">Клавиш за отключване</string> - <string name="pubkey_memory_load">Зареди в паметта</string> - <string name="pubkey_memory_unload">Премахни от паметта</string> - <string name="pubkey_load_on_start">Зареди ключа при стартиране</string> - <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> - <string name="portforward_edit">Променете пренасочването на портове</string> - <string name="portforward_delete">Изтрийте пренасочването на портове</string> - <string name="prompt_nickname">Псевдоним:</string> - <string name="prompt_destination">Назначение:</string> - <string name="prompt_old_password">Стара парола</string> - <string name="prompt_password">Парола:</string> - <string name="prompt_again">(отново)</string> - <string name="prompt_type">Тип:</string> - <string name="prompt_password_can_be_blank">Бележка: паролата не може да е празна</string> - <string name="prompt_bits">Битове</string> - <string name="alert_passwords_do_not_match_msg">Паролите не съвпадат!</string> - <string name="alert_wrong_password_msg">Грешна парола!</string> - <string name="alert_sdcard_absent">SD картата не е поставена</string> - <string name="button_add">Добавяне</string> - <string name="button_change">Промяна</string> - <string name="button_generate">Генерирай ключ</string> - <string name="button_resize">Промяна на размера на екрана</string> - <string name="alert_disconnect_msg">Връзката изгубена</string> - <string name="list_keymode_none">Забраняване</string> - <string name="console_copy_done">Копирани %1$d байта в клипборда</string> - <string name="console_menu_close">Затваряне</string> - <string name="console_menu_copy">Копиране</string> - <string name="console_menu_paste">Поставяне</string> - <string name="console_menu_portforwards">Пренасочване на портове</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="list_host_disconnect">Прекъсване на връзката</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> -</resources>
--- a/res/values-ca/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Client SSH simple, potent i lliure</string> - <string name="service_desc">Manté les connexions SSH i les claus públiques</string> - <string name="title_hosts_list">Servidors</string> - <string name="title_pubkey_list">Claus Públiques</string> - <string name="title_port_forwards_list">Redirecció de Ports</string> - <string name="title_host_editor">Edició del Servidor</string> - <string name="title_help">Ajuda</string> - <string name="title_colors">Colors</string> - <string name="resolve_connect">Connecta</string> - <string name="resolve_entropy">Recull Entropia</string> - <string name="menu_insert">Afegeix servidor</string> - <string name="menu_delete">Elimina servidor</string> - <string name="menu_preferences">Preferències</string> - <string name="help_intro">Si us plau, esculli un tema per a més informació en aquest assumpte en particular</string> - <string name="help_about">Sobre ConnectBot</string> - <string name="help_keyboard">Teclat</string> - <string name="pubkey_generate">Genera</string> - <string name="pubkey_import">Importa</string> - <string name="pubkey_delete">Elimina la clau</string> - <string name="pubkey_gather_entropy">Recull Entropia</string> - <string name="pubkey_touch_prompt">Toca aquesta caixa per obtenir aleatorietat: %1$d%% completat</string> - <string name="pubkey_touch_hint">Per assegurar l\'aleatorietat durant la generació de la clau, mou el dit aleatoriament per sobre la caixa de sota.</string> - <string name="pubkey_generating">"Generant parell de claus…"</string> - <string name="pubkey_copy_private">Còpia la clau privada</string> - <string name="pubkey_copy_public">Còpia la clau pública</string> - <string name="pubkey_list_empty">Pulsa Menu per crear\no importar parells de claus.</string> - <string name="pubkey_unknown_format">Format desconegut</string> - <string name="pubkey_change_password">Canvia la contrasenya</string> - <string name="pubkey_list_pick">Obté de /sdcard</string> - <string name="pubkey_import_parse_problem">Problema analitzant les claus privades importades</string> - <string name="pubkey_unlock">Desbloqueja clau</string> - <string name="pubkey_failed_add">Contrasenya incorrecta per la clau \'%1$s\'. Autenticació fallada</string> - <string name="pubkey_memory_load">Carrega a la memòria</string> - <string name="pubkey_memory_unload">Descarrega de la memòria</string> - <string name="pubkey_load_on_start">Carrega la clau a l\'inici</string> - <string name="pubkey_confirm_use">Confirmar abans d\'usar</string> - <string name="portforward_list_empty">Pulsa Menu per crear\nredireccions de ports.</string> - <string name="portforward_edit">Edita redireccions de ports</string> - <string name="portforward_delete">Elimina redireccions de ports</string> - <string name="prompt_nickname">Sobrenom:</string> - <string name="prompt_nickname_hint_pubkey">La meva clau</string> - <string name="prompt_source_port">Port d\'origen:</string> - <string name="prompt_destination">Destí:</string> - <string name="prompt_old_password">Contrasenya anterior:</string> - <string name="prompt_password">Contrasenya:</string> - <string name="prompt_again">(altre cop)</string> - <string name="prompt_type">Tipus:</string> - <string name="prompt_password_can_be_blank">Nota: la contrasenya pot ser en blanc</string> - <string name="prompt_bits">Bits</string> - <string name="prompt_pubkey_password">Contrasenya per la clau \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Permet al servidor remot\nutilitzar la clau \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">ALERTA: LA IDENTIFICACIÓ DEL SERVIDOR REMOT HA CANVIAT!</string> - <string name="host_verification_failure_warning">ES POSSIBLE QUE ALGÚ ESTIGUI FENT ALGUNA COSA LLETGA!\nAlgú pot estar escoltant la teva comunicació (atac home-al-mig)!\nTambé és possible que simplement el servidor hagi canviat la clau.</string> - <string name="prompt_host_disconnected">Servidor desconnectat.\nTancar sessió?</string> - <string name="prompt_continue_connecting">Estàs segur que vols\ncontinuar connectant?</string> - <string name="host_authenticity_warning">La autenticació amb el servidor \'%1$s\' no es pot establir.</string> - <string name="host_fingerprint">Servidor %1$s empremta de la clau és %2$s</string> - <string name="alert_passwords_do_not_match_msg">Les contrasenyes no coincideixen!</string> - <string name="alert_wrong_password_msg">La contrasenya no és correcta.</string> - <string name="alert_key_corrupted_msg">Les claus privades semblen malmèses!</string> - <string name="alert_sdcard_absent">La targeta SD no es troba present!</string> - <string name="button_add">Afegeix</string> - <string name="button_change">Canvia</string> - <string name="button_generate">Genera clau</string> - <string name="button_resize">Redimensiona</string> - <string name="alert_disconnect_msg">Connexió perduda</string> - <string name="pref_emulation_category">Emulador del terminal</string> - <string name="pref_emulation_title">Mode d\'emulació</string> - <string name="pref_emulation_summary">Mode d\'emulació de terminal per l\'ús de connexions PTY</string> - <string name="pref_scrollback_title">Tamany de la història</string> - <string name="pref_scrollback_summary">Tamany de la memòria per mantenir la història de cada consola</string> - <string name="pref_ui_category">Interfície d\'usuari</string> - <string name="pref_rotation_title">Mode de rotació</string> - <string name="pref_rotation_summary">Com canvia la orientació quan el teclat s\'obre o es tanca</string> - <string name="pref_fullscreen_title">Pantalla completa</string> - <string name="pref_fullscreen_summary">Amaga la barra d\'estat en consola</string> - <string name="pref_memkeys_title">Recorda les claus en memòria</string> - <string name="pref_memkeys_summary">Manté les claus descarregadesen memòria fins que el servei finalitzi</string> - <string name="pref_update_title">Comprova actualització</string> - <string name="pref_update_summary">Escull la freqüència màxima de comprovació d\'actualitzacions de ConnectBot</string> - <string name="pref_conn_persist_title">Connexions persistents</string> - <string name="pref_conn_persist_summary">Manté les connexions mentre l\'aplicació és en segon pla</string> - <string name="pref_keymode_title">Drecera de carpetes</string> - <string name="pref_keymode_summary">Escull com usar Alt per \'/\' i Shift per Tab</string> - <string name="pref_camera_title">Drecera de càmera</string> - <string name="pref_camera_summary">Escull quina acció fer quan el botó de la càmera es clica</string> - <string name="pref_keepalive_title">Manté la pantalla encesa</string> - <string name="pref_keepalive_summary">Evita que la pantalla s\'apagui mentre s\'usa la consola</string> - <string name="pref_wifilock_title">Manté activa la Wi-Fi</string> - <string name="pref_wifilock_summary">Evita que la Wi-Fi s\'apagui mentre hi ha una sessió activa</string> - <string name="pref_bumpyarrows_title">Cursors vibrants</string> - <string name="pref_bumpyarrows_summary">Vibra quan s\'envien els cursors de direcció amb la rodeta; útil per connexions lentes</string> - <string name="pref_bell_category">So del Terminal</string> - <string name="pref_bell_title">So activat</string> - <string name="pref_bell_volume_title">Volum del so</string> - <string name="pref_bell_vibrate_title">Vibra en sonar</string> - <string name="pref_bell_notification_title">Notificacions en rerefons</string> - <string name="pref_bell_notification_summary">Envia notificacions quan un terminal actiu al rerefons envia una senyal de so.</string> - <string name="list_keymode_right">Utilitza les tecles de la dreta</string> - <string name="list_keymode_left">Utilitza les tecles de l\'esquerra</string> - <string name="list_keymode_none">Deshabilita</string> - <string name="list_pubkeyids_none">No usis claus</string> - <string name="list_pubkeyids_any">Fes servir qualsevol clau desbloquejada</string> - <string name="hostpref_nickname_title">Sobrenom</string> - <string name="hostpref_color_title">Color de la categoria</string> - <string name="hostpref_fontsize_title">Mida de la lletra (pt)</string> - <string name="hostpref_pubkeyid_title">Usa autenticació de claus públiques</string> - <string name="hostpref_authagent_title">Usa agent d\'autenticació SSH</string> - <string name="hostpref_postlogin_title">Automatització post-entrada</string> - <string name="hostpref_postlogin_summary">Comandes a executar en el servidor remot un cop autenticat.</string> - <string name="hostpref_compression_title">Compressió</string> - <string name="hostpref_compression_summary">Això pot ajudar per xarxes lentes</string> - <string name="hostpref_wantsession_title">Inicia una sessió de shell</string> - <string name="hostpref_wantsession_summary">Deshabilita aquesta preferència per només usar redireccionament de ports</string> - <string name="hostpref_stayconnected_title">Manté connectat</string> - <string name="hostpref_stayconnected_summary">Intenta reconnectar al servidor si es desconnecta</string> - <string name="hostpref_delkey_title">Tecla DEL</string> - <string name="hostpref_delkey_summary">El codi enviat al pulsar la tecla DEL</string> - <string name="hostpref_encoding_title">Codificació</string> - <string name="hostpref_encoding_summary">Codificació de caràcters per el servidor</string> - <string name="hostpref_connection_category">Paràmetres de connexió</string> - <string name="hostpref_username_title">Nom d\'usuari</string> - <string name="hostpref_hostname_title">Servidor</string> - <string name="hostpref_port_title">Port</string> - <string name="bind_never">Mai connectat</string> - <string name="bind_minutes">Fa %1$s minuts</string> - <string name="bind_hours">Fa %1$s hores</string> - <string name="bind_days">Fa %1$s dies</string> - <string name="console_copy_done">Copiats %1$d bytes al porta-retalls</string> - <string name="console_copy_start">Toca i arrosega\no fes servir les tecles de direcció\nper escollir l\'àrea a copiar</string> - <string name="console_menu_close">Tanca</string> - <string name="console_menu_copy">Copia</string> - <string name="console_menu_paste">Enganxa</string> - <string name="console_menu_portforwards">Redireccionament de ports</string> - <string name="console_menu_resize">Força el tamany</string> - <string name="console_menu_urlscan">Llistat de URL</string> - <string name="button_yes">Sí</string> - <string name="button_no">No</string> - <string name="portforward_local">Local</string> - <string name="portforward_remote">Remot</string> - <string name="portforward_dynamic">Dinàmic (SOCKS)</string> - <string name="portforward_pos">Crea redireccionament de ports</string> - <string name="portforward_done">Redireccionament creat correctament</string> - <string name="portforward_problem">Problemes creant el redireccionament de ports, potser s\'usen ports per sota del 1024 o el port és en ús actualment?</string> - <string name="portforward_menu_add">Afegeix redireccionament de ports</string> - <string name="hint_userhost">usuari\@servidor</string> - <string name="list_format_error">Usa el format %1$s</string> - <string name="format_username">Usuari</string> - <string name="format_hostname">servidor</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Gestiona Claus</string> - <string name="list_menu_sortcolor">Ordena per color</string> - <string name="list_menu_sortname">Ordena per nom</string> - <string name="list_menu_settings">Arrenjaments</string> - <string name="list_host_disconnect">Desconnecta</string> - <string name="list_host_edit">Edita el servidor</string> - <string name="list_host_portforwards">Edita el redireccionament de ports</string> - <string name="list_host_delete">Elimina servidors</string> - <string name="list_host_empty">Utilitza el quadre de connexió ràpida\nde sota per connectar al servidor</string> - <string name="list_rotation_default">Per defecte</string> - <string name="list_rotation_land">Força horitzontal</string> - <string name="list_rotation_port">Força vertical</string> - <string name="list_rotation_auto">Automàtic</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A llavors Espai</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Res</string> - <string name="list_delkey_backspace">Retrocés</string> - <string name="list_delkey_del">Suprimeix</string> - <string name="delete_message">Estas segur que vols esborrar \'%1$s\'?</string> - <string name="delete_pos">Sí, esborra</string> - <string name="delete_neg">Cancel·la</string> - <string name="wizard_agree">Accepto</string> - <string name="wizard_next">Següent</string> - <string name="wizard_back">Enrere</string> - <string name="terminal_no_hosts_connected">No hi ha servidors connectats actualment</string> - <string name="terminal_connecting">Connectant a %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">Clau de servidor \'%1$s\' verificada: %2$s</string> - <string name="terminal_failed">Verificació de la clau del servidor errònia.</string> - <string name="terminal_using_s2c_algorithm">Algoritme servidor-a-client: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algoritme client-a-servidor: %1$s %2$s</string> - <string name="terminal_using_algorithm">Usant algoritme: %1$s %2$s</string> - <string name="terminal_auth">Intentant autenticar</string> - <string name="terminal_auth_pass">Intentant autenticació de \'contrasenya\'</string> - <string name="terminal_auth_pass_fail">Autenticació amb \'contrasenya\' errònia</string> - <string name="terminal_auth_pubkey_any">Intentant autenticació amb \'claus públiques\' amb totes les claus en memòria</string> - <string name="terminal_auth_pubkey_invalid">La clau pública seleccionada és invàlida, intenta reseleccionar la clau en l\'editor del servidor</string> - <string name="terminal_auth_pubkey_specific">Intentant autenticació amb \'claus públiques\' amb una clau específica</string> - <string name="terminal_auth_pubkey_fail">Mètode d\'autenticació \'claus públiques\' amb clau \'%1$s\' fallit</string> - <string name="terminal_auth_ki">Intentant autenticació \'teclat-interactiu\'</string> - <string name="terminal_auth_ki_fail">Mètode d\'autenticació \'teclat-interactiu\' fallit.</string> - <string name="terminal_auth_fail">[El servidor no admet autenticació amb \'contrasenya\' o \'teclat-interactiu\'.]</string> - <string name="terminal_no_session">La sessió no s\'iniciarà degut a la preferencia de servidor.</string> - <string name="terminal_enable_portfoward">Activa el redireccionament de ports: %1$s</string> - <string name="local_shell_unavailable">Fallada! El shell local no està disponible en aquest telèfon.</string> - <string name="notification_text">%1$s necessita la teva atenció.</string> - <string name="no">No</string> - <string name="with_confirmation">Amb confirmació</string> - <string name="yes">Sí</string> - <string name="exceptions_submit_message">Sembla que ConnectBot ha tingut un problema l\'últim cop que s\'ha iniciat. Enviar la informació de l\'error als desenvolupadors de ConnectBot?</string> - <string name="menu_colors_reset">Reinicia</string> - <string name="app_is_running">El ConnectBot està en marxa</string> - <string name="color_red">vermell</string> - <string name="color_green">verd</string> - <string name="color_blue">blau</string> - <string name="color_gray">gris</string> -</resources>
--- a/res/values-cs/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,198 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Jednoduchý, všestranný, open-source SSH klient</string> - <string name="service_desc">Správa SSH spojení a nahraných klíčů</string> - <string name="title_hosts_list">Hostitelé</string> - <string name="title_pubkey_list">Veřejné klíče</string> - <string name="title_port_forwards_list">Přesměrování portu</string> - <string name="title_host_editor">Upravit hostitele</string> - <string name="title_help">Nápověda</string> - <string name="title_colors">Barvy</string> - <string name="resolve_connect">Připojit</string> - <string name="resolve_entropy">Získat entropii</string> - <string name="menu_insert">Přidat hostitele</string> - <string name="menu_delete">Smazat hostitele</string> - <string name="menu_preferences">Nastavení</string> - <string name="help_intro">Prosím, vyberte následující téma pro více informací na daný subjekt.</string> - <string name="help_about">O aplikaci ConnectBot</string> - <string name="help_keyboard">Klávesnice</string> - <string name="pubkey_generate">Vygenerovat</string> - <string name="pubkey_import">Importovat</string> - <string name="pubkey_delete">Smazat klíč</string> - <string name="pubkey_gather_entropy">Získávání entropie</string> - <string name="pubkey_touch_prompt">Dotkněte se plochy pro získání náhodnosti: %1$d%% hotovo</string> - <string name="pubkey_touch_hint">Pro zajištění náhodnosti během generování klíče pohybujte prstem náhodně po ploše níže.</string> - <string name="pubkey_generating">Generování páru klíčů...</string> - <string name="pubkey_copy_private">Kopírovat soukromý klíč</string> - <string name="pubkey_copy_public">Kopírovat veřejný klíč</string> - <string name="pubkey_list_empty">Zvolte \"Menu\" pro vytvoření\nnebo import párů klíčů.</string> - <string name="pubkey_unknown_format">Neznámý formát</string> - <string name="pubkey_change_password">Změnit heslo</string> - <string name="pubkey_list_pick">Vyberte z /sdcard</string> - <string name="pubkey_import_parse_problem">Problém s importem soukromého klíče</string> - <string name="pubkey_unlock">Odemknout klíč</string> - <string name="pubkey_failed_add">Špatné heslo pro klíč \'%1$s\'. Ověření selhalo.</string> - <string name="pubkey_memory_load">Nahrát do paměti</string> - <string name="pubkey_memory_unload">Odstranit z paměti</string> - <string name="pubkey_load_on_start">Nahrát klíč při startu</string> - <string name="pubkey_confirm_use">Potvrdit před použitím</string> - <string name="portforward_list_empty">Zvolte \"Menu\" pro vytvoření\npřesměrování portů.</string> - <string name="portforward_edit">Upravit přesměrování portů</string> - <string name="portforward_delete">Smazat přesměrování portů</string> - <string name="prompt_nickname">Přezdívka:</string> - <string name="prompt_nickname_hint_pubkey">Můj pracovní klíč</string> - <string name="prompt_source_port">Zdrojový port:</string> - <string name="prompt_destination">Cíl:</string> - <string name="prompt_old_password">Původní heslo:</string> - <string name="prompt_password">Heslo:</string> - <string name="prompt_again">(znovu)</string> - <string name="prompt_type">Typ:</string> - <string name="prompt_password_can_be_blank">Poznámka: heslo může být prázdné</string> - <string name="prompt_bits">Počet bitů:</string> - <string name="prompt_pubkey_password">Heslo pro klíč \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Povolit vzdálenému počítači\npoužít klíč \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">VAROVÁNÍ: IDENTIFIKACE VZDÁLENÉHO HOSTA SE ZMĚNILA!</string> - <string name="host_verification_failure_warning">JE MOŽNÉ ŽE NĚKDO PROVÁDÍ NĚCO NEKALÉHO!\nNěkdo vás může odposlouchávat (man-in-the-middle)!\nTaké je možné že se klíč počítače právě změnil.</string> - <string name="prompt_host_disconnected">Host se odpojil.\nUkončit sezení?</string> - <string name="prompt_continue_connecting">Opravdu chcete\npokračovat v připojování?</string> - <string name="host_authenticity_warning">Nelze ověřit autenticitu počítače \'%1$s\'.</string> - <string name="host_fingerprint">Otisk klíče počítače %1$s je %2$s</string> - <string name="alert_passwords_do_not_match_msg">Hesla se neshodují!</string> - <string name="alert_wrong_password_msg">Špatné heslo!</string> - <string name="alert_key_corrupted_msg">Soukromý klíč vypadá poškozeně!</string> - <string name="alert_sdcard_absent">Není vložena SD karta!</string> - <string name="button_add">Přidat</string> - <string name="button_change">Změnit</string> - <string name="button_generate">Generovat klíč</string> - <string name="button_resize">Změnit velikost</string> - <string name="alert_disconnect_msg">Spojení ztraceno</string> - <string name="pref_emulation_category">Emulace terminálu</string> - <string name="pref_emulation_title">Režim emulace</string> - <string name="pref_emulation_summary">Režim emulace terminálu použitý při PTY spojeních</string> - <string name="pref_scrollback_title">Velikost historie</string> - <string name="pref_scrollback_summary">Velikost historie uložená v paměti pro každou konzoli</string> - <string name="pref_ui_category">Uživatelské rozhraní</string> - <string name="pref_rotation_title">Režim rotace</string> - <string name="pref_rotation_summary">Jak změnit rotaci když se zobrazí / skryje klávesnice</string> - <string name="pref_fullscreen_title">Celá obrazovka</string> - <string name="pref_fullscreen_summary">Skrýt stavový řádek když je zobrazena konzole</string> - <string name="pref_memkeys_title">Uchovávat klíče v paměti</string> - <string name="pref_memkeys_summary">Ponechat odemčené klíče v paměti dokud není ukončena služba na pozadí</string> - <string name="pref_update_title">Kontrolovat aktualizace</string> - <string name="pref_update_summary">Nastavit maximální frekvenci pro kontrolu aktualizací ConnectBota</string> - <string name="pref_conn_persist_title">Trvalá spojení</string> - <string name="pref_conn_persist_summary">Vynutit spojení i v pozadí</string> - <string name="pref_keymode_title">Zkratky adresářů</string> - <string name="pref_keymode_summary">Volba použití kláves Alt pro znak \"/\" a Shift pro tabulátor</string> - <string name="pref_camera_title">Zkratka fotoaparátu</string> - <string name="pref_camera_summary">Vyberte kterou zkratku použít když je stisknuto tlačítko fotoaparátu</string> - <string name="pref_keepalive_title">Ponechat zapnutou obrazovku</string> - <string name="pref_keepalive_summary">Zabránit obrazovce ve vypnutí při práci v konzoli</string> - <string name="pref_wifilock_title">Ponechat Wi-Fi aktivní</string> - <string name="pref_wifilock_summary">Zabránit Wi-Fi ve vypnutí když je sezení aktivní</string> - <string name="pref_bumpyarrows_title">Hmatová odezva šipek</string> - <string name="pref_bumpyarrows_summary">Vibrovat při posílání kurzorových kláves z trackballu; užitečná pro špatná spojení</string> - <string name="pref_bell_category">Zvonek terminálu</string> - <string name="pref_bell_title">Zvukové upozornění</string> - <string name="pref_bell_volume_title">Hlasitost zvonku</string> - <string name="pref_bell_vibrate_title">Vibrovat při zvonku</string> - <string name="pref_bell_notification_title">Upozornění v pozadí</string> - <string name="pref_bell_notification_summary">Zobrazit upozornění když terminál běžící v pozadí zazvoní zvonkem</string> - <string name="list_keymode_right">Použít klávesy napravo</string> - <string name="list_keymode_left">Použít klávesy nalevo</string> - <string name="list_keymode_none">Vypnout</string> - <string name="list_pubkeyids_none">Nepoužívat klíče</string> - <string name="list_pubkeyids_any">Použít jakýkoliv odemčený klíč</string> - <string name="hostpref_nickname_title">Přezdívka</string> - <string name="hostpref_color_title">Barevná kategorie</string> - <string name="hostpref_fontsize_title">Velikost fontu (pt)</string> - <string name="hostpref_pubkeyid_title">Použít autentizaci veřejným klíčem</string> - <string name="hostpref_authagent_title">Použít SSH autorizačního agenta</string> - <string name="hostpref_postlogin_title">Automatizace po přihlášení</string> - <string name="hostpref_postlogin_summary">Příkazy které se spustí na vzdáleném serveru po přihlášení</string> - <string name="hostpref_compression_title">Komprese</string> - <string name="hostpref_compression_summary">Může pomoct na pomalejších sítích</string> - <string name="hostpref_wantsession_title">Spustit sezení shellu</string> - <string name="hostpref_wantsession_summary">Vypněte tuto možnost pokud pouze přesměrováváte porty</string> - <string name="hostpref_stayconnected_title">Zůstat připojený</string> - <string name="hostpref_stayconnected_summary">Zkusit se znovu připojit při odpojení</string> - <string name="hostpref_delkey_title">Klávesa DEL</string> - <string name="hostpref_delkey_summary">Kód klávesy odeslaný při stisku DEL</string> - <string name="hostpref_encoding_title">Kódování</string> - <string name="hostpref_encoding_summary">Kódování znaků na hostovi</string> - <string name="hostpref_connection_category">Nastavení připojení</string> - <string name="hostpref_username_title">Uživatelské jméno</string> - <string name="bind_never">Nikdy nepřipojen</string> - <string name="bind_minutes">Před %1$s minutami</string> - <string name="bind_hours">Před %1$s hodinami</string> - <string name="bind_days">Před %1$s dny</string> - <string name="console_copy_done">Zkopírováno %1$d bajtů do schránky</string> - <string name="console_copy_start">Stiskněte a táhněte\nnebo použijte směrový ovladač\npro výběr oblasti ke zkopírování</string> - <string name="console_menu_close">Zavřít</string> - <string name="console_menu_copy">Kopírovat</string> - <string name="console_menu_paste">Vložit</string> - <string name="console_menu_portforwards">Přesměrování portů</string> - <string name="console_menu_resize">Vynutit velikost</string> - <string name="console_menu_urlscan">Najít URL</string> - <string name="button_yes">Ano</string> - <string name="button_no">Ne</string> - <string name="portforward_local">Místní</string> - <string name="portforward_remote">Vzdálený</string> - <string name="portforward_dynamic">Dynamický (SOCKS)</string> - <string name="portforward_pos">Vytvořit přesměrování portu</string> - <string name="portforward_done">Přesměrování portu úspěšně vytvořeno</string> - <string name="portforward_menu_add">Přidat přesměrování portu</string> - <string name="hint_userhost">user\@hostname</string> - <string name="list_format_error">Použijte formát %1$s</string> - <string name="format_username">uživatelské jméno</string> - <string name="format_hostname">jméno hosta</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Spravovat veřejné klíče</string> - <string name="list_menu_sortcolor">Seřadit podle barvy</string> - <string name="list_menu_sortname">Seřadit podle jména</string> - <string name="list_menu_settings">Nastavení</string> - <string name="list_host_disconnect">Odpojit</string> - <string name="list_host_edit">Upravit hosta</string> - <string name="list_host_portforwards">Upravit přesměrování portů</string> - <string name="list_host_delete">Smazat hosta</string> - <string name="list_host_empty">Použijte pole rychlého připojení\nníže pro připojení k hostovi.</string> - <string name="list_rotation_default">Standardní</string> - <string name="list_rotation_land">Vynutit na šířku</string> - <string name="list_rotation_port">Vynutit na výšku</string> - <string name="list_rotation_auto">Automaticky</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A potom mezerník</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Nic</string> - <string name="list_delkey_backspace">Backspace</string> - <string name="list_delkey_del">Delete</string> - <string name="delete_message">Určitě chcete smazat \'%1$s\'?</string> - <string name="delete_pos">Ano, smazat</string> - <string name="delete_neg">Zrušit</string> - <string name="wizard_agree">Souhlasím</string> - <string name="wizard_next">Další</string> - <string name="wizard_back">Zpět</string> - <string name="terminal_no_hosts_connected">Žádný host není připojený</string> - <string name="terminal_connecting">Připojování k %1$s:%2$d přes %3$s</string> - <string name="terminal_failed">Selhalo ověření klíče hosta</string> - <string name="terminal_using_s2c_algorithm">Algoritmus server-klient: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algoritmus klient-server: %1$s %2$s</string> - <string name="terminal_using_algorithm">Použitý algoritmus: %1$s %2$s</string> - <string name="terminal_auth">Pokus o autentizaci</string> - <string name="terminal_auth_pubkey_invalid">Vybraný veřejný klič je neplatný, zkuste jej znovu vybrat při úpravě hosta</string> - <string name="terminal_no_session">Sezení nebude spuštěno kvůli nastavení hosta.</string> - <string name="terminal_enable_portfoward">Povolit přesměrování portu: %1$s</string> - <string name="local_shell_unavailable">Selhání! Místní shell není na tomto telefonu podporován</string> - <string name="notification_text">%1$s žádá pozornost.</string> - <string name="no">Ne</string> - <string name="with_confirmation">S potvrzením</string> - <string name="yes">Ano</string> - <string name="exceptions_submit_message">Vypadá to že měl ConnectBot problém když naposledy běžel. Odeslat hlášení o chybě vývojářům ConnectBota?</string> - <string name="menu_colors_reset">Obnovit</string> - <string name="app_is_running">ConnectBot běží</string> - <string name="color_red">červená</string> - <string name="color_green">zelená</string> - <string name="color_blue">modrá</string> - <string name="color_gray">šedá</string> -</resources>
--- a/res/values-da/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Enkel, kraftfuld, open source SSH klient</string> - <string name="service_desc">Opretholder SSH forbindelser og indlæste offentlige nøgler</string> - <string name="title_hosts_list">Værter</string> - <string name="title_pubkey_list">Offentlige nøgler</string> - <string name="title_port_forwards_list">Port-videresendelser</string> - <string name="title_host_editor">Rediger vært</string> - <string name="title_help">Hjælp</string> - <string name="title_colors">Farver</string> - <string name="resolve_connect">Tilslut</string> - <string name="resolve_entropy">Indsamler entropi</string> - <string name="menu_insert">Tilføj vært</string> - <string name="menu_delete">Fjern vært</string> - <string name="menu_preferences">Egenskaber</string> - <string name="help_intro">Vælg et emne nedenfor for yderligere information.</string> - <string name="help_about">Om ConnectBot</string> - <string name="help_keyboard">Tastatur</string> - <string name="pubkey_generate">Opret</string> - <string name="pubkey_import">Importér</string> - <string name="pubkey_delete">Slet nøgle</string> - <string name="pubkey_gather_entropy">Indsamler entropi</string> - <string name="pubkey_touch_prompt">Berør denne boks for at generere tilfældighed: %1$d%% færdig</string> - <string name="pubkey_touch_hint">For at garantere tilfældig data til oprettelse af nøglen, skal du flytte din finger tilfældigt indenfor boksen nedenfor.</string> - <string name="pubkey_generating">"Opretter nøglepar…"</string> - <string name="pubkey_copy_private">Kopier privat nøgle</string> - <string name="pubkey_copy_public">Kopier offentlig nøgle</string> - <string name="pubkey_list_empty">Tryk Menu for at oprette\nog importere nøglepar.</string> - <string name="pubkey_unknown_format">Ukendt format</string> - <string name="pubkey_change_password">Ændre adgangskode</string> - <string name="pubkey_list_pick">Vælg fra /sdcard</string> - <string name="pubkey_import_parse_problem">Fejl ved indlæsning af privat nøgle</string> - <string name="pubkey_unlock">Lås nøgle op</string> - <string name="pubkey_failed_add">Forkert adgangskode for nøglen \'%1$s\'. Autorisering mislykkedes.</string> - <string name="pubkey_memory_load">Indlæs i hukommelse</string> - <string name="pubkey_memory_unload">Fjern fra hukommelse</string> - <string name="pubkey_load_on_start">Indlæs nøgle ved start</string> - <string name="pubkey_confirm_use">Bekræft før brug</string> - <string name="portforward_list_empty">Tryk Menu for at oprette\nport-videresendelser.</string> - <string name="portforward_edit">Rediger port-videresendelse</string> - <string name="portforward_delete">Slet port-videresendelse</string> - <string name="prompt_nickname">Kaldenavn:</string> - <string name="prompt_nickname_hint_pubkey">Min arbejdsnøgle</string> - <string name="prompt_source_port">Kildeport:</string> - <string name="prompt_destination">Destination:</string> - <string name="prompt_old_password">Gammel adgangskode:</string> - <string name="prompt_password">Adgangskode:</string> - <string name="prompt_again">(igen)</string> - <string name="prompt_type">Type:</string> - <string name="prompt_password_can_be_blank">Bemærk: Adgangskoden kan være blank</string> - <string name="prompt_bits">Bit:</string> - <string name="prompt_pubkey_password">Adgangskode for nøglen \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Tillad fjernvært at\nbruge nøglen \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">ADVARSEL: FJERNVÆRTENS IDENTIFIKATION ER ÆNDRET!</string> - <string name="host_verification_failure_warning">DET ER MULIGT AT NOGEN FORETAGER SIG BESKIDTE HANDLINGER!\nDer er mulighed for at nogen aflytter dig (man-in-the-middle angreb)!\nDet er også muligt at værtens nøgle er blevet skiftet.</string> - <string name="prompt_host_disconnected">Værten har afbrudt forbindelsen.\nLuk session?</string> - <string name="prompt_continue_connecting">Er du sikker på at du ønsker\nat skabe forbindelse?</string> - <string name="host_authenticity_warning">Ægtheden for værten \'%1$s\' kan ikke påvises.</string> - <string name="host_fingerprint">%1$s nøgle fingeraftryk er %2$s</string> - <string name="alert_passwords_do_not_match_msg">Adgangskoderne er ikke ens!</string> - <string name="alert_wrong_password_msg">Forkert adgangskode!</string> - <string name="alert_key_corrupted_msg">Privat nøgle synes ødelagt!</string> - <string name="alert_sdcard_absent">SD-kort er ikke sat i!</string> - <string name="button_add">Tilføj</string> - <string name="button_change">Ændre</string> - <string name="button_generate">Opret nøgle</string> - <string name="button_resize">Ændre størrelse</string> - <string name="alert_disconnect_msg">Forbindelse tabt</string> - <string name="pref_emulation_category">Terminal emulering</string> - <string name="pref_emulation_title">Emulerings metode</string> - <string name="pref_emulation_summary">Terminal emulerings metode til brug ved PTY forbindelser</string> - <string name="pref_scrollback_title">Rul-tilbage buffer</string> - <string name="pref_scrollback_summary">Størrelsen af rul-tilbage bufferen for hver konsol</string> - <string name="pref_ui_category">Brugerflade</string> - <string name="pref_rotation_title">Rotations tilstand</string> - <string name="pref_rotation_summary">Hvordan skærmen roteres når keyboard skubbes ind/ud</string> - <string name="pref_fullscreen_title">Fuld skærm</string> - <string name="pref_fullscreen_summary">Skjul statusbar i konsol</string> - <string name="pref_memkeys_title">Husk nøgler i hukommelsen</string> - <string name="pref_memkeys_summary">Gem oplåste nøgler i hukommelsen indtil baggrunds servicen er afsluttet</string> - <string name="pref_update_title">Opdaterings tjek</string> - <string name="pref_update_summary">Maksimal tid mellem check for opdateringer til ConnectBot</string> - <string name="pref_conn_persist_title">Vedvarende forbindelser</string> - <string name="pref_conn_persist_summary">Tving forbindelser til at være aktive i baggrunden</string> - <string name="pref_keymode_title">Biblioteksgenveje</string> - <string name="pref_keymode_summary">Vælg hvordan Alt for \'/\' og Skift for Tabulater skal bruges</string> - <string name="pref_camera_title">Kamera genveje</string> - <string name="pref_camera_summary">Vælg genvej som kamera-knap skal aktivere</string> - <string name="pref_keepalive_title">Hold skærm tændt</string> - <string name="pref_keepalive_summary">Undgå skærm slukker når der arbejdes i en konsol</string> - <string name="pref_wifilock_title">Hold Wi-Fi aktiv</string> - <string name="pref_wifilock_summary">Undgå at Wi-Fi slår fra imens en session er aktiv</string> - <string name="pref_bumpyarrows_title">Vibrerende pile</string> - <string name="pref_bumpyarrows_summary">Vibrér når der afsendes piletaster fra trackballen; nyttig ved langsomme forbindelser</string> - <string name="pref_bell_category">Terminalklokke</string> - <string name="pref_bell_title">Hørbar klokke</string> - <string name="pref_bell_volume_title">Klokke volume</string> - <string name="pref_bell_vibrate_title">Vibrér når klokken ringer</string> - <string name="pref_bell_notification_title">Baggrundspåmindelser</string> - <string name="pref_bell_notification_summary">Send påmindelse når en terminal, der kører i baggrunden, ringer med klokken.</string> - <string name="list_keymode_right">Anvend taster på højre side</string> - <string name="list_keymode_left">Anvend taster på venstre side</string> - <string name="list_keymode_none">Slå fra</string> - <string name="list_pubkeyids_none">Brug ikke tasterne</string> - <string name="list_pubkeyids_any">Anvend enhver ulåst nøgle</string> - <string name="hostpref_nickname_title">Kaldenavn</string> - <string name="hostpref_color_title">Farvekategori</string> - <string name="hostpref_fontsize_title">Skriftstørrelse (pt)</string> - <string name="hostpref_pubkeyid_title">Brug offentlig nøgleautorisering</string> - <string name="hostpref_authagent_title">Brug SSH godkendelses klient</string> - <string name="hostpref_postlogin_title">Post-login automatik</string> - <string name="hostpref_postlogin_summary">Udfør kommandoer på fjernserveren efter autorisering</string> - <string name="hostpref_compression_title">Komprimering</string> - <string name="hostpref_compression_summary">Dette kan hjælpe på langsomme netværk</string> - <string name="hostpref_wantsession_title">Start konsol session</string> - <string name="hostpref_wantsession_summary">Deaktiver denne præference og brug kun port-videresendelser</string> - <string name="hostpref_stayconnected_title">Oprethold forbindelse</string> - <string name="hostpref_stayconnected_summary">Forbind igen hvis forbindelsen tabes</string> - <string name="hostpref_delkey_title">Slet tast</string> - <string name="hostpref_delkey_summary">Tast som sendes når slet tasten benyttes</string> - <string name="hostpref_encoding_title">Tekstkodning</string> - <string name="hostpref_encoding_summary">Tekstkodning for værten</string> - <string name="hostpref_connection_category">Forbindelsesindstillinger</string> - <string name="hostpref_username_title">Brugernavn</string> - <string name="hostpref_hostname_title">Vært</string> - <string name="hostpref_port_title">Port</string> - <string name="bind_never">Aldrig forbundet</string> - <string name="bind_minutes">%1$s minutter siden</string> - <string name="bind_hours">%1$s timer siden</string> - <string name="bind_days">%1$s dage siden</string> - <string name="console_copy_done">Kopier %1$d byte til udklipsholder</string> - <string name="console_copy_start">Berør og flyt\neller brug piletasterne\nfor at vælge område at kopiere</string> - <string name="console_menu_close">Luk</string> - <string name="console_menu_copy">Kopier</string> - <string name="console_menu_paste">Indsæt</string> - <string name="console_menu_portforwards">Port-videresendelser</string> - <string name="console_menu_resize">Tving størrelse</string> - <string name="console_menu_urlscan">URL skan</string> - <string name="button_yes">Ja</string> - <string name="button_no">Nej</string> - <string name="portforward_local">Lokal</string> - <string name="portforward_remote">Fjern</string> - <string name="portforward_dynamic">Dynamisk (SOCKS)</string> - <string name="portforward_pos">Opret port-videresendelse</string> - <string name="portforward_done">Port-videresendelse oprettet</string> - <string name="portforward_problem">Der opstod problemer ved oprettelsen af port-videresendelse. Måske bruger du en port lavere end 1025, eller en port som allerede er i brug.</string> - <string name="portforward_menu_add">Tilføj port-videresendelse</string> - <string name="hint_userhost">brugernavn\@vært</string> - <string name="list_format_error">Anvend formatet %1$s</string> - <string name="format_username">brugernavn</string> - <string name="format_hostname">værtsnavn</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Administrer offentlige nøgler</string> - <string name="list_menu_sortcolor">Sortér efter farve</string> - <string name="list_menu_sortname">Sortér efter navn</string> - <string name="list_menu_settings">Indstillinger</string> - <string name="list_host_disconnect">Afbryd forbindelse</string> - <string name="list_host_edit">Redigér vært</string> - <string name="list_host_portforwards">Redigér port-videresendelser</string> - <string name="list_host_delete">Slet vært</string> - <string name="list_host_empty">Anvend hurtig boksen nedenfor\nfor at oprette forbindelse\ntil en vært.</string> - <string name="list_rotation_default">Standard</string> - <string name="list_rotation_land">Fremtving liggende</string> - <string name="list_rotation_port">Fremtving stående</string> - <string name="list_rotation_auto">Automatisk</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A derefter mellemrum</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Ingen</string> - <string name="list_delkey_backspace">Slet tilbage</string> - <string name="list_delkey_del">Slet</string> - <string name="delete_message">Er du sikker på at du vil slette \'%1$s\'?</string> - <string name="delete_pos">Ja, slet</string> - <string name="delete_neg">Afbryd</string> - <string name="wizard_agree">Godkend</string> - <string name="wizard_next">Næste</string> - <string name="wizard_back">Tilbage</string> - <string name="terminal_no_hosts_connected">Ingen forbindelser aktive i øjeblikket</string> - <string name="terminal_connecting">Forbinder til %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">Verificeret vært \'%1$s\' nøgle: %2$s</string> - <string name="terminal_failed">Verifikation af værtsnøgle mislykkedes.</string> - <string name="terminal_using_s2c_algorithm">Server-til-klient algoritme: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Klient-til-server algoritme: %1$s %2$s</string> - <string name="terminal_using_algorithm">Bruger algoritme: %1$s %2$s</string> - <string name="terminal_auth">Forsøger at autorisere</string> - <string name="terminal_auth_pass">Forsøger adgangskode-autorisering</string> - <string name="terminal_auth_pass_fail">Autoriseringsmetoden adgangskode mislykkedes</string> - <string name="terminal_auth_pubkey_any">Forsøger \'publickey\'-autorisering med enhver offentlig nøgle i hukommelsen</string> - <string name="terminal_auth_pubkey_invalid">Valgte offentlige nøgle er ugyldig, prøv at vælge nøglen igen</string> - <string name="terminal_auth_pubkey_specific">Forsøger \'publickey\'-autorisering med valgte offentlige nøgle</string> - <string name="terminal_auth_pubkey_fail">Autentifikationsmetoden \'publickey\' med nøglen \'%1$s\' fejlede</string> - <string name="terminal_auth_ki">Forsøger \'keyboard-interactive\' autorisering</string> - <string name="terminal_auth_ki_fail">\'keyboard-interactive\'-autorisering fejlede</string> - <string name="terminal_auth_fail">[Din vært understøtter ikke \'password\' eller \'keyboard-interactive\' autorisering.]</string> - <string name="terminal_no_session">Sessionen kunne ikke startes pga. værtens preferencer</string> - <string name="terminal_enable_portfoward">Aktiver port-videresendelse: %1$s</string> - <string name="local_shell_unavailable">Fejl! Lokal konsol er ikke tilgængelig på denne telefon.</string> - <string name="notification_text">%1$s vil have din opmærksomhed.</string> - <string name="no">Nej</string> - <string name="with_confirmation">Med godkendelse</string> - <string name="yes">Ja</string> - <string name="exceptions_submit_message">ConnectBot havde tilsyneladende problemer sidste gang det blev brugt. Send fejlrapport til ConnectBot udviklerne?</string> - <string name="menu_colors_reset">Nulstil</string> - <string name="app_is_running">ConnectBot kører</string> - <string name="color_red">rød</string> - <string name="color_green">grøn</string> - <string name="color_blue">blå</string> - <string name="color_gray">grå</string> -</resources>
--- a/res/values-de/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,325 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Einfacher, mächtiger, open-source SSH client.</string> - <string name="service_desc">Hält SSH-Verbindungen und geladene öffentliche Schlüssel aufrecht</string> - <string name="auth_agent_service_desc">Handelt als SSH-Agent für andere Anwendungen am Gerät</string> - <string name="ssh_agent_permission_label">Im SSH-Agent gespeicherte Schlüssel verwenden</string> - <string name="ssh_agent_permission_desc">Erlaubt der Anwendung SSH-Transaktionen zu authentifizieren mit Ihren im ConnectBot gespeicherten Privatschlüsseln. - SEHR GEFÄHRLICH - kann von böswilligen Anwendungen mißbraucht werden.</string> - <string name="title_hosts_list">Hosts</string> - <string name="title_pubkey_list">Öffentliche Schlüssel</string> - <string name="title_port_forwards_list">Port-Weiterleitungen</string> - <string name="title_host_editor">Host bearbeiten</string> - <string name="title_help">Hilfe</string> - <string name="title_colors">Farben</string> - <string name="resolve_connect">Verbinden</string> - <string name="resolve_entropy">Sammle Entropie</string> - <string name="menu_insert">Host hinzufügen</string> - <string name="menu_delete">Host löschen</string> - <string name="menu_preferences">Einstellungen</string> - <string name="help_intro">Für mehr Informationen wählen Sie eine Überschrift!</string> - <string name="help_about">Über ConnectBot</string> - <string name="help_keyboard">Tastatur</string> - <string name="pubkey_generate">Erzeugen</string> - <string name="pubkey_import">Importieren</string> - <string name="pubkey_delete">Schlüssel löschen</string> - <string name="pubkey_gather_entropy">Sammle Entropie</string> - <string name="pubkey_touch_prompt">Berühren Sie diese Box, um Zufallszahlen zu erzeugen: %1$d%% fertig</string> - <string name="pubkey_touch_hint">Um eine gute Zufallsverteilung zu gewährleisten, bewegen Sie Ihren Finger zufällig über die Box unten!</string> - <string name="pubkey_generating">"Erzeuge Schlüsselpaar…"</string> - <string name="pubkey_copy_private">Privaten Schlüssel kopieren</string> - <string name="pubkey_copy_public">Öffentlichen Schlüssel kopieren</string> - <string name="pubkey_list_empty">\"Menu\" drücken, um Schlüsselpaare\nzu erzeugen oder zu importieren.</string> - <string name="pubkey_unknown_format">Unbekanntes Format</string> - <string name="pubkey_change_password">Passwort ändern</string> - <string name="pubkey_list_pick">Wähle von /sdcard</string> - <string name="pubkey_import_parse_problem">Fehler beim Parsen des importierten, geheimen Schlüssels</string> - <string name="pubkey_unlock">Schlüssel entsperren</string> - <string name="pubkey_failed_add">Falsches Passwort für Schlüssel \'%1$s\'. Legitimation fehlgeschlagen.</string> - <string name="pubkey_memory_load">In Speicher laden</string> - <string name="pubkey_memory_unload">Aus Speicher entfernen</string> - <string name="pubkey_load_on_start">Schlüssel beim Start laden</string> - <string name="pubkey_confirm_use">Bestätigen vor Benutzung</string> - <string name="portforward_list_empty">Auf \"Menu\" tippen um Port-\nWeiterleitungen zu erstellen.</string> - <string name="portforward_edit">Port-Weiterleitung bearbeiten.</string> - <string name="portforward_delete">Port-Weiterleitung löschen.</string> - <string name="prompt_nickname">Spitzname:</string> - <string name="prompt_nickname_hint_pubkey">Mein Schlüssel</string> - <string name="prompt_source_port">Quellport</string> - <string name="prompt_destination">Ziel:</string> - <string name="prompt_old_password">Altes Passwort:</string> - <string name="prompt_password">Passwort:</string> - <string name="prompt_again">(nochmal)</string> - <string name="prompt_type">Typ:</string> - <string name="prompt_password_can_be_blank">Hinweis: Passwort kann leer bleiben</string> - <string name="prompt_bits">Bits:</string> - <string name="prompt_pubkey_password">Passwort für Schlüssel \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Remote Host die Benutzung\ndes Schlüssels \'%1$s\' erlauben?</string> - <string name="host_verification_failure_warning_header">WARNUNG: IDENTIFIKATION DES ENTFERNTEN HOSTS HAT SICH GEÄNDERT!</string> - <string name="host_verification_failure_warning">MÖGLICHERWEISE TUT JEMAND ETWAS BÖSES!\nJemand könnte Sie jetzt gerade belauschen (man-in-the-middle attack)!\nEs ist auch möglich, dass nur der Host-Key geändert wurde.</string> - <string name="prompt_host_disconnected">Der Host hat die Verbindung beendet.\nSitzung schließen?</string> - <string name="prompt_continue_connecting">Sind Sie sicher, dass Sie\neine Verbindung herstellen wollen?</string> - <string name="host_authenticity_warning">Die Authentizität von Host \'%1$s\' kann nicht garantiert werden.</string> - <string name="host_fingerprint">Host %1$ss Schlüssel Fingerabdruck ist %2$s</string> - <string name="alert_passwords_do_not_match_msg">Passwörter stimmen nicht überein!</string> - <string name="alert_wrong_password_msg">Falsches Passwort!</string> - <string name="alert_key_corrupted_msg">Geheimer Schlüssel scheint korrupt!</string> - <string name="alert_sdcard_absent">SD-Karte nicht eingesteckt!</string> - <string name="button_add">Hinzufügen</string> - <string name="button_change">Ändern</string> - <string name="button_generate">Schlüssel erzeugen</string> - <string name="button_resize">Größe ändern</string> - <string name="button_resize_reset">Standardgröße</string> - <string name="alert_disconnect_msg">Die Verbindung wurde getrennt.</string> - <string name="pref_emulation_category">Terminalemulation</string> - <string name="pref_emulation_title">Emulationsmodus</string> - <string name="pref_emulation_summary">Terminalemulationsmodus für PTY Verbindungen</string> - <string name="pref_scrollback_title">Bildlaufpuffergröße</string> - <string name="pref_scrollback_summary">Größe des Bildlaufpuffers, der für jede Konsole im Speicher gehalten wird</string> - <string name="pref_ui_category">Benutzungsschnittstelle</string> - <string name="pref_rotation_title">Rotationsmodus</string> - <string name="pref_rotation_summary">Wie soll die Rotation beim Ein-/Ausklappen der Tastatur verändert werden</string> - <string name="pref_memkeys_title">Schlüssel im Speicher behalten</string> - <string name="pref_memkeys_summary">Entsperrte Schlüssel im Speicher halten, bis der Hintergrunddienst beendet wurde</string> - <string name="pref_update_title">Aktualisierungen suchen</string> - <string name="pref_update_summary">Die maximale Frequenz einstellen, mit der nach ConnectBot Aktualisierungen gesucht werden soll</string> - <string name="pref_conn_persist_title">Persistente Verbindungen</string> - <string name="pref_conn_persist_summary">Erhalte Verbindungen auch im Hintergrund</string> - <string name="pref_keymode_title">Verzeichniskürzel</string> - <string name="pref_keymode_summary">Einstellen, wie Alt für \'/\' und Hochstellen für \'Tab\' verwendet werden sollen</string> - <string name="pref_camera_title">Kamerataste</string> - <string name="pref_camera_summary">Aktion, die beim Drücken der Kamera-Taste ausgeführt wird</string> - <string name="pref_volup_title">Lauter-Taste</string> - <string name="pref_volup_summary">Aktion, die beim Drücken der Lauter-Taste ausgeführt wird</string> - <string name="pref_voldn_title">Leiser-Taste</string> - <string name="pref_voldn_summary">Aktion, die beim Drücken der Leiser-Taste ausgeführt wird</string> - <string name="pref_search_title">Suchtaste</string> - <string name="pref_search_summary">Aktion, die beim Drücken der Suchtaste ausgeführt wird</string> - <string name="pref_keepalive_title">Bildschirm anlassen</string> - <string name="pref_keepalive_summary">Verhindern, dass beim Arbeiten an der Konsole der Bildschirm abgeschaltet wird</string> - <string name="pref_wifilock_title">WLAN aktiviert lassen</string> - <string name="pref_wifilock_summary">Verhindern, dass während einer aktiven Sitzung WLAN deaktiviert wird</string> - <string name="pref_bumpyarrows_title">Vibrierende Pfeiltasten</string> - <string name="pref_bumpyarrows_summary">Vibirieren, wenn Pfeiltasten vom Trackball gesendet werden; nützlich bei laggenden Verbindungen</string> - <string name="pref_bell_category">Terminalglocke</string> - <string name="pref_bell_title">Hörbare Glocke</string> - <string name="pref_bell_volume_title">Glockenlautstärke</string> - <string name="pref_bell_vibrate_title">Bei Glocke vibrieren</string> - <string name="pref_bell_notification_title">Hintergrundnotiz</string> - <string name="pref_bell_notification_summary">Benachrichtigen, wenn ein im Hintergrund laufendendes Terminal eine Glocke erklingen lässt.</string> - <string name="list_keymode_right">Tasten rechts verwenden</string> - <string name="list_keymode_left">Tasten links verwenden</string> - <string name="list_keymode_none">Ausschalten</string> - <string name="list_pubkeyids_none">Keine Schlüssel verwenden</string> - <string name="list_pubkeyids_any">Beliebigen entsperrten Schlüssel verwenden</string> - <string name="hostpref_nickname_title">Nutzername</string> - <string name="hostpref_color_title">Farbkategorie</string> - <string name="hostpref_fontsize_title">Fontgröße (pt)</string> - <string name="hostpref_pubkeyid_title">Verwende pubkey Authentisierung</string> - <string name="hostpref_authagent_title">SSH auth agent benutzen?</string> - <string name="hostpref_postlogin_title">Post-Login Automatisierung</string> - <string name="hostpref_postlogin_summary">Befehle, die auf dem entfernten Host nach der Anmeldung gestartet werden sollen.</string> - <string name="hostpref_compression_title">Kompression</string> - <string name="hostpref_compression_summary">Dies könnte bei langsamen Netzwerken helfen</string> - <string name="hostpref_wantsession_title">Kommandozeilensitzung starten</string> - <string name="hostpref_wantsession_summary">Diese Einstellung abwählen, um ausschließlich Port-Weiterleitungen zu verwenden</string> - <string name="hostpref_stayconnected_title">Verbindung halten</string> - <string name="hostpref_stayconnected_summary">Verbindung bei Verbindungsabbruch wiederherstellen</string> - <string name="hostpref_delkey_title">DEL Taste</string> - <string name="hostpref_delkey_summary">Zu sendender Tastencode wenn DEL gedrückt wird</string> - <string name="hostpref_encoding_title">Zeichensatz</string> - <string name="hostpref_encoding_summary">Zeichen-Encoding für den Host</string> - <string name="hostpref_connection_category">Verbindungseinstellungen</string> - <string name="hostpref_username_title">Benutzername</string> - <string name="hostpref_hostname_title">Host</string> - <string name="hostpref_port_title">Port</string> - <string name="hostpref_x11_forwarding">"X11-Weiterleitung"</string> - <string name="hostpref_wantx11forward_title">"X11-Weiterleitung aktivieren"</string> - <string name="hostpref_wantx11forward_summary">"X11-Sitzungen an unten angegebenen Host und Port weiterleiten"</string> - <string name="hostpref_x11host_title">"Host für X11-Weiterleitung"</string> - <string name="hostpref_x11port_title">"Port für X11-Weiterleitung"</string> - <string name="bind_never">Nie verbunden</string> - <string name="bind_minutes">vor %1$s Minuten</string> - <string name="bind_hours">vor %1$s Stunden</string> - <string name="bind_days">vor %1$s Tagen</string> - <string name="console_copy_done">%1$d Byte in die Zwischenablage kopiert</string> - <string name="console_copy_start">Berühren und ziehen\noder Trackball verwenden\num zu kopierenden Bereich auszuwählen</string> - <string name="console_menu_close">Schließen</string> - <string name="console_menu_copy">Kopieren</string> - <string name="console_menu_paste">Einfügen</string> - <string name="console_menu_portforwards">Port-Weiterleitungen</string> - <string name="console_menu_resize">Größe erzwingen</string> - <string name="console_menu_urlscan">URL Scan</string> - <string name="console_menu_screencapture">Bildschirmfoto</string> - <string name="console_menu_download">"Datei herunterladen"</string> - <string name="console_menu_upload">"Datei hochladen"</string> - <string name="button_yes">Ja</string> - <string name="button_no">Nein</string> - <string name="portforward_local">Lokal</string> - <string name="portforward_remote">Entfernt</string> - <string name="portforward_dynamic">Dynamisch (SOCKS)</string> - <string name="portforward_pos">Port-Weiterleitung anlegen</string> - <string name="portforward_done">Port-Weiterleitung angelegt.</string> - <string name="portforward_problem">Konnte Port-Weiterleitung nicht anlegen. Verwenden Sie Ports kleiner als 1024, oder wird der Port bereits verwendet?</string> - <string name="portforward_menu_add">Port-Weiterleitung hinzufügen</string> - <string name="hint_userhost">benutzer\@host</string> - <string name="list_format_error">Benutze das Format %1$s</string> - <string name="format_username">Benutzer</string> - <string name="format_hostname">Host</string> - <string name="format_port">Port</string> - <string name="list_menu_pubkeys">Pubkeys verwalten</string> - <string name="list_menu_sortcolor">Nach Farbe sortieren</string> - <string name="list_menu_sortname">Nach Name sortieren</string> - <string name="list_menu_settings">Einstellungen</string> - <string name="list_host_disconnect">Verbindung trennen</string> - <string name="list_host_edit">Host editieren</string> - <string name="list_host_portforwards">Port-Weiterleitungen editieren</string> - <string name="list_host_delete">Host löschen</string> - <string name="list_host_empty">Benutzen Sie die quick-connect box\nunten um sich mit einem Host zu verbinden.</string> - <string name="list_rotation_default">Vorgabe</string> - <string name="list_rotation_land">Querformat erzwingen</string> - <string name="list_rotation_port">Hochformat erzwingen</string> - <string name="list_rotation_auto">Automatisch</string> - <string name="list_hwbutton_screen_capture">Screenshot</string> - <string name="list_hwbutton_ctrl">CTRL</string> - <string name="list_hwbutton_tab">Tab</string> - <string name="list_hwbutton_ctrlaspace">Strg+A dann Space</string> - <string name="list_hwbutton_ctrla">Strg+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Nichts</string> - <string name="list_delkey_backspace">Rücktaste</string> - <string name="list_delkey_del">Entfernen</string> - <string name="delete_message">Soll \'%1$s\' wirklich gelöscht werden?</string> - <string name="delete_pos">Ja, löschen</string> - <string name="delete_neg">Abbrechen</string> - <string name="wizard_agree">Zustimmung</string> - <string name="wizard_next">Weiter</string> - <string name="wizard_back">Zurück</string> - <string name="terminal_no_hosts_connected">Zur Zeit keine Hosts verbunden</string> - <string name="terminal_connecting">Verbinde mit %1$s:%2$d mittels %3$s</string> - <string name="terminal_sucess">Host \'%1$s\' Schlüssel: %2$s bestätigt</string> - <string name="terminal_failed">Überprüfung des Host-Schlüssels fehlgeschlagen.</string> - <string name="terminal_using_s2c_algorithm">Server zu Client Algorithmus: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Client zu Server Algorithmus: %1$s %2$s</string> - <string name="terminal_using_algorithm">Benutze Algorithmus: %1$s %2$s</string> - <string name="terminal_auth">Versuche zu authentisieren.</string> - <string name="terminal_auth_pass">Versuche Authentisierung mit Passwort.</string> - <string name="terminal_auth_pass_fail">Authentisierungsmethode \'Passwort\' fehlgeschlagen.</string> - <string name="terminal_auth_pubkey_any">Versuche Public Key Authentisierung mit allen öffentlichen Schlüsseln im Speicher</string> - <string name="terminal_auth_pubkey_invalid">Der ausgewählte öffentliche Schlüssel ist ungültig, versuchen Sie den Schlüssel im Host-Editor neu auszuwählen</string> - <string name="terminal_auth_pubkey_specific">Versuche Public Key Authentisierung mit einem bestimmten öffentlichen Schlüssel</string> - <string name="terminal_auth_pubkey_fail">Authentifizierungs Methode \'publickey\' mit Schlüssel \'%1$s\' fehlgeschlagen</string> - <string name="terminal_auth_ki">Versuche \'keyboard-interactive\' Authentisierung.</string> - <string name="terminal_auth_ki_fail">Authentisierungsmethode \'keyboard-interactive\' fehlgeschlagen</string> - <string name="terminal_auth_fail">[Ihr Host unterstützt weder \'password\' noch \'keyboard-interactive\' Authentisierung.]</string> - <string name="terminal_no_session">Sitzung wird wegen Host Präferenz nicht gestartet</string> - <string name="terminal_enable_portfoward">Aktiviere Port Forwarding: %1$s</string> - <string name="local_shell_unavailable">Fehler! Lokale Kommandozeile ist auf diesem Telefon nicht verfügbar.</string> - <string name="notification_text">%1$s will ihre Aufmerksamkeit.</string> - <string name="no">Nein</string> - <string name="with_confirmation">Mit Bestätigung</string> - <string name="yes">Ja</string> - <string name="exceptions_submit_message">Scheinbar hatte ConnectBot Probleme bei der letzten Benutzung. Fehlermeldung an die ConnectBot übermitteln?</string> - <string name="menu_colors_reset">Zurücksetzen</string> - <string name="app_is_running">ConnectBot läuft</string> - <string name="color_red">rot</string> - <string name="color_green">grün</string> - <string name="color_blue">blau</string> - <string name="color_gray">grau</string> - <string name="colors_fg">Schriftfarbe:</string> - <string name="color_bg">Hintergrundfarbe:</string> - <string name="image_description_connected">Verbunden.</string> - <string name="image_description_key_is_locked">Schlüssel ist gesperrt.</string> - <string name="image_description_toggle_control_character">Steuerzeichen umschalten</string> - <string name="image_description_send_escape_character">Escape-Zeichen senden.</string> - <string name="image_description_show_keyboard">Tastatur anzeigen.</string> - <string name="button_close">Schließen</string> - <string name="pref_custom_keymap_title">Angepasstes Tastaturlayout</string> - <string name="pref_custom_keymap_summary">Umleitung von bestimmten Tasten auf unterstützten Geräten</string> - <string name="pref_custom_keymap_full">vollständige Tastatur</string> - <string name="pref_custom_keymap_disabled">deaktiviert</string> - <string name="resize_error_title">Fehler bei Änderung der Bildschirmgröße</string> - <string name="resize_error_width_height">Länge und Breite müssen größer als 0 sein</string> - <string name="pref_screen_capture_category">Screenshot</string> - <string name="pref_screen_capture_folder">Pfad für Screenshots</string> - <string name="pref_screen_capture_folder_summary">Ordner für das Speichern von Screenshots</string> - <string name="pref_screen_capture_popup">Benachrichtigung beim Screenshot</string> - <string name="pref_screen_capture_popup_summary">Ein Pop-Up-Fenster nach Erstellung eines Screenshots anzeigen</string> - <string name="screen_capture">Screenshot</string> - <string name="screenshot_success_title">Screenshot erfolgreich</string> - <string name="screenshot_saved_as">Screenshot wurde gespeichert als</string> - <string name="screenshot_error_title">Fehler beim Screenshot</string> - <string name="screenshot_not_saved_as">Screenshot konnte nicht gespeichert werden als</string> - <string name="pref_picker_string">Inhalt des Sym-Fensters</string> - <string name="pref_picker_string_summary">Zeichenkette für das Zeichenwahl-Dialogfenster</string> - <string name="pref_picker_keep_open">Sym-Fenster offen halten</string> - <string name="pref_picker_keep_open_summary">Nur der Abbrechen-Knopf schließt das Zeichenwahl-Dialogfenster</string> - <string name="pref_file_transfer_category">Übertragung von Dateien</string> - <string name="pref_file_dialog_title">Dateiauswahl</string> - <string name="pref_file_dialog_summary">Formular zur Auswahl von Dateien und Verzeichnissen</string> - <string name="pref_file_dialog_builtin">eingebaut</string> - <string name="error_starting_app">Fehler beim Ausführen von %1$s</string> - <string name="file_chooser_select_file">Datei %1s auswählen</string> - <string name="select_for_download">fürs Herunterladen</string> - <string name="select_for_upload">fürs Hochladen</string> - <string name="select_for_key_import">für den Schlüssel-Import</string> - <string name="location">Position</string> - <string name="cant_read_folder">Fehler beim lesen des Verzeichnisses.</string> - <string name="nnew">Neu</string> - <string name="select">Auswählen</string> - <string name="file_name">Dateiname:</string> - <string name="cancel">Abbrechen</string> - <string name="save">Speichern</string> - <string name="new_file">Neue Datei</string> - <string name="no_data">Keine Daten</string> - <string name="pref_download_folder">Download-Verzeichnis</string> - <string name="pref_download_folder_summary">Pfad zum Speichern von heruntergeladenen Dateien</string> - <string name="pref_remote_upload_folder">Upload-Verzeichnis</string> - <string name="pref_remote_upload_folder_summary">Server-Pfad für das Hochladen von Dateien</string> - <string name="pref_upload_dest_prompt">Upload-Ziel abfragen</string> - <string name="pref_upload_dest_prompt_summary">Zielpfad für Dateiuploads abfragen</string> - <string name="pref_background_file_transfer">Hintergrundübertragung von Dateien</string> - <string name="pref_background_file_transfer_summary">Das Herunterladen und Hochladen von Dateien im Hintergrund ausführen</string> - <string name="transfer_downloading">"Herunterladen von Dateien…"</string> - <string name="transfer_downloading_file">Lade herunter: %1$s</string> - <string name="transfer_download_complete">Herunterladen abgeschlossen</string> - <string name="transfer_download_failed">Fehler beim Herunterladen: %1$s</string> - <string name="transfer_select_remote_download_title">Datei(en) herunterladen</string> - <string name="transfer_select_remote_download_desc">Pfade der herunterzuladenden entfernten Dateien eintragen (zeilenweise)</string> - <string name="transfer_select_remote_upload_dest_title">Zielpfad für Upload</string> - <string name="transfer_select_remote_upload_dest_desc">Gewünschter Server-Pfad für:</string> - <string name="transfer_button_download">Herunterladen</string> - <string name="transfer_button_upload">Hochladen</string> - <string name="transfer_uploading">"Hochladen von Dateien…"</string> - <string name="transfer_uploading_file">Lade hoch: %1$s</string> - <string name="transfer_upload_complete">Hochladen abgeschlossen</string> - <string name="transfer_upload_failed">Fehler beim Hochladen:%1$s</string> - <string name="pubkey_export_private">"Privaten Schlüssel exportieren"</string> - <string name="pubkey_export_public">"Öffentlichen Schlüssel exportieren"</string> - <string name="pubkey_public_save_as">Öffentlichen Schlüssel speichern</string> - <string name="pubkey_public_save_as_desc">Dateiname (volständiger Pfad) zum Speichern des öffentlichen Schlüssels</string> - <string name="pubkey_private_save_as">Privaten Schlüssel speichern</string> - <string name="pubkey_private_save_as_desc">Dateiname (volständiger Pfad) zum Speichern des privaten Schlüssels</string> - <string name="pubkey_public_export_success">Öffentlicher Schlüssel gespeichert als %1$s</string> - <string name="pubkey_public_export_problem">Fehler beim Export des öffentlichen Schlüssels</string> - <string name="pubkey_private_export_success">Privater Schlüssel gespeichert als %1$s</string> - <string name="pubkey_private_export_problem">Fehler beim Export des privaten Schlüssels</string> - <string name="pref_debug_category">Entwickler-Einstellungen</string> - <string name="pref_debug_keycodes">Tastencodes anzeigen</string> - <string name="pref_debug_keycodes_summary">Codes der im Terminal gedrückten Tasten anzeigen</string> - <string name="keycode_pressed">Code der gedrückten Taste</string> - <string name="pref_extended_longpress">Erweitertes Longpress-Menu</string> - <string name="pref_extended_longpress_summary">Eingabeoptionen im Tap-And-Hold-Menü anzeigen</string> - <string name="longpress_select_action">Aktion auswählen</string> - <string name="longpress_enable_full_screen_mode">Vollbildmodus aktivieren</string> - <string name="longpress_disable_full_screen_mode">Vollbildmodus deaktivieren</string> - <string name="longpress_change_font_size">Fontgröße ändern</string> - <string name="longpress_arrows_dialog">Pfeiltaste</string> - <string name="longpress_fkeys_dialog">Funktionstasten</string> - <string name="longpress_ctrl_dialog">CTRL+?</string> - <string name="longpress_sym_dialog">Zeichenwahl</string> - <string name="pref_ctrl_string">Inhalt des Ctrl-Fensters</string> - <string name="pref_ctrl_string_summary">Zeichenkette für die CTRL+? kombination</string> - <string name="fullscreen">Vollbild</string> -</resources>
--- a/res/values-el/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="title_help">Βοήθεια</string> - <string name="title_colors">Χρώματα</string> - <string name="resolve_connect">Σύνδεση</string> -</resources>
--- a/res/values-en-rCA/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="title_colors">Colours</string> - <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> - <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> - <string name="hostpref_color_title">Colour category</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="list_menu_sortcolor">Sort by colour</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> -</resources>
--- a/res/values-en-rGB/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * Copyright 2011 Darren Salt - * - * This file is derived from res/values/strings.xml - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="title_colors">"Colours"</string> - <string name="hostpref_color_title">"Colour category"</string> - <string name="list_menu_sortcolor">"Sort by colour"</string> - <string name="color_gray">"grey"</string> -</resources>
--- a/res/values-es/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Cliente de SSH sencillo, potente y open-source</string> - <string name="service_desc">Mantiene conexiones SSH y las claves públicas guardadas</string> - <string name="title_hosts_list">Máquinas</string> - <string name="title_pubkey_list">Claves Publicas</string> - <string name="title_port_forwards_list">Traducciones de puerto</string> - <string name="title_host_editor">Editar equipo remoto</string> - <string name="title_help">Ayuda</string> - <string name="title_colors">Colores</string> - <string name="resolve_connect">Conectar</string> - <string name="resolve_entropy">Recolectar entropía</string> - <string name="menu_insert">Añadir equipo remoto</string> - <string name="menu_delete">Eliminar máquina</string> - <string name="menu_preferences">Configuración</string> - <string name="help_intro">Por favor seleccione un tema a continuación para más información sobre una materia en particular.</string> - <string name="help_about">Acerca de ConnectBot</string> - <string name="help_keyboard">Teclado</string> - <string name="pubkey_generate">Generar</string> - <string name="pubkey_import">Importar</string> - <string name="pubkey_delete">Eliminar clave</string> - <string name="pubkey_gather_entropy">Haciendo acopio de entropía</string> - <string name="pubkey_touch_prompt">Toque esta caja para conseguir aleatoriedad: %1$d%% hecho</string> - <string name="pubkey_touch_hint">Para poder conseguir aleatoriedad durante la generacion de la clave, mueva su dedo aleatoriamente sobre la caja a continuación.</string> - <string name="pubkey_generating">Generar llavero de claves</string> - <string name="pubkey_copy_private">Copiar clave privada</string> - <string name="pubkey_copy_public">Copiar clave pública</string> - <string name="pubkey_list_empty">Presione menu para crear\nó importar un llavero de claves</string> - <string name="pubkey_unknown_format">Formato desconocido</string> - <string name="pubkey_change_password">Cambiar contraseña</string> - <string name="pubkey_list_pick">Escoger desde la tarjeta sd</string> - <string name="pubkey_import_parse_problem">Problema analizando clave privada importada</string> - <string name="pubkey_unlock">Desbloquear clave</string> - <string name="pubkey_failed_add">Contraseña incorrecta para la clave \'%1$s\'. Autenticación fallida.</string> - <string name="pubkey_memory_load">Cargar en memoria</string> - <string name="pubkey_memory_unload">Descargar de memoria</string> - <string name="pubkey_load_on_start">Cargar clave al inicio</string> - <string name="pubkey_confirm_use">Confirme antes de usar</string> - <string name="portforward_list_empty">Presione Menu para crear\nó importar redireccionamientos.</string> - <string name="portforward_edit">Editar redireccionamiento de puerto</string> - <string name="portforward_delete">Eliminar redireccionamiento de puerto</string> - <string name="prompt_nickname">Nombre de usuario:</string> - <string name="prompt_nickname_hint_pubkey">Mi clave de trabajo</string> - <string name="prompt_source_port">Puerto fuente:</string> - <string name="prompt_destination">Destino:</string> - <string name="prompt_old_password">Contraseña antigua:</string> - <string name="prompt_password">Contraseña:</string> - <string name="prompt_again">(de nuevo)</string> - <string name="prompt_type">Tipo:</string> - <string name="prompt_password_can_be_blank">Nota: la contraseña puede ser dejada en blanco</string> - <string name="prompt_bits">Bits:</string> - <string name="prompt_pubkey_password">Contraseña para clave \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">¿Autorizar maquina remota\nde usar clave \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">ATENCIÓN: ¡LA IDENTIFICACIÓN DE LA MAQUINA REMOTA HA CAMBIADO!</string> - <string name="host_verification_failure_warning">¡ES POSIBLE QUE ALGUIEN ESTE HACIENDO ALGO INAPROPIADO!\nAlguien puede estar interviniendo en estos momentos (ataque man-in-the-middle)!\nTambién es posible que la clave haya sido cambiada.</string> - <string name="prompt_host_disconnected">La máquina ha sido desconectada.\n¿Desea cerrar sesión?</string> - <string name="prompt_continue_connecting">¿Esta seguro de que desea\nseguir conectándose?</string> - <string name="host_authenticity_warning">La autenticidad de la máquina \'%1$s\' no puede ser establecida.</string> - <string name="host_fingerprint">La clave huella de la maquina %1$s es %2$s</string> - <string name="alert_passwords_do_not_match_msg">¡Las contraseñas no coinciden!</string> - <string name="alert_wrong_password_msg">¡Contraseña errónea!</string> - <string name="alert_key_corrupted_msg">¡La clave privada parece corrupta!</string> - <string name="alert_sdcard_absent">¡Tarjeta SD no insertada!</string> - <string name="button_add">Añadir</string> - <string name="button_change">Modificar</string> - <string name="button_generate">Generar clave</string> - <string name="button_resize">Redimensionar</string> - <string name="alert_disconnect_msg">Conexión perdida</string> - <string name="pref_emulation_category">Emulación del terminal</string> - <string name="pref_emulation_title">Modo emulación</string> - <string name="pref_emulation_summary">Modo emulación para usar en conexiones PTY</string> - <string name="pref_scrollback_title">Tamaño de navegación</string> - <string name="pref_scrollback_summary">Tamaño de búfer que quedara en memoria para cada consola.</string> - <string name="pref_ui_category">Interfaz de usuario</string> - <string name="pref_rotation_title">Modo de rotación</string> - <string name="pref_rotation_summary">Como cambiar la rotación cuando se abra el teclado.</string> - <string name="pref_fullscreen_title">Pantalla completa</string> - <string name="pref_fullscreen_summary">Esconder barra de estatus cuando este en consola</string> - <string name="pref_memkeys_title">Recordar claves en memoria</string> - <string name="pref_memkeys_summary">Recordar claves en memoria hasta que el servicio en segundo plano termine</string> - <string name="pref_update_title">Revisar por actualizaciones</string> - <string name="pref_update_summary">Establecer la frequencia maxima para revisar actualizaciones de ConnectBot</string> - <string name="pref_conn_persist_title">Conexiones persistentes</string> - <string name="pref_conn_persist_summary">Mantener conexiones activas en segundo plano</string> - <string name="pref_keymode_title">Secuencia de teclas para directorios</string> - <string name="pref_keymode_summary">Especifique como usar Alt para \'/\' y Shit para Tab</string> - <string name="pref_camera_title">Boton de la Cámara</string> - <string name="pref_camera_summary">Especifique que secuencia de teclas activar cuando presione el botón de la cámara</string> - <string name="pref_keepalive_title">Mantener pantalla activa</string> - <string name="pref_keepalive_summary">Prevenir que se apague la pantalla cuando se este trabajando en consola</string> - <string name="pref_wifilock_title">Mantener la red inálambrica activa</string> - <string name="pref_wifilock_summary">Prevenir que la red inálambrica se apague mientras haya una conexión activa</string> - <string name="pref_bumpyarrows_title">Cursor con vibración</string> - <string name="pref_bumpyarrows_summary">Vibrar al recibir las teclas del cursor desde el trackball; útil para conexiones con retardos</string> - <string name="pref_bell_category">Timbre del terminal</string> - <string name="pref_bell_title">Timbre audible</string> - <string name="pref_bell_volume_title">Volúmen del timbre</string> - <string name="pref_bell_vibrate_title">Vibrar con el timbre</string> - <string name="pref_bell_notification_title">Notificaciones de fondo</string> - <string name="pref_bell_notification_summary">Activar notificacion cuando algun terminal corriendo en el fondo active un timbre</string> - <string name="list_keymode_right">Usar teclas del lado derecho</string> - <string name="list_keymode_left">Usar teclas del lado izquierdo</string> - <string name="list_keymode_none">Desactivar</string> - <string name="list_pubkeyids_none">No usar teclas</string> - <string name="list_pubkeyids_any">Utilizar cualquier clave desbloqueada</string> - <string name="hostpref_nickname_title">Apodo</string> - <string name="hostpref_color_title">Categoria de colores</string> - <string name="hostpref_fontsize_title">Tamaño de la fuente (pt)</string> - <string name="hostpref_pubkeyid_title">Usar clave de autenticación pública</string> - <string name="hostpref_authagent_title">Utilizar agente de autenticación SSH</string> - <string name="hostpref_postlogin_title">Inicio de sesión después de la automatización</string> - <string name="hostpref_postlogin_summary">Comandos para ejecutar en el servidor remoto, una vez autenticado</string> - <string name="hostpref_compression_title">Compresión</string> - <string name="hostpref_compression_summary">Esto puede ayudar con las redes más lentas</string> - <string name="hostpref_wantsession_title">Inciar sesión en shell</string> - <string name="hostpref_wantsession_summary">Desactive esta preferencia para usar sólo reenvíos por puerto</string> - <string name="hostpref_stayconnected_title">Mantenerse conectado</string> - <string name="hostpref_stayconnected_summary">Intentar reconectar al equipo si se desconecta</string> - <string name="hostpref_delkey_title">Tecla DEL</string> - <string name="hostpref_delkey_summary">El código clave que se envía cuando se pulsa tecla DEL</string> - <string name="hostpref_encoding_title">Codificando</string> - <string name="hostpref_encoding_summary">Codificación de caracteres para la maquina</string> - <string name="hostpref_connection_category">Opciones de Conexión</string> - <string name="hostpref_username_title">Nombre de usuario</string> - <string name="hostpref_hostname_title">Host (equipo anfitrión)</string> - <string name="hostpref_port_title">Puerto</string> - <string name="bind_never">Nunca fué conectado</string> - <string name="bind_minutes">Hace %1$s minutos</string> - <string name="bind_hours">Hace %1$s horas</string> - <string name="bind_days">Hace %1$s días</string> - <string name="console_copy_done">%1$d bytes copiados al portapaleles</string> - <string name="console_copy_start">Toque y arrastre\no use la almohadilla direccional\npara seleccionar la zona a copiar</string> - <string name="console_menu_close">Cerrar</string> - <string name="console_menu_copy">Copiar</string> - <string name="console_menu_paste">Pegar</string> - <string name="console_menu_portforwards">Traducciones de puerto</string> - <string name="console_menu_resize">Forzar un tamaño</string> - <string name="console_menu_urlscan">Escaneo de direcciones</string> - <string name="button_yes">Sí</string> - <string name="button_no">Denegar</string> - <string name="portforward_local">Local</string> - <string name="portforward_remote">Remoto</string> - <string name="portforward_dynamic">Dinámicos (SOCKS)</string> - <string name="portforward_pos">Crear reenvio de puerto</string> - <string name="portforward_done">Creacion satisfactoria del reenvio de puerto</string> - <string name="portforward_problem">Problema al crear el puerto de reenvio, tal vez usted está usando puertos menores de 1024 o el puerto ya está siendo utilizado?</string> - <string name="portforward_menu_add">Añadir redirección de puertos</string> - <string name="hint_userhost">usuario\@equipo</string> - <string name="list_format_error">Usar formato %1$s</string> - <string name="format_username">Usuario</string> - <string name="format_hostname">nombre del host</string> - <string name="format_port">puerto</string> - <string name="list_menu_pubkeys">Administrar clave públicas</string> - <string name="list_menu_sortcolor">Ordenar por color</string> - <string name="list_menu_sortname">Ordenar por nombre</string> - <string name="list_menu_settings">Configuración</string> - <string name="list_host_disconnect">Desconectar</string> - <string name="list_host_edit">Editar equipo</string> - <string name="list_host_portforwards">Editar redirección de puertos</string> - <string name="list_host_delete">Eliminar equipo</string> - <string name="list_host_empty">Usar la casilla de conexión rápida\na continuación para conectarse a una máquina</string> - <string name="list_rotation_default">Predeterminado</string> - <string name="list_rotation_land">Forzar paisaje</string> - <string name="list_rotation_port">Forzar retrato</string> - <string name="list_rotation_auto">Automático</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A después espacio</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Ninguno</string> - <string name="list_delkey_backspace">Borrar</string> - <string name="list_delkey_del">Eliminar</string> - <string name="delete_message">¿Está seguro de que quiere eliminar \'%1$s\'?</string> - <string name="delete_pos">Sí, eliminar</string> - <string name="delete_neg">Cancelar</string> - <string name="wizard_agree">De acuerdo</string> - <string name="wizard_next">Siguiente</string> - <string name="wizard_back">Atrás</string> - <string name="terminal_no_hosts_connected">No hay equipos conectados ahora</string> - <string name="terminal_connecting">Canectando a %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">Host (equipo anfitrion) \'%1$s\' clave: %2$s verifiado.</string> - <string name="terminal_failed">Verificación del host (equipo anfitrion) fallida</string> - <string name="terminal_using_s2c_algorithm">Algoritmo servidor-cliente: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algoritmo cliente-servidor: %1$s %2$s</string> - <string name="terminal_using_algorithm">Algoritmo que se esta usando: %1$s %2$s</string> - <string name="terminal_auth">Intentando autenticar</string> - <string name="terminal_auth_pass">Intentando autenticación de la contraseña</string> - <string name="terminal_auth_pass_fail">Método de autenticación \'password\' fallido</string> - <string name="terminal_auth_pubkey_any">Intentando autenticacion de la clave pública usando las claves públicas en memoria</string> - <string name="terminal_auth_pubkey_invalid">La clave pública selecciona es invalida, intenta reseleccional la clave en el editor de host (equipo anfitrion)</string> - <string name="terminal_auth_pubkey_specific">Intentar autenticación de la clave pública con una clave pública determinada</string> - <string name="terminal_auth_pubkey_fail">El método de autenticación \'publickey\' con clave \'%1$s\' ha fallado.</string> - <string name="terminal_auth_ki">Intentando autenticación \'interactiva por teclado\'</string> - <string name="terminal_auth_ki_fail">El método de autenticación \'interactiva por teclado\' ha fallado</string> - <string name="terminal_auth_fail">[Su equipo no soporta el método de autenticación por \'contraseña\' o por \'interacción por teclado\'.]</string> - <string name="terminal_no_session">La sesión no se iniciará debido a las preferencias del equipo.</string> - <string name="terminal_enable_portfoward">Activar redirección de puerto: %1$s</string> - <string name="local_shell_unavailable">¡Fallo! Su intérprete de órdenes local no está disponible en este teléfono.</string> - <string name="notification_text">%1$s requiere de tu atención.</string> - <string name="no">Denegar</string> - <string name="with_confirmation">Con confirmación</string> - <string name="yes">Sí</string> - <string name="exceptions_submit_message">Parece que ConnectBot tuvo un problema en su última ejecución. Enviar reporte de error a los desarrolladores de ConnectBot?</string> - <string name="menu_colors_reset">Restablecer</string> - <string name="app_is_running">ConnectBot está ejecutándose</string> - <string name="color_red">rojo</string> - <string name="color_green">verde</string> - <string name="color_blue">azul</string> - <string name="color_gray">gris</string> - <string name="image_description_connected">Conectado</string> - <string name="image_description_show_keyboard">Mostrar teclado.</string> -</resources>
--- a/res/values-eu/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,215 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">SSH bezero soil, ahaltsu eta librea</string> - <string name="service_desc">SSH konexio eta kargatutako gako publikoak mantentzen ditu</string> - <string name="title_hosts_list">Ostalariak</string> - <string name="title_pubkey_list">Gako publikoak</string> - <string name="title_port_forwards_list">Ataka birbidalketak</string> - <string name="title_host_editor">Editatu ostalaria</string> - <string name="title_help">Laguntza</string> - <string name="title_colors">Koloreak</string> - <string name="resolve_connect">Konektatu</string> - <string name="resolve_entropy">Bildu entropia</string> - <string name="menu_insert">Gehitu ostalaria</string> - <string name="menu_delete">Ezabatu ostalaria</string> - <string name="menu_preferences">Hobespenak</string> - <string name="help_intro">Mesedez, hautatu beheko gaietako bat informazio gehiago nahi izanez gero.</string> - <string name="help_about">ConnectBot-i buruz</string> - <string name="help_keyboard">Teklatua</string> - <string name="pubkey_generate">Sortu</string> - <string name="pubkey_import">Inportatu</string> - <string name="pubkey_delete">Ezabatu gakoa</string> - <string name="pubkey_gather_entropy">Entropia biltzen</string> - <string name="pubkey_touch_prompt">Ukitu kaxa hau ausazkotasuna lortzeko: %1$d%% eginda</string> - <string name="pubkey_touch_hint">Gakoa sortzeko beharrezko den ausazkotasuna lortzeko, mugitu hatza ausaz azpiko kaxaren gainean.</string> - <string name="pubkey_generating">"Gako parea sortzen…"</string> - <string name="pubkey_copy_private">Kopiatu gako pribatua</string> - <string name="pubkey_copy_public">Kopiatu gako publikoa</string> - <string name="pubkey_list_empty">Sakatu \"Menu\" gako pareak\nsortu edo inportatzeko</string> - <string name="pubkey_unknown_format">Formatu ezezaguna</string> - <string name="pubkey_change_password">Aldatu pasahitza</string> - <string name="pubkey_list_pick">Hautatu /sdcard-etik</string> - <string name="pubkey_import_parse_problem">Arazoa inportatutako gako pribatua aztertzean</string> - <string name="pubkey_unlock">Desblokeatu gakoa</string> - <string name="pubkey_failed_add">Pasahitz okerra \'%1$s\' gakoarentzat. Autentifikazioak huts egin du.</string> - <string name="pubkey_memory_load">Kargatu memoriara</string> - <string name="pubkey_memory_unload">Deskargatu memoriatik</string> - <string name="pubkey_load_on_start">Kargatu gakoa abiaraztean</string> - <string name="pubkey_confirm_use">Baieztatu erabili aurretik</string> - <string name="portforward_list_empty">Sakatu \"Menua\" ataka\nbirbidalketak sortzeko.</string> - <string name="portforward_edit">Editatu ataka birbidalketa</string> - <string name="portforward_delete">Ezabatu ataka birbidalketa</string> - <string name="prompt_nickname">Goitizena:</string> - <string name="prompt_nickname_hint_pubkey">Nire laneko gakoa</string> - <string name="prompt_source_port">Iturburuko ataka:</string> - <string name="prompt_destination">Helburua:</string> - <string name="prompt_old_password">Pasahitz zaharra:</string> - <string name="prompt_password">Pasahitza:</string> - <string name="prompt_again">(berriro)</string> - <string name="prompt_type">Mota:</string> - <string name="prompt_password_can_be_blank">Oharra: pasahitza hutsik utz daiteke</string> - <string name="prompt_bits">Bitak:</string> - <string name="prompt_pubkey_password">\'%1$s\' gakoaren pasahitza</string> - <string name="prompt_allow_agent_to_use_key">Urruneko ostalariak \'%1$s\'\ngakoa erabil dezan onartu?</string> - <string name="host_verification_failure_warning_header">KONTUZ: URRUNEKO OSTALARIAREN IDENTIFIKAZIOA ALDATU DA!</string> - <string name="host_verification_failure_warning">POSIBLE DA NORBAIT ZERBAIT MALTZURRA EGITEN ARITZEA!\nNorbait ezkutuan entzuten aritu daiteke(man-in-the-middle erasoa)!\nBeste aukera ostalariaren gakoa aldatu izana da.</string> - <string name="prompt_host_disconnected">Ostalaria deskonektatu egin da.\nSaioa itxi nahi duzu?</string> - <string name="prompt_continue_connecting">Ziur zaude konektatzen\njarraitu nahi duzula?</string> - <string name="host_authenticity_warning">\'%1$s\' ostalariaren autentifikazioa ezin da ziurtatu.</string> - <string name="host_fingerprint">%1$s ostalariaren hatz-marka %2$s da</string> - <string name="alert_passwords_do_not_match_msg">Pasahitzak ez datoz bat!</string> - <string name="alert_wrong_password_msg">Pasahitz okerra!</string> - <string name="alert_key_corrupted_msg">Gako pribatua hondatuta dagoela dirudi!</string> - <string name="alert_sdcard_absent">Ez da aurkitu SD txartelik!</string> - <string name="button_add">Gehitu</string> - <string name="button_change">Aldatu</string> - <string name="button_generate">Sortu gakoa</string> - <string name="button_resize">Aldatu tamaina</string> - <string name="alert_disconnect_msg">Konexioa galdu da</string> - <string name="pref_emulation_category">Terminal emulatzailea</string> - <string name="pref_emulation_title">Emulazio modua</string> - <string name="pref_emulation_summary">PTY konexioetarako terminal emulazio modua</string> - <string name="pref_scrollback_title">Korritze-barraren tamaina</string> - <string name="pref_scrollback_summary">Kontsola bakoitzarentzat memorian gordeko den korritze-barraren buffer tamaina.</string> - <string name="pref_ui_category">Erabiltzaile-interfazea</string> - <string name="pref_rotation_title">Biratze modua</string> - <string name="pref_rotation_summary">Nola aldatu biratzea teklatua bistaratzean/izkutatzean.</string> - <string name="pref_fullscreen_title">Pantaila osoa</string> - <string name="pref_fullscreen_summary">Ezkutatu egoera-barra kontsola erabiltzean</string> - <string name="pref_memkeys_title">Gorde gakoak memorian</string> - <string name="pref_memkeys_summary">Gogoratu desblokeatutako gakoak memorian zerbitzua amaitu arte</string> - <string name="pref_update_title">Eguneraketak begiratu</string> - <string name="pref_update_summary">ConnectBot-en eguneraketarik dagoen begiratzeko maiztasun maximoa finkatu</string> - <string name="pref_conn_persist_title">Konexio iraunkorrak</string> - <string name="pref_conn_persist_summary">Behartu konexioak aktibo mantentzera atzeko planoko daudenean</string> - <string name="pref_keymode_title">Direktorien laster-teklak</string> - <string name="pref_keymode_summary">Zehaztu nola erabili Alt \'/\'-entzat eta Shift Tab-entzat</string> - <string name="pref_camera_title">Kameraren laster-tekla</string> - <string name="pref_camera_summary">Zehaztu kameraren botoia sakatzean aktibatu nahi duzun laster-tekla</string> - <string name="pref_keepalive_title">Mantendu pantaila aktibo</string> - <string name="pref_keepalive_summary">Galarazi pantaila itzaltzea kontsola moduan lanean aritzean</string> - <string name="pref_wifilock_title">Mantendu WiFi-a aktibo</string> - <string name="pref_wifilock_summary">Galarazi WiFi-a itzaltzea saio aktibo bat dagoen bitartean</string> - <string name="pref_bumpyarrows_title">Bibraziodun geziak</string> - <string name="pref_bumpyarrows_summary">Bibratu trackball bidez erakusle-geziak bidaltzean; atzerapendun konexioentzat egokia</string> - <string name="pref_bell_category">Terminalaren txirrina</string> - <string name="pref_bell_title">Txirrin entzungarria</string> - <string name="pref_bell_volume_title">Txirrinaren bolumena</string> - <string name="pref_bell_vibrate_title">Bibratu txirrinarekin</string> - <string name="pref_bell_notification_title">Atzeko planoko jakinerazpenak</string> - <string name="pref_bell_notification_summary">Bidali jakinerazpena atzeko planoan dagoen terminal batek txirrina jotzean.</string> - <string name="list_keymode_right">Erabili eskuinaldeko teklak</string> - <string name="list_keymode_left">Erabili ezkerraldeko teklak</string> - <string name="list_keymode_none">Desgaitu</string> - <string name="list_pubkeyids_none">Ez erabili gakorik</string> - <string name="list_pubkeyids_any">Erabili desblokeatutako edozein gako</string> - <string name="hostpref_nickname_title">Goitizena</string> - <string name="hostpref_color_title">Kolore kategoria</string> - <string name="hostpref_fontsize_title">Letra-tamaina (pt)</string> - <string name="hostpref_pubkeyid_title">Erabili gako publiko bidezko autentifikazioa</string> - <string name="hostpref_authagent_title">Erabili SSH autentifikazio-eragilea</string> - <string name="hostpref_postlogin_title">Saio hasiera ondoko automatizazioa</string> - <string name="hostpref_postlogin_summary">Autentifikatu ondoren urruneko zerbitzarian exekutatu beharreko komandoak</string> - <string name="hostpref_compression_title">Konpresioa</string> - <string name="hostpref_compression_summary">Hau lagungarri izan daiteke konexio mantsoekin</string> - <string name="hostpref_wantsession_title">Hasi shell saioa</string> - <string name="hostpref_wantsession_summary">Desgaitu aukera hau ataka birbidalketak bakarrik erabiltzeko</string> - <string name="hostpref_stayconnected_title">Konektatuta mantendu</string> - <string name="hostpref_stayconnected_summary">Saiatu ostalarira birkonektatzen deskonektatzean</string> - <string name="hostpref_delkey_title">DEL tekla</string> - <string name="hostpref_delkey_summary">DEL tekla sakatzean bidaltzen den tekla-kodea</string> - <string name="hostpref_encoding_title">Kodeketa</string> - <string name="hostpref_encoding_summary">Ostalariarentzako karaktere kodeketa</string> - <string name="hostpref_connection_category">Konexio hobespenak</string> - <string name="hostpref_username_title">Erabiltzaile-izena</string> - <string name="hostpref_hostname_title">Ostalaria</string> - <string name="hostpref_port_title">Ataka</string> - <string name="bind_never">Inoiz ez da konexiorik ezarri</string> - <string name="bind_minutes">Duela %1$s minutu</string> - <string name="bind_hours">Duela %1$s ordu</string> - <string name="bind_days">Duela %1$s egun</string> - <string name="console_copy_done">%1$d byte kopiatuta arbelera</string> - <string name="console_copy_start">Ukitu eta arrastatu\nedo erabili norabide kuxina\nkopiatu beharreko eremua hautatzeko</string> - <string name="console_menu_close">Itxi</string> - <string name="console_menu_copy">Kopiatu</string> - <string name="console_menu_paste">Itsatsi</string> - <string name="console_menu_portforwards">Ataka birbidalketak</string> - <string name="console_menu_resize">Behartu tamaina</string> - <string name="console_menu_urlscan">URL eskaneatzea</string> - <string name="button_yes">Bai</string> - <string name="button_no">Ez</string> - <string name="portforward_local">Lokala</string> - <string name="portforward_remote">Urrunekoa</string> - <string name="portforward_dynamic">Dinamikoa (SOCKS)</string> - <string name="portforward_pos">Sortu ataka birbidalketa</string> - <string name="portforward_done">Ataka birbidalketa ongi sortu da</string> - <string name="portforward_problem">Arazoa ataka birbidalketa sortzean, behar bada erabilitako ataka 1024 baino txikiagoa da edo dagoeneko erabiltzen den ataka bat da?</string> - <string name="portforward_menu_add">Gehitu ataka birbidalketa</string> - <string name="hint_userhost">erabiltzailea\@ostalaria</string> - <string name="list_format_error">Erabili %1$s formatua</string> - <string name="format_username">erabiltzaile-izena</string> - <string name="format_hostname">ostalaria</string> - <string name="format_port">ataka</string> - <string name="list_menu_pubkeys">Kudeatu gako publikoak</string> - <string name="list_menu_sortcolor">Antolatu kolorearen arabera</string> - <string name="list_menu_sortname">Antolatu izenaren arabera</string> - <string name="list_menu_settings">Ezarpenak</string> - <string name="list_host_disconnect">Deskonektatu</string> - <string name="list_host_edit">Editatu ostalaria</string> - <string name="list_host_portforwards">Editatu ataka birbidalketak</string> - <string name="list_host_delete">Ezabatu ostalaria</string> - <string name="list_host_empty">Erabili azpiko konexio-azkarreko kaxa\nostalari batetara konektatzeko</string> - <string name="list_rotation_default">Lehenetsia</string> - <string name="list_rotation_land">Behartu horizontala</string> - <string name="list_rotation_port">Behartu bertikala</string> - <string name="list_rotation_auto">Automatikoa</string> - <string name="list_hwbutton_ctrlaspace">Ktrl+A ondoren zuriunea</string> - <string name="list_hwbutton_ctrla">Ktrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Ezer ez</string> - <string name="list_delkey_backspace">Atzera tekla</string> - <string name="list_delkey_del">Ezabatu</string> - <string name="delete_message">Ziur zaude \'%1$s\' ezabatu nahi duzula?</string> - <string name="delete_pos">Bai, ezabatu</string> - <string name="delete_neg">Utzi</string> - <string name="wizard_agree">Ados</string> - <string name="wizard_next">Hurrengoa</string> - <string name="wizard_back">Atzera</string> - <string name="terminal_no_hosts_connected">Ez dago ostalaririk konektatuta une honetan</string> - <string name="terminal_connecting">%1$s:%2$d-ra konektatzen %3$s bidez</string> - <string name="terminal_sucess">Egiaztatutako ostalaria \'%1$s\' gakoa: %2$s</string> - <string name="terminal_failed">Ostalariaren gakoaren egiaztapenak huts egin du</string> - <string name="terminal_using_s2c_algorithm">Zerbitzari-bezero algoritmoa: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Bezero-zerbitzari algoritmoa: %1$s %2$s</string> - <string name="terminal_using_algorithm">Uneko algoritmoa: %1$s %2$s</string> - <string name="terminal_auth">Autentifikatzen saiatzen</string> - <string name="terminal_auth_pass">\'Pasahitz bidez\' autentifikatzen saiatzen</string> - <string name="terminal_auth_pass_fail">\'Pasahitz bidezko\' autentifikatzeak huts egin du</string> - <string name="terminal_auth_pubkey_any">\'Gako publiko bidezko\' autentifikatze saiakera memoriako gako publikoak erabiliz</string> - <string name="terminal_auth_pubkey_invalid">Hautatutako gako publikoa baliogabea da, saiatu berriz hautatzen ostalari editorean</string> - <string name="terminal_auth_pubkey_specific">Saiatu \'gako publiko bidez\' autentifikatzen gako publiko zehatz batekin</string> - <string name="terminal_auth_pubkey_fail">\'%1$s\' gakoa erabiliz egindako \'gako publiko bidezko\' autenfikazioak huts egin du</string> - <string name="terminal_auth_ki">\'Teklatu bidezko autentifikazio elkarreragilea\' saiatzen</string> - <string name="terminal_auth_ki_fail">\'Teklatu bidezko autentifikazio elkarreragileak\' huts egin du</string> - <string name="terminal_auth_fail">[Zure ostalariak ez du onartzen \'pasahitz bidezko\' edo \'teklatu bidezko autentifikazio elkarreragilerik\'.]</string> - <string name="terminal_no_session">Saiorik ez da hasiko ostalariaren hobespenak direla eta.</string> - <string name="terminal_enable_portfoward">Gaitu ataka birbidalketa: %1$s</string> - <string name="local_shell_unavailable">Errorea! Shell lokala ez dago eskuragarri telefono honetan.</string> - <string name="notification_text">%1$s-k zure arreta behar du.</string> - <string name="no">Ez</string> - <string name="with_confirmation">Berrespenarekin</string> - <string name="yes">Bai</string> - <string name="exceptions_submit_message">Dirudienez ConnectBot-ek arazo bat izan zuen azken exekuzioan. ConnectBot-en garatzaileei errore-txostena bidali?</string> - <string name="menu_colors_reset">Berrezarri</string> - <string name="app_is_running">ConnectBot martxan dago</string> - <string name="color_red">gorria</string> - <string name="color_green">berdea</string> - <string name="color_blue">urdina</string> - <string name="color_gray">grisa</string> - <string name="image_description_connected">Konektatuta.</string> - <string name="image_description_key_is_locked">Gakoa blokeatuta dago.</string> - <string name="image_description_toggle_control_character">Txandakatu kontrol karakterea.</string> - <string name="image_description_send_escape_character">Bidali ihes karakterea.</string> - <string name="image_description_show_keyboard">Erakutsi teklatua.</string> -</resources>
--- a/res/values-fa/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources/>
--- a/res/values-fi/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Yksinkertainen ja tehokas avoimen lähdekoodin SSH-asiakasohjelma.</string> - <string name="service_desc">Ylläpitää SSH-yhteydet ja ladatut julkiset avaimet</string> - <string name="title_hosts_list">Palvelimet</string> - <string name="title_pubkey_list">Julkiset avaimet</string> - <string name="title_port_forwards_list">Porttiohjaukset</string> - <string name="title_host_editor">Muokaa palvelinta</string> - <string name="title_help">Ohje</string> - <string name="title_colors">Värit</string> - <string name="resolve_connect">Yhdistä</string> - <string name="resolve_entropy">Satunnaisdatan keräys</string> - <string name="menu_insert">Lisää palvelin</string> - <string name="menu_delete">Poista palvelin</string> - <string name="menu_preferences">Asetukset</string> - <string name="help_intro">Valitse alta aihe, josta haluat lisätietoja.</string> - <string name="help_about">Tietoja ConnectBotista</string> - <string name="help_keyboard">Näppäimistö</string> - <string name="pubkey_generate">Luo</string> - <string name="pubkey_import">Tuo</string> - <string name="pubkey_delete">Poista avain</string> - <string name="pubkey_gather_entropy">Kerätään satunnaisdataa</string> - <string name="pubkey_touch_prompt">Kosketa tätä laatikkoa kerätäksesi satunnaisdataa: %1$d%% valmiina</string> - <string name="pubkey_touch_hint">Liikuta sormeasi alla olevan laatikon kohdalla sattumanvaraisesti varmistaaksesi avaimen luonnin satunnaisuuden.</string> - <string name="pubkey_generating">"Luodaan avainparia…"</string> - <string name="pubkey_copy_private">Kopio yksityinen avain</string> - <string name="pubkey_copy_public">Kopioi julkinen avain</string> - <string name="pubkey_list_empty">Paina valikkopainiketta\nluodaksesi tai tuodaksesi\navainpareja.</string> - <string name="pubkey_unknown_format">Tuntematon tyyppi</string> - <string name="pubkey_change_password">Vaihda salasana</string> - <string name="pubkey_list_pick">Hae sijainnista /sdcard</string> - <string name="pubkey_import_parse_problem">Ongelma käsiteltäessä tuotua avainparia</string> - <string name="pubkey_unlock">Poista avaimen lukitus</string> - <string name="pubkey_failed_add">Väärä salasana avaimelle \'%1$s\'. Tunnistus epäonnistui.</string> - <string name="pubkey_memory_load">Lataa muistiin</string> - <string name="pubkey_memory_unload">Poista muistista</string> - <string name="pubkey_load_on_start">Lataa avain käynnistyksen yhteydessä</string> - <string name="pubkey_confirm_use">Vahvista ennen käyttöä</string> - <string name="portforward_list_empty">Paina valikkopainiketta\nluodaksesi porttiohjauksia.</string> - <string name="portforward_edit">Muokkaa porttiohjausta</string> - <string name="portforward_delete">Poista porttiohjaus</string> - <string name="prompt_nickname">Lempinimi:</string> - <string name="prompt_nickname_hint_pubkey">Työavain</string> - <string name="prompt_source_port">Lähdeportti:</string> - <string name="prompt_destination">Kohde:</string> - <string name="prompt_old_password">Vanha salasana:</string> - <string name="prompt_password">Salasana:</string> - <string name="prompt_again">(uudelleen)</string> - <string name="prompt_type">Tyyppi:</string> - <string name="prompt_password_can_be_blank">Huomio: salasana voi olla sisältämättä merkkejä</string> - <string name="prompt_bits">Bittejä:</string> - <string name="prompt_pubkey_password">Salasana avaimelle \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Hyväksy etäyhteys:\nkäytä avainta \'%1$s\'</string> - <string name="host_verification_failure_warning_header">VAROITUS: ETÄPÄÄN KONEEN TUNNISTE ON MUUTTUNUT!</string> - <string name="host_verification_failure_warning">JOKU SAATTAA OLLA TEKEMÄSSÄ PAHOJAAN!\nOn mahdollista, että yhteyttäsi salakuunnellaan (niin kutsuttu man-in-the-middle -hyökkäys)!\nOn toki myös mahdollista, että palvelimen avainta vain on muutettu.</string> - <string name="prompt_host_disconnected">Palvelin katkaisi yhteyden.\nSuljetaanko istunto?</string> - <string name="prompt_continue_connecting">Haluatko varmasti\njatkaa yhdistämistä?</string> - <string name="host_authenticity_warning">Palvelimen \'%1$s\' aitoutta ei voida varmentaa</string> - <string name="host_fingerprint">Palvelimen %1$s avaimen sormenjälki: %2$s</string> - <string name="alert_passwords_do_not_match_msg">Salasanat eivät täsmää!</string> - <string name="alert_wrong_password_msg">Väärä salasana!</string> - <string name="alert_key_corrupted_msg">Yksityinen avain vaikuttaa korruptoituneelta.</string> - <string name="alert_sdcard_absent">Laitteessa ei ole muistikorttia!</string> - <string name="button_add">Lisää</string> - <string name="button_change">Muokkaa</string> - <string name="button_generate">Luo avain</string> - <string name="button_resize">Muuta kokoa</string> - <string name="alert_disconnect_msg">Yhteys katkesi</string> - <string name="pref_emulation_category">Pääte-emulaattori</string> - <string name="pref_emulation_title">Emulointitila</string> - <string name="pref_emulation_summary">PTY-yhteyksissä käytettävä emulointitila</string> - <string name="pref_scrollback_title">Vierityspuskurin koko</string> - <string name="pref_scrollback_summary">Konsolikohtainen koko vierityspuskurille, jossa pidetään konsolin historiaa</string> - <string name="pref_ui_category">Käyttöliittymä</string> - <string name="pref_rotation_title">Näytön pyöritys</string> - <string name="pref_rotation_summary">Miten näyttöä pyöritetään kun näppäimistö tulee näkyviin/poistuu näkyvistä</string> - <string name="pref_fullscreen_title">Kokoruutu</string> - <string name="pref_fullscreen_summary">Piilota ilmoitusalue konsolikäytössä</string> - <string name="pref_memkeys_title">Pidä avaimet muistissa</string> - <string name="pref_memkeys_summary">Pitää avatut avaimet muistissa kunnes taustapalvelu suljetaan</string> - <string name="pref_update_title">Päivitysten tarkistus</string> - <string name="pref_update_summary">Kuinka usein ConnectBot enintään tarkistaa päivitykset</string> - <string name="pref_conn_persist_title">Ylläpidä yhteys</string> - <string name="pref_conn_persist_summary">Pakottaa yhteyden pysymään aktiivisena ohjelman ollessa taustalla</string> - <string name="pref_keymode_title">Pikanäppäimet</string> - <string name="pref_camera_title">Kamera-pikanäppäin</string> - <string name="pref_camera_summary">Valitse kamerapainikkeesta suoritettava toiminto</string> - <string name="pref_keepalive_title">Pidä näyttö päällä</string> - <string name="pref_keepalive_summary">Estää näytön sammumisen työskenneltäessä konsolissa</string> - <string name="pref_wifilock_title">Pidä Wi-Fi-yhteys päällä</string> - <string name="pref_wifilock_summary">Estää Wi-Fi-yhteyden katkaisemisen kun istunto on aktiivinen</string> - <string name="pref_bumpyarrows_title">Värinä nuolista</string> - <string name="pref_bumpyarrows_summary">Värinäefekti aina kun nuolinäppäinten painalluksia lähetetään palvelimelle. Kätevä hitaille yhteyksille.</string> - <string name="pref_bell_category">Päätteen kello</string> - <string name="pref_bell_title">Kellon äänet käytössä</string> - <string name="pref_bell_volume_title">Kellon äänenvoimakkuus</string> - <string name="pref_bell_vibrate_title">Värinäefekti kellosta</string> - <string name="pref_bell_notification_title">Taustailmoitukset</string> - <string name="pref_bell_notification_summary">Näyttää ilmoituksen kun taustalla olevassa päätteessä soitetaan kelloa.</string> - <string name="list_keymode_right">Käytä oikean reunan erikoispainikkeita</string> - <string name="list_keymode_left">Käytä vasemman reunan erikoispainikkeita</string> - <string name="list_keymode_none">Pois käytöstä</string> - <string name="list_pubkeyids_none">Älä käytä avaimia</string> - <string name="list_pubkeyids_any">Käytä mitä tahansa avattua avainta</string> - <string name="hostpref_nickname_title">Lempinimi</string> - <string name="hostpref_color_title">Väri</string> - <string name="hostpref_fontsize_title">Kirjasimen koko (pistettä)</string> - <string name="hostpref_pubkeyid_title">Kirjaudu avainparilla</string> - <string name="hostpref_authagent_title">Käytä SSH-kirjautumisagenttia</string> - <string name="hostpref_postlogin_title">Kirjautumisen jälkeiset automaattiset toimenpiteet</string> - <string name="hostpref_postlogin_summary">Palvelimella kirjautumisen jälkeen ajettavat komennot</string> - <string name="hostpref_compression_title">Pakkaus</string> - <string name="hostpref_compression_summary">Tämä voi helpottaa hitaiden yhteyksien käyttämistä</string> - <string name="hostpref_wantsession_title">Käynnistä komentorivi-istunto</string> - <string name="hostpref_wantsession_summary">Ota tämä pois käytöstä jos käytät vain porttiohjausta</string> - <string name="hostpref_stayconnected_title">Pysy yhteydessä</string> - <string name="hostpref_stayconnected_summary">Yritä yhdistää palvelimeen uudelleen yhteyden katkeamisen jälkeen</string> - <string name="hostpref_delkey_title">Del-näppäin</string> - <string name="hostpref_delkey_summary">Del-näppäintä painettaessa lähetettävä näppäinkoodi</string> - <string name="hostpref_encoding_title">Merkistökoodaus</string> - <string name="hostpref_encoding_summary">Palvelimella käytettävä merkistökoodaus</string> - <string name="hostpref_connection_category">Yhteysasetukset</string> - <string name="hostpref_username_title">Käyttäjätunnus</string> - <string name="hostpref_hostname_title">Palvelin</string> - <string name="hostpref_port_title">Portti</string> - <string name="bind_never">Ei koskaan yhdistetty</string> - <string name="bind_minutes">%1$s minuuttia sitten</string> - <string name="bind_hours">%1$s tuntia sitten</string> - <string name="bind_days">%1$s päivää sitten</string> - <string name="console_copy_done">%1$d tavua kopioitu leikepöydälle</string> - <string name="console_copy_start">Maalaa koskettamalla\ntai käytä nuolinäppäimiä\nvalitaksesi kopioitavan alueen</string> - <string name="console_menu_close">Sulje</string> - <string name="console_menu_copy">Kopioi</string> - <string name="console_menu_paste">Liitä</string> - <string name="console_menu_portforwards">Porttiohjaukset</string> - <string name="console_menu_resize">Pakota koko</string> - <string name="console_menu_urlscan">URL-haku</string> - <string name="button_yes">Kyllä</string> - <string name="button_no">Ei</string> - <string name="portforward_local">Paikallinen</string> - <string name="portforward_remote">Etä</string> - <string name="portforward_dynamic">Dynaaminen (SOCKS)</string> - <string name="portforward_pos">Luo porttiohjaus</string> - <string name="portforward_done">Porttiohjaus luotu onnistuneesti</string> - <string name="portforward_problem">Ongelma luotaessa porttiohjausta. Ehkä käytät porttia joka on alle 1024 tai portti on jo käytössä?</string> - <string name="portforward_menu_add">Lisää porttiohjaus</string> - <string name="hint_userhost">tunnus\@palvelin</string> - <string name="list_format_error">Käytä muotoa %1$s</string> - <string name="format_username">käyttäjätunnus</string> - <string name="format_hostname">palvelin</string> - <string name="format_port">portti</string> - <string name="list_menu_pubkeys">Hallitse avaimia</string> - <string name="list_menu_sortcolor">Lajittele värin mukaan</string> - <string name="list_menu_sortname">Lajittele nimen mukaan</string> - <string name="list_menu_settings">Asetukset</string> - <string name="list_host_disconnect">Katkaise</string> - <string name="list_host_edit">Muokkaa palvelinta</string> - <string name="list_host_portforwards">Muokkaa porttiohjauksia</string> - <string name="list_host_delete">Poista palvelin</string> - <string name="list_host_empty">Käytä alla olevaa tekstikenttää\nyhdistääksesei palvelimeen.</string> - <string name="list_rotation_default">Oletus</string> - <string name="list_rotation_land">Pakota vaakatasoon</string> - <string name="list_rotation_port">Pakota pystysuuntaan</string> - <string name="list_rotation_auto">Automaattinen</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A ja välilyönti</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Ei mitään</string> - <string name="list_delkey_backspace">Askelpalautin</string> - <string name="list_delkey_del">Delete</string> - <string name="delete_message">Oletko varma että haluat poistaa: \'%1$s\'?</string> - <string name="delete_pos">Kyllä, poista</string> - <string name="delete_neg">Peru</string> - <string name="wizard_agree">Hyväksy</string> - <string name="wizard_next">Seuraava</string> - <string name="wizard_back">Edellinen</string> - <string name="terminal_no_hosts_connected">Yhteenkään palvelimeen ei ole yhdistetty</string> - <string name="terminal_connecting">Muodostetaan %3$s-yhteys palvelimeen %1$s:%2$d</string> - <string name="terminal_sucess">Varmennettiin palvelin \'%1$s\' avain: %2$s</string> - <string name="terminal_failed">Palvelimen avaimen varmistaminen epäonnistui</string> - <string name="terminal_using_s2c_algorithm">Salausalgoritmi palvelimelta asiakkaalle: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Salausalgoritmi asiakkaalta palvelimelle: %1$s %2$s</string> - <string name="terminal_using_algorithm">Käytetään salausalgoritmia %1$s %2$s</string> - <string name="terminal_auth">Kirjaudutaan</string> - <string name="terminal_auth_pass">Yritetään \'salasana\' tunnistusta</string> - <string name="terminal_auth_pass_fail">Varmennusmenetelmä \'password\' epäonnistui</string> - <string name="terminal_auth_pubkey_any">Yritetään \'publickey\' varmennusta millä tahansa muistissa olevalla julkisella avaimella</string> - <string name="terminal_auth_pubkey_invalid">Valittu julkinen avain ei kelpaa, kokeile valita toinen avain palvelimen asetuksista</string> - <string name="terminal_auth_pubkey_specific">Yritetään \'publickey\' varmennusta tietyllä julkisella avaimella</string> - <string name="terminal_auth_pubkey_fail">Varmennusmenetelmä \'publickey\' avaimella \'%1$s\' epäonnistui</string> - <string name="terminal_auth_ki">Yritetään \'keyboard-interactive\' varmennusta</string> - <string name="terminal_auth_ki_fail">Varmennusmenetelmä \'keyboard-interactive\' epäonnistui</string> - <string name="terminal_auth_fail">[Palvelin ei tue \'password\' tai \'keyboard-interactive\' varmennusmenetelmiä.]</string> - <string name="terminal_no_session">Istuntoa ei aloiteta palvelimen asetuksista johtuen</string> - <string name="terminal_enable_portfoward">Ota käyttöön porttiohjaus %1$s</string> - <string name="local_shell_unavailable">Virhe! Paikallista komentoriviä ei ole käytettävissä</string> - <string name="notification_text">%1$s kaipaa huomiotasi.</string> - <string name="no">Ei</string> - <string name="with_confirmation">Kysy varmistus</string> - <string name="yes">Kyllä</string> - <string name="exceptions_submit_message">ConnectBotilla vaikutti olevan ongelmia kun sitä käytettiin edellisen kerran. Lähetetäänkö virheraportti ohjelman kehittäjille?</string> - <string name="menu_colors_reset">Palauta</string> - <string name="app_is_running">ConnectBot on käynnissä</string> - <string name="color_red">punainen</string> - <string name="color_green">vihreä</string> - <string name="color_blue">sininen</string> - <string name="color_gray">harmaa</string> - <string name="image_description_connected">Yhdistetty.</string> - <string name="image_description_send_escape_character">Lähetä escape.</string> - <string name="image_description_show_keyboard">Näytä näppäimistö</string> -</resources>
--- a/res/values-fr/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Un client SSH simple, open-source et puissant.</string> - <string name="service_desc">Maintient les connexions SSH et les clefs publiques chargées</string> - <string name="title_hosts_list">Serveurs</string> - <string name="title_pubkey_list">Clés publiques</string> - <string name="title_port_forwards_list">Redirections de ports</string> - <string name="title_host_editor">Modifier le serveur</string> - <string name="title_help">Aide</string> - <string name="title_colors">Couleurs</string> - <string name="resolve_connect">Connexion</string> - <string name="resolve_entropy">Générer de l\'entropie</string> - <string name="menu_insert">Ajouter un serveur</string> - <string name="menu_delete">Supprimer le serveur</string> - <string name="menu_preferences">Préférences</string> - <string name="help_intro">Sélectionnez un sujet ci-dessous pour plus d\'informations.</string> - <string name="help_about">À propos de ConnectBot</string> - <string name="help_keyboard">Clavier</string> - <string name="pubkey_generate">Générer</string> - <string name="pubkey_import">Importer</string> - <string name="pubkey_delete">Supprimer la clé</string> - <string name="pubkey_gather_entropy">Génération d\'entropie</string> - <string name="pubkey_touch_prompt">Touchez cette boîte pour générer de l\'entropie : %1$d%% effectué</string> - <string name="pubkey_touch_hint">Afin d\'assurer la qualité des nombres aléatoires utilisés pendant la génération de la clé, merci de bouger votre doigt de façon aléatoire sur la boîte ci-dessous.</string> - <string name="pubkey_generating">"Génération de la paire de clés en cours…"</string> - <string name="pubkey_copy_private">Copier la clé privée</string> - <string name="pubkey_copy_public">Copier la clé publique</string> - <string name="pubkey_list_empty">Cliquer sur le Menu pour créer\nou importer des paires de clés.</string> - <string name="pubkey_unknown_format">Format inconnu</string> - <string name="pubkey_change_password">Changer le mot de passe</string> - <string name="pubkey_list_pick">Récupérer depuis /sdcard</string> - <string name="pubkey_import_parse_problem">Problème lors du parsage de la clé privée importée</string> - <string name="pubkey_unlock">Déverrouiller la clé</string> - <string name="pubkey_failed_add">Mot de passe incorrect pour la clé \'%1$s\'. L\'authentification a échoué.</string> - <string name="pubkey_memory_load">Charger en mémoire</string> - <string name="pubkey_memory_unload">Décharger de la mémoire</string> - <string name="pubkey_load_on_start">Charger la clé au démarrage</string> - <string name="pubkey_confirm_use">Confirmer avant utilisation</string> - <string name="portforward_list_empty">Appuyez sur Menu pour créer\ndes redirections de port.</string> - <string name="portforward_edit">Éditer la redirection de port</string> - <string name="portforward_delete">Effacer la redirection de port</string> - <string name="prompt_nickname">Pseudonyme :</string> - <string name="prompt_nickname_hint_pubkey">Ma clé de travail</string> - <string name="prompt_source_port">Port source :</string> - <string name="prompt_destination">Destination :</string> - <string name="prompt_old_password">Ancien mot de passe :</string> - <string name="prompt_password">Mot de passe :</string> - <string name="prompt_again">(encore)</string> - <string name="prompt_type">Type :</string> - <string name="prompt_password_can_be_blank">Note : le mot de passe peut être vide</string> - <string name="prompt_bits">Bits :</string> - <string name="prompt_pubkey_password">Mot de passe pour la clé \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Autoriser l\'hôte distant à\nutiliser la clé \'%1$s\' ?</string> - <string name="host_verification_failure_warning_header">ATTENTION : L\'IDENTIFICATION DE L\'HÔTE DISTANT A CHANGÉ !</string> - <string name="host_verification_failure_warning">IL EST POSSIBLE QUE QUELQU\'UN FASSE QUELQUE CHOSE DE NUISIBLE !\nQuelqu\'un pourrait vous écouter en ce moment (attaque de l\'homme du milieu) !\nIl est aussi possible que la clé du serveur ait juste changée.</string> - <string name="prompt_host_disconnected">L\'hôte s\'est déconnecté.\nFermer la session ?</string> - <string name="prompt_continue_connecting">Êtes-vous sûr de vouloir\ncontinuer à vous connecter ?</string> - <string name="host_authenticity_warning">L\'authenticité du serveur \'%1$s\' ne peut être établie</string> - <string name="host_fingerprint">L\'empreinte de la clé du serveur %1$s est %2$s</string> - <string name="alert_passwords_do_not_match_msg">Les mots de passe sont différents !</string> - <string name="alert_wrong_password_msg">Mauvais mot de passe !</string> - <string name="alert_key_corrupted_msg">La clé privé semble corrompue !</string> - <string name="alert_sdcard_absent">Pas de carte SD dans le lecteur !</string> - <string name="button_add">Ajouter</string> - <string name="button_change">Changer</string> - <string name="button_generate">Générer une clé</string> - <string name="button_resize">Retailler</string> - <string name="alert_disconnect_msg">Connexion perdue</string> - <string name="pref_emulation_category">Émulation du mode terminal</string> - <string name="pref_emulation_title">Mode d\'émulation</string> - <string name="pref_emulation_summary">Mode d\'émulation de terminal à utiliser pour les connexions PTY</string> - <string name="pref_scrollback_title">Taille de l\'historique</string> - <string name="pref_scrollback_summary">Taille de l\'historique à garder en mémoire pour chaque console</string> - <string name="pref_ui_category">Interface utilisateur</string> - <string name="pref_rotation_title">Mode de rotation</string> - <string name="pref_rotation_summary">Comment changer l\'orientation de l\'écran suivant si le clavier est déplié</string> - <string name="pref_fullscreen_title">Plein écran</string> - <string name="pref_fullscreen_summary">Cacher la barre de notifications lorsque la console est active</string> - <string name="pref_memkeys_title">Garder les clés en mémoire</string> - <string name="pref_memkeys_summary">Garder les clés débloquées en mémoire tant que le service tourne en arrière-plan</string> - <string name="pref_update_title">Vérifier les mises à jour</string> - <string name="pref_update_summary">Régler la fréquence de vérification pour les mises à jour de ConnectBot</string> - <string name="pref_conn_persist_title">Connexions persistantes</string> - <string name="pref_conn_persist_summary">Forcer les connexions à rester connectées en arrière-plan</string> - <string name="pref_keymode_title">Raccourcis de navigation</string> - <string name="pref_keymode_summary">Définir quel couple de touches Alt et Shift utiliser pour \'/\' et Tab</string> - <string name="pref_camera_title">Raccourci du bouton Appareil photo</string> - <string name="pref_camera_summary">Sélectionnez le raccourci à exécuter quand le bouton caméra est pressé</string> - <string name="pref_keepalive_title">Garder l\'écran allumé</string> - <string name="pref_keepalive_summary">Empêcher la mise en veille de l\'écran pendant une session console</string> - <string name="pref_wifilock_title">Garder le Wi-Fi actif</string> - <string name="pref_wifilock_summary">Empêcher la désactivation du Wi-Fi quand une session est active</string> - <string name="pref_bumpyarrows_title">Flêches vibrantes</string> - <string name="pref_bumpyarrows_summary">Vibrer lors de l\'envoi d\'une touche directionnelle à partir du trackball ; intéressant pour les connexions lentes</string> - <string name="pref_bell_category">Cloche du terminal</string> - <string name="pref_bell_title">Alerte sonore</string> - <string name="pref_bell_volume_title">Volume de l\'alerte</string> - <string name="pref_bell_vibrate_title">Vibrer en cas d\'alerte</string> - <string name="pref_bell_notification_title">Notifications en arrière-plan</string> - <string name="pref_bell_notification_summary">Envoyer une notification lorsqu\'un terminal en arrière-plan génère une alerte</string> - <string name="list_keymode_right">Utiliser les touches du côté droit du clavier</string> - <string name="list_keymode_left">Utiliser les touches du côté gauche du clavier</string> - <string name="list_keymode_none">Désactivé</string> - <string name="list_pubkeyids_none">Ne pas utiliser les clés publiques</string> - <string name="list_pubkeyids_any">Utiliser une clé pour l\'authentification</string> - <string name="hostpref_nickname_title">Surnom</string> - <string name="hostpref_color_title">Catégorie de couleur</string> - <string name="hostpref_fontsize_title">Taille de police (pt)</string> - <string name="hostpref_pubkeyid_title">Utiliser l\'authentification par clé publique</string> - <string name="hostpref_authagent_title">Utiliser l\'agent d\'authentification SSH</string> - <string name="hostpref_postlogin_title">Commande à exécuter automatiquement après l\'authentification</string> - <string name="hostpref_postlogin_summary">Commandes à lancer sur le serveur distant après s\'être authentifié</string> - <string name="hostpref_compression_title">Compression</string> - <string name="hostpref_compression_summary">Cela peut aider pour les réseaux lents</string> - <string name="hostpref_wantsession_title">Démarrer une session en ligne de commande</string> - <string name="hostpref_wantsession_summary">Décochez cette case pour n\'utiliser que les redirections de port</string> - <string name="hostpref_stayconnected_title">Rester connecté</string> - <string name="hostpref_stayconnected_summary">Essayer de se reconnecter à l\'hôte si on est déconnecté</string> - <string name="hostpref_delkey_title">Touche SUPPR</string> - <string name="hostpref_delkey_summary">Le code de touche envoyé quand la touche SUPPR est appuyée.</string> - <string name="hostpref_encoding_title">Encodage</string> - <string name="hostpref_encoding_summary">Jeu de caractères à utiliser pour le serveur</string> - <string name="hostpref_connection_category">Paramètres de connexion</string> - <string name="hostpref_username_title">Nom d\'utilisateur</string> - <string name="hostpref_hostname_title">Serveur</string> - <string name="hostpref_port_title">Port</string> - <string name="bind_never">Jamais connecté</string> - <string name="bind_minutes">Il y a %1$s minutes</string> - <string name="bind_hours">Il y a %1$s heures</string> - <string name="bind_days">Il y a %1$s jours</string> - <string name="console_copy_done">%1$d octets copiés dans le presse-papier</string> - <string name="console_copy_start">Touchez et tirez, ou utilisez\nles touches directionnelles\npour sélectionner la région\nà copier</string> - <string name="console_menu_close">Fermer</string> - <string name="console_menu_copy">Copier</string> - <string name="console_menu_paste">Coller</string> - <string name="console_menu_portforwards">Redirections de port</string> - <string name="console_menu_resize">Forcer la taille</string> - <string name="console_menu_urlscan">Lister les URL</string> - <string name="button_yes">Oui</string> - <string name="button_no">Non</string> - <string name="portforward_local">Local</string> - <string name="portforward_remote">Distant</string> - <string name="portforward_dynamic">Dynamique (SOCKS)</string> - <string name="portforward_pos">Créer la redirection de port</string> - <string name="portforward_done">Redirection de port créée avec succès</string> - <string name="portforward_problem">Problème de création de la redirection de port, peut-être utilisez-vous un port sous le 1024 ou un déjà utilisé ?</string> - <string name="portforward_menu_add">Ajouter une redirection de port</string> - <string name="hint_userhost">utilisateur\@serveur</string> - <string name="list_format_error">Utilisez le format \"%1$s\"</string> - <string name="format_username">utilisateur</string> - <string name="format_hostname">nom d\'hôte</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Gérer les clés publiques</string> - <string name="list_menu_sortcolor">Trier par couleur</string> - <string name="list_menu_sortname">Trier par nom</string> - <string name="list_menu_settings">Réglages</string> - <string name="list_host_disconnect">Déconnexion</string> - <string name="list_host_edit">Éditer le serveur</string> - <string name="list_host_portforwards">Éditer les redirections de port</string> - <string name="list_host_delete">Effacer le serveur</string> - <string name="list_host_empty">Utilisez la boîte de connexion rapide en bas\npour vous connecter à un serveur</string> - <string name="list_rotation_default">Par défaut</string> - <string name="list_rotation_land">Forcer le mode paysage</string> - <string name="list_rotation_port">Forcer le mode portrait</string> - <string name="list_rotation_auto">Automatique</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A puis Espace</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Échap</string> - <string name="list_hwbutton_esc_a">Echap+A</string> - <string name="list_hwbutton_none">Aucun</string> - <string name="list_delkey_backspace">Retour arrière</string> - <string name="list_delkey_del">Supprimer</string> - <string name="delete_message">Êtes-vous sûr de vouloir supprimer \'%1$s\' ?</string> - <string name="delete_pos">Oui, supprimer</string> - <string name="delete_neg">Annuler</string> - <string name="wizard_agree">Accepter</string> - <string name="wizard_next">Suivant</string> - <string name="wizard_back">Précédent</string> - <string name="terminal_no_hosts_connected">Aucun hôte actuellement connecté</string> - <string name="terminal_connecting">Connexion à %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">Clé de vérification de l\'hôte \'%1$s\' : %2$s</string> - <string name="terminal_failed">Authentification par clé échouée</string> - <string name="terminal_using_s2c_algorithm">Algorithme serveur vers client : %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algorithme client vers serveur : %1$s %2$s</string> - <string name="terminal_using_algorithm">Utilisation de l\'algorithme de chiffrement : %1$s %2$s</string> - <string name="terminal_auth">Tentative d\'authentification</string> - <string name="terminal_auth_pass">Tentative d\'authentification par mot de passe</string> - <string name="terminal_auth_pass_fail">L\'authentification par mot de passe a échoué</string> - <string name="terminal_auth_pubkey_any">Tentative d\'authentification avec une clé publique en mémoire</string> - <string name="terminal_auth_pubkey_invalid">La clé publique sélectionnée est invalide, essayez de sélectionner une clé dans les préférences de l\'hôte</string> - <string name="terminal_auth_pubkey_specific">Tentative d\'authentification par clé publique avec une clé publique spécifique</string> - <string name="terminal_auth_pubkey_fail">La méthode d\'authentification par clé publique avec la clé \'%1$s\' a échoué.</string> - <string name="terminal_auth_ki">Tentative d\'authentification par clavier</string> - <string name="terminal_auth_ki_fail">La méthode d\'authentification par clavier a échouée</string> - <string name="terminal_auth_fail">[L\'hôte ne supporte pas l\'authentification par mot de passe ou par clavier.]</string> - <string name="terminal_no_session">La session ne sera pas démarrée à cause des préférences de l\'hôte.</string> - <string name="terminal_enable_portfoward">Activer la redirection de port : %1$s</string> - <string name="local_shell_unavailable">Échec ! Le shell local est indisponible pour ce téléphone.</string> - <string name="notification_text">%1$s requiert votre attention.</string> - <string name="no">Non</string> - <string name="with_confirmation">Après confirmation</string> - <string name="yes">Oui</string> - <string name="exceptions_submit_message">Il semblerait que ConnectBot ait eu un problème lors de sa dernière utilisation. Voulez-vous envoyer un rapport d\'erreur aux développeurs de ConnectBot ?</string> - <string name="menu_colors_reset">Réinitialiser</string> - <string name="app_is_running">ConnectBot est en cours</string> - <string name="color_red">rouge</string> - <string name="color_green">vert</string> - <string name="color_blue">bleu</string> - <string name="color_gray">gris</string> - <string name="colors_fg">PP :</string> - <string name="color_bg">AP :</string> - <string name="image_description_connected">Connecté</string> - <string name="image_description_key_is_locked">Clef verrouillée</string> - <string name="image_description_toggle_control_character">Activer/désactiver le caractère \"contrôle\"</string> - <string name="image_description_send_escape_character">Envoyer \"échap\"</string> - <string name="image_description_show_keyboard">Afficher le clavier.</string> -</resources>
--- a/res/values-gl/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Cliente SSH simple, potente e open-source</string> - <string name="title_hosts_list">Servidores</string> - <string name="title_pubkey_list">Chaves públicas</string> - <string name="title_port_forwards_list">Redirección de portos</string> - <string name="title_host_editor">Editar servidor</string> - <string name="title_help">Axuda</string> - <string name="title_colors">Cores</string> - <string name="resolve_connect">Conectar</string> - <string name="resolve_entropy">Xerar entropía</string> - <string name="menu_insert">Engadir un servidor</string> - <string name="menu_delete">Borrar servidor</string> - <string name="menu_preferences">Preferencias</string> - <string name="help_intro">Seleccione un apartado dos seguintes para máis información dun tema particular</string> - <string name="help_about">Acerca de ConnectBot</string> - <string name="help_keyboard">Teclado</string> - <string name="pubkey_generate">Xerar</string> - <string name="pubkey_import">Importar</string> - <string name="pubkey_delete">Borrar a chave</string> - <string name="pubkey_gather_entropy">Xerando Entropía</string> - <string name="pubkey_touch_prompt">Toca esta casiña para xerar aleatoriedade: %1$d%% feito</string> - <string name="pubkey_touch_hint">Para garantir aleatoriedade durante a xeración da chave, mova o dedo aleatoriamente na casiña a continuación</string> - <string name="pubkey_generating">"Xerando par de chaves…"</string> - <string name="pubkey_copy_private">Copiar chave privada</string> - <string name="pubkey_copy_public">Copiar chave pública</string> - <string name="pubkey_list_empty">Pulse Menu para crear\nou importar pares de chaves</string> - <string name="pubkey_unknown_format">Formato descoñecido</string> - <string name="pubkey_change_password">Cambiar o contrasinal</string> - <string name="pubkey_list_pick">Seleccionar da /sdcard</string> - <string name="pubkey_import_parse_problem">Problema analisando a chave privada importada</string> - <string name="pubkey_unlock">Desbloquear chave</string> - <string name="pubkey_memory_load">Cargar en memoria</string> - <string name="pubkey_memory_unload">Descargar de memoria</string> - <string name="pubkey_load_on_start">Cargar chave ao iniciar</string> - <string name="pubkey_confirm_use">Confirmar antes de usar</string> - <string name="portforward_list_empty">Pulsar Menu para crear\nredireccións de portos</string> - <string name="portforward_edit">Editar redirección de porto</string> - <string name="portforward_delete">Borrar redirección de porto</string> - <string name="prompt_nickname">Seudónimo:</string> - <string name="prompt_nickname_hint_pubkey">A miña chave do traballo</string> - <string name="prompt_source_port">Porto orixe:</string> - <string name="prompt_destination">Destino:</string> - <string name="prompt_old_password">Contrasinal antigo:</string> - <string name="prompt_password">Contrasinal:</string> - <string name="prompt_again">(de novo)</string> - <string name="prompt_type">Tipo:</string> - <string name="prompt_password_can_be_blank">Nota: o contrasinal pode quedar baleiro</string> - <string name="host_verification_failure_warning_header">¡ATENCIÓN: A IDENTIFICACIÓN DO EQUIPO REMOTO CAMBIOU!</string> - <string name="host_verification_failure_warning">¡É POSIBLE QUE HAXA ALGUÉN FACENDO ALGO INAXEITADO!\n¡Alguén podería estar intervindo neste momento (cun ataque man-in-the-middle)!\nTamén é posible que a chave do equipo simplemente cambiara.</string> - <string name="prompt_host_disconnected">O equipo desconectouse.\n¿Pechar a sesión?</string> - <string name="prompt_continue_connecting">Seguro que quere\ncontinuar conectándose?</string> - <string name="alert_passwords_do_not_match_msg">¡Non coinciden os contrasinais!</string> - <string name="alert_wrong_password_msg">¡Contrasinal incorrecto!</string> - <string name="alert_key_corrupted_msg">¡A chave privada parece corrupta!</string> - <string name="alert_sdcard_absent">¡A tarxeta SD non está inserida!</string> - <string name="button_add">Engadir</string> - <string name="button_change">Modificar</string> - <string name="button_generate">Xerar chave</string> - <string name="button_resize">Redimensionar</string> - <string name="alert_disconnect_msg">Conexión Perdida</string> - <string name="pref_emulation_category">Emulación de terminal</string> - <string name="pref_emulation_title">Modo de emulación</string> - <string name="pref_emulation_summary">Modo de emulación de terminal para usar en conexións PTY</string> - <string name="pref_scrollback_title">Tamaño de navegación</string> - <string name="pref_scrollback_summary">Tamaño de búfer que quedará en memoria para cada consola</string> - <string name="pref_ui_category">Interface de usuario</string> - <string name="pref_rotation_title">Modo de rotación</string> - <string name="pref_rotation_summary">Como cambiar a rotación ao abrir/pechar o teclado</string> - <string name="pref_fullscreen_title">Pantalla completa</string> - <string name="pref_fullscreen_summary">Esconder a barra de estado cando estea na consola</string> - <string name="pref_memkeys_title">Recordar chaves en memoria</string> - <string name="pref_memkeys_summary">Manter chaves desbloqueadas en memoria ata que o servicio de backend teña terminado</string> - <string name="pref_update_title">Comprobar actualizacións</string> - <string name="pref_update_summary">Establecer a frecuencia máxima para comprobar as actualizacións de ConnectBot</string> - <string name="pref_conn_persist_title">Conexións persistentes</string> - <string name="pref_conn_persist_summary">Manter conexións activas en segundo plano</string> - <string name="pref_keymode_title">Atallos de teclado para directorios</string> - <string name="pref_camera_title">Atallo de teclado para a cámara</string> - <string name="pref_keepalive_title">Manter pantalla activa</string> - <string name="pref_keepalive_summary">Evitar que a pantalla se apague ao traballar nunha consola</string> - <string name="pref_wifilock_title">Manter a Wi-Fi activa</string> - <string name="pref_wifilock_summary">Evitar que a Wi-Fi se apague mentres a sesión está activa</string> - <string name="pref_bumpyarrows_summary">Vibrar ao enviar teclas de dirección dende o trackball; útil para conexións con retardos</string> - <string name="pref_bell_category">Timbre do terminal</string> - <string name="pref_bell_title">Timbre audible</string> - <string name="pref_bell_volume_title">Volume do timbre</string> - <string name="pref_bell_vibrate_title">Vibrar co timbre</string> - <string name="pref_bell_notification_title">Notificacións en segundo plano</string> - <string name="list_keymode_none">Deshabilitar</string> - <string name="list_pubkeyids_none">Non usar chaves</string> - <string name="list_pubkeyids_any">Usar calquera chave desbloqueada</string> - <string name="hostpref_fontsize_title">Tamaño da fonte (pt)</string> - <string name="hostpref_postlogin_summary">Comandos a executar no servidor remoto unha vez autenticado</string> - <string name="hostpref_compression_title">Compresión</string> - <string name="hostpref_compression_summary">Esto podería axudar en redes lentas</string> - <string name="hostpref_wantsession_title">Comezar sesión de shell</string> - <string name="hostpref_encoding_title">Codificación</string> - <string name="hostpref_encoding_summary">Codificación de caracteres para a máquina remota</string> - <string name="hostpref_connection_category">Configuracion da conexión</string> - <string name="hostpref_username_title">Nome de usuario</string> - <string name="hostpref_hostname_title">Máquina</string> - <string name="hostpref_port_title">Porto</string> - <string name="bind_never">Nunca conectado</string> - <string name="bind_minutes">Hai %1$s minutos</string> - <string name="bind_hours">Hai %1$s horas</string> - <string name="bind_days">Hai %1$s días</string> - <string name="console_copy_done">Copiados %1$d bytes ao portapapeis</string> - <string name="console_copy_start">Tocar e arrastrar\nou usar o cursor direccional\npara seleccionar a área a copiar</string> - <string name="console_menu_close">Pechar</string> - <string name="console_menu_copy">Copiar</string> - <string name="console_menu_paste">Pegar</string> - <string name="console_menu_portforwards">Redirección de portos</string> - <string name="console_menu_resize">Forzar tamaño</string> - <string name="console_menu_urlscan">Escanear URLs</string> - <string name="portforward_remote">Remoto</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> -</resources>
--- a/res/values-he/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">לקוח SSH פשוט, עצמתי ובקוד פתוח.</string> - <string name="service_desc">מתפעל חיבורי SSH ומפתחות ציבוריים שנטענים</string> - <string name="title_hosts_list">מארחים</string> - <string name="title_pubkey_list">מפתחות ציבוריים</string> - <string name="title_port_forwards_list">הפניית פתחות</string> - <string name="title_host_editor">עריכת מארח</string> - <string name="title_help">עזרה</string> - <string name="title_colors">צבעים</string> - <string name="resolve_connect">התחברות</string> - <string name="resolve_entropy">נאסף גיבוב</string> - <string name="menu_insert">הוספת מארח</string> - <string name="menu_delete">מחיקת מארח</string> - <string name="menu_preferences">העדפות</string> - <string name="help_intro">נא לבחור נושא להלן לקבל פרטים נוספים בנוגע לנושא מסוים.</string> - <string name="help_about">על אודות ConnectBot</string> - <string name="help_keyboard">מקלדת</string> - <string name="pubkey_generate">יצירה</string> - <string name="pubkey_import">יבוא</string> - <string name="pubkey_delete">מחיקת מפתח</string> - <string name="pubkey_gather_entropy">נאסף גיבוב</string> - <string name="pubkey_touch_prompt">יש לגעת בתיבה זו כדי לאסוף נתונים אקראיים: %1$d%% הושלמו</string> - <string name="pubkey_touch_hint">כדי להבטיח את האקראיות במהלך יצירת המפתח, עליך להעביר את האצבע באקראיות על התיבה שלהלן.</string> - <string name="pubkey_generating">צמד המפתחות נוצר...</string> - <string name="pubkey_copy_private">העתקת המפתח הפרטי</string> - <string name="pubkey_copy_public">העתקת המפתח הציבורי</string> - <string name="pubkey_list_empty">יש לגעת ב„תפריט“ כדי ליצור\nאו לייבא צמדי מפתחות.</string> - <string name="pubkey_unknown_format">מבנה בלתי ידוע</string> - <string name="pubkey_change_password">החלפת הססמה</string> - <string name="pubkey_list_pick">בחירה מ־/sdcard</string> - <string name="pubkey_import_parse_problem">אירעה תקלה בעת ניתוח המפתח הפרטי שייובא</string> - <string name="pubkey_unlock">שחרור המפתח</string> - <string name="pubkey_failed_add">הססמה עבור המפתח \'%1$s\' שגויה. האימות נכשל.</string> - <string name="pubkey_memory_load">טעינה לזיכרון</string> - <string name="pubkey_memory_unload">פריקה מהזיכרון</string> - <string name="pubkey_load_on_start">טעינת המפתח עם ההפעלה</string> - <string name="pubkey_confirm_use">לאמת לפני השימוש</string> - <string name="portforward_list_empty">יש לגעת ב„תפריט“ כדי ליצור\nהפניית פתחות.</string> - <string name="portforward_edit">עריכת הפניית הפתחות</string> - <string name="portforward_delete">מחיקת הפניית הפתחות</string> - <string name="prompt_nickname">כינוי:</string> - <string name="prompt_nickname_hint_pubkey">המפתח בעבודה שלי</string> - <string name="prompt_source_port">פתחת המקור:</string> - <string name="prompt_destination">יעד:</string> - <string name="prompt_old_password">ססמה ישנה:</string> - <string name="prompt_password">ססמה:</string> - <string name="prompt_again">(שוב)</string> - <string name="prompt_type">סוג:</string> - <string name="prompt_password_can_be_blank">הערה: הססמה יכולה להישאר ריקה</string> - <string name="prompt_bits">סיביות:</string> - <string name="prompt_pubkey_password">ססמה עבור המפתח \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">האם לאפשר למארח המרוחק\nלהשתמש במפתח \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">אזהרה: זיהוי המארח המרוחק השתנה!</string> - <string name="host_verification_failure_warning">יתכן שמישהו עושה טריק מלוכלך!\nיכול להיות שמישהו מנסה לצוטט לך ברגעים אלה (מתקפת סוכן אמצע)!\nיכול גם להיות שמפתח המארח הוחלף.</string> - <string name="prompt_host_disconnected">המארח התנתק.\nלסגור את החלון?</string> - <string name="prompt_continue_connecting">האם אכן\nלהמשיך בהליך החיבור?</string> - <string name="host_authenticity_warning">לא ניתן לאמת את אותנטיות המארח\'%1$s\'.</string> - <string name="host_fingerprint">טביעת האצבע של המפתח שלהמארח %1$s היא %2$s</string> - <string name="alert_passwords_do_not_match_msg">הססמאות אינן תואמות!</string> - <string name="alert_wrong_password_msg">ססמה שגויה!</string> - <string name="alert_key_corrupted_msg">המפתח הפרטי נראה פגום!</string> - <string name="alert_sdcard_absent">לא הוכנס כרטיס SD!</string> - <string name="button_add">הוספה</string> - <string name="button_change">החלפה</string> - <string name="button_generate">יצירת מפתח</string> - <string name="button_resize">שינוי גודל</string> - <string name="alert_disconnect_msg">החיבור אבד</string> - <string name="pref_emulation_category">הדמיית מסוף</string> - <string name="pref_emulation_title">מצב הדמיה</string> - <string name="pref_emulation_summary">מצב הדמיית מסוף לשימוש בחיבורי PTY</string> - <string name="pref_scrollback_title">גודל גלילה אחורה</string> - <string name="pref_scrollback_summary">גודל מטמון הגלילה שיישאר בזיכרון בכל מסוף</string> - <string name="pref_ui_category">מנשק משתמש</string> - <string name="pref_rotation_title">מצב סיבוב</string> - <string name="pref_rotation_summary">כיצד לשנות את הסיבוב כאשר המקלדת עולה/יורדת</string> - <string name="pref_fullscreen_title">מסך מלא</string> - <string name="pref_fullscreen_summary">להסתיר את שורת המצב בעת השימוש במסוף</string> - <string name="pref_memkeys_title">לשמור את המפתחות בזיכרון</string> - <string name="pref_memkeys_summary">להשאיר את המפתחות לאחר השחרור בזיכרון עד ששירות המנגנון מושבת</string> - <string name="pref_update_title">בדיקת עדכון</string> - <string name="pref_update_summary">הגדרת התדירות המרבית לבדיקת עדכונים של ConnectBot</string> - <string name="pref_conn_persist_title">חיבורים עיקשים</string> - <string name="pref_conn_persist_summary">לשמור על החיבורים פעילים ברקע</string> - <string name="pref_keymode_title">קיצורי ספריות</string> - <string name="pref_keymode_summary">ניתן לבחור כיצד להשתמש ב־Alt לטובת \'/\' וב־Shift לטובת Tab</string> - <string name="pref_camera_title">קיצור דרך מצלמה</string> - <string name="pref_camera_summary">ניתן לבחור איזה קיצור דרך יופעל בעת לחיצה על לחצן המצלמה</string> - <string name="pref_keepalive_title">להשאיר את המסך פעיל</string> - <string name="pref_keepalive_summary">למנוע את כיבוי המסך בעת העבודה עם המסוף</string> - <string name="pref_wifilock_title">להשאיר את הרשת האלחוטית פעילה</string> - <string name="pref_wifilock_summary">למנוע את כיבוי מתאם הרשת האלחוטית כאשר ישנו חלון פעיל</string> - <string name="pref_bumpyarrows_title">חצים עם רטט</string> - <string name="pref_bumpyarrows_summary">המכשיר ירטוט בעת שליחת מקשי חצים מכדור הגלילה; שימוש לחיבורים אטיים</string> - <string name="pref_bell_category">פעמון מסוף</string> - <string name="pref_bell_title">פעמון עם צליל</string> - <string name="pref_bell_volume_title">עצמת הפעמון</string> - <string name="pref_bell_vibrate_title">רטט עם הפעמון</string> - <string name="pref_bell_notification_title">התרעות ברקע</string> - <string name="pref_bell_notification_summary">שליחת התרעה כאשר מסוף שפעיל ברקע מצלצל בפעמון.</string> - <string name="list_keymode_right">שימוש במקשים מימין</string> - <string name="list_keymode_left">שימוש במקשים משמאל</string> - <string name="list_keymode_none">נטרול</string> - <string name="list_pubkeyids_none">לא להשתמש במפתחות</string> - <string name="list_pubkeyids_any">שימוש במפתח כלשהו שאינו נעול</string> - <string name="hostpref_nickname_title">כינוי</string> - <string name="hostpref_color_title">קטגוריית הצבע</string> - <string name="hostpref_fontsize_title">גודל הגופן (נק׳)</string> - <string name="hostpref_pubkeyid_title">שימוש באימות מפתח ציבורי</string> - <string name="hostpref_authagent_title">שימוש בסוכן אימות SSH</string> - <string name="hostpref_postlogin_title">אוטומציה שלאחר הכניסה</string> - <string name="hostpref_postlogin_summary">פקודות להפעלה בשרת המרוחק לאחר האימות</string> - <string name="hostpref_compression_title">דחיסה</string> - <string name="hostpref_compression_summary">אפשרות זו עשויה להועיל במקרה של רשתות אטיות</string> - <string name="hostpref_wantsession_title">הפעלת חלון מעטפת</string> - <string name="hostpref_wantsession_summary">ניתן לנטרל אפשרות זו כדי להשתמש בהפניית פתחות בלבד</string> - <string name="hostpref_stayconnected_title">להשאיר את החיבור פעיל</string> - <string name="hostpref_stayconnected_summary">לנסות להתחבר שוב למארח לאחר ניתוק</string> - <string name="hostpref_delkey_title">מקש DEL</string> - <string name="hostpref_delkey_summary">קוד המקש בעת לחיצה על מקש ה־DEL</string> - <string name="hostpref_encoding_title">קידוד</string> - <string name="hostpref_encoding_summary">קידוד תווים בצד המארח</string> - <string name="hostpref_connection_category">הגדרות חיבור</string> - <string name="hostpref_username_title">שם משתמש</string> - <string name="hostpref_hostname_title">מארח</string> - <string name="hostpref_port_title">פתחה</string> - <string name="bind_never">לא חובר מעולם</string> - <string name="bind_minutes">לפני %1$s דקות</string> - <string name="bind_hours">לפני %1$s שעות</string> - <string name="bind_days">לפני %1$s ימים</string> - <string name="console_copy_done">הועתקו %1$d בתים ללוח הגזירים</string> - <string name="console_copy_start">יש לגעת ולגרור\nאו להשתמש בלוח כיוונים\nכדי לבחור אזור להעתקה</string> - <string name="console_menu_close">סגירה</string> - <string name="console_menu_copy">העתקה</string> - <string name="console_menu_paste">הדבקה</string> - <string name="console_menu_portforwards">הפניית פתחות</string> - <string name="console_menu_resize">אילוץ גודל</string> - <string name="console_menu_urlscan">סריקת כתובות</string> - <string name="button_yes">כן</string> - <string name="button_no">לא</string> - <string name="portforward_local">מקומי</string> - <string name="portforward_remote">מרוחק</string> - <string name="portforward_dynamic">דינמי (SOCKS)</string> - <string name="portforward_pos">יצירת הפניית פתחות</string> - <string name="portforward_done">הפניית הפתחות נוצרה בהצלחה</string> - <string name="portforward_problem">אירעה שגיאה ביצירת הפניית פתחות, יתכן שניסית להשתמש בפתחות מתחת ל־1024 או שהפתחה כבר בשימוש?</string> - <string name="portforward_menu_add">הוספת הפניית פתחות</string> - <string name="hint_userhost">user\@hostname</string> - <string name="list_format_error">יש להשתמש בצורה „%1$s“</string> - <string name="format_username">username</string> - <string name="format_hostname">hostname</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">ניהול מפתחות ציבוריים</string> - <string name="list_menu_sortcolor">סידור לפי צבע</string> - <string name="list_menu_sortname">סידור לפי שם</string> - <string name="list_menu_settings">הגדרות</string> - <string name="list_host_disconnect">ניתוק</string> - <string name="list_host_edit">עריכת מארח</string> - <string name="list_host_portforwards">עריכת הפניית פתחות</string> - <string name="list_host_delete">מחיקת מארח</string> - <string name="list_host_empty">יש להשתמש בתיבת ההתחברות המהירה\nשלהלן כדי להתחבר למארח.</string> - <string name="list_rotation_default">בררת מחדל</string> - <string name="list_rotation_land">אילוץ מצב אופקי</string> - <string name="list_rotation_port">אילוץ מצב אנכי</string> - <string name="list_rotation_auto">אוטומטי</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A ואז רווח</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">ללא</string> - <string name="list_delkey_backspace">Backspace</string> - <string name="list_delkey_del">Delete</string> - <string name="delete_message">האם אכן למחוק את \'%1$s\'?</string> - <string name="delete_pos">כן, למחוק</string> - <string name="delete_neg">ביטול</string> - <string name="wizard_agree">מוסכם</string> - <string name="wizard_next">הבא</string> - <string name="wizard_back">הקודם</string> - <string name="terminal_no_hosts_connected">אין מארחים מחוברים כרגע</string> - <string name="terminal_connecting">מתבצעת התחברות אל %1$s:%2$d דרך %3$s</string> - <string name="terminal_sucess">מפתח של המארח המאומת \'%1$s\': %2$s</string> - <string name="terminal_failed">אימות מפתח המארח נכשל.</string> - <string name="terminal_using_s2c_algorithm">אלגוריתם שרת ללקוח: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">אלגוריתם לקוח לשרת: %1$s %2$s</string> - <string name="terminal_using_algorithm">אלגוריתם בשימוש: %1$s %2$s</string> - <string name="terminal_auth">מתבצע ניסיון אימות</string> - <string name="terminal_auth_pass">מתבצע ניסיון לאימות \'ססמה\'</string> - <string name="terminal_auth_pass_fail">שיטת האימות \'ססמה\' נכשלה</string> - <string name="terminal_auth_pubkey_any">מתבצע ניסיון לאימות \'מפתח ציבורי\' עם מפתחות ציבוריים כלשהם מהזיכרון</string> - <string name="terminal_auth_pubkey_invalid">המפתח הציבורי שנבחר שגוי, כדאי לנסות לבחור מחדש מפתח בעורך המארחים</string> - <string name="terminal_auth_pubkey_specific">מתבצע ניסיון לאימות \'מפתח ציבורי\' עם מפתח ציבורי מסוים</string> - <string name="terminal_auth_pubkey_fail">שיטת האימות \'מפתח ציבורי\' עם המפתח \'%1$s\' נכשלה</string> - <string name="terminal_auth_ki">מתבצע ניסיון לאימות \'פעילות-מקלדת\'</string> - <string name="terminal_auth_ki_fail">שיטת האימות \'פעילות-מקלדת\' נכשלה</string> - <string name="terminal_auth_fail">[המארח שלך אינו תומך באימות \'ססמה\' או \'פעילות-מקלדת\'.]</string> - <string name="terminal_no_session">ההפעלה לא תתחיל עקב העדפות המארח.</string> - <string name="terminal_enable_portfoward">הפעלת הפניית פתחות: %1$s</string> - <string name="local_shell_unavailable">תקלה! המעטפת המקומית אינה זמינה במכשיר זה.</string> - <string name="notification_text">ל־%1$s נדרשת תשומת הלב שלך.</string> - <string name="no">לא</string> - <string name="with_confirmation">עם אימות</string> - <string name="yes">כן</string> - <string name="exceptions_submit_message">מתברר כי חלה תקלה ב־ConnectBot במהלך ההפעלה האחרונה. האם לשלוח את הדיווח למפתחים של ConnectBot?</string> - <string name="menu_colors_reset">איפוס</string> - <string name="app_is_running">ConnectBot פעיל</string> - <string name="color_red">אדום</string> - <string name="color_green">ירוק</string> - <string name="color_blue">כחול</string> - <string name="color_gray">אפור</string> - <string name="colors_fg">קדמה:</string> - <string name="color_bg">רקע:</string> - <string name="image_description_connected">יש חיבור.</string> - <string name="image_description_key_is_locked">המפתח נעול.</string> - <string name="image_description_toggle_control_character">החלפת מצב תווי בקרה.</string> - <string name="image_description_send_escape_character">שליחת תו סליקה.</string> - <string name="image_description_show_keyboard">הצגת מקלדת.</string> -</resources>
--- a/res/values-hr/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Jednostavan, moćan, open.source SSH klijent.</string> - <string name="service_desc">Pamti SSH konekcije i učitane javne ključeve</string> - <string name="title_hosts_list">Računala</string> - <string name="title_pubkey_list">Javni ključevi</string> - <string name="title_port_forwards_list">Port forwards</string> - <string name="title_host_editor">Uredi Računalo</string> - <string name="title_help">Pomoć</string> - <string name="title_colors">Boje</string> - <string name="resolve_connect">Spoji se</string> - <string name="resolve_entropy">Očitaj Entropiju</string> - <string name="menu_insert">Dodaj računalo</string> - <string name="menu_delete">Obriši računalo</string> - <string name="menu_preferences">Postavke</string> - <string name="help_intro">Molim Vas za više informacija odaberite temu ispod.</string> - <string name="help_about">O ConnectBot-u</string> - <string name="help_keyboard">Tipkovnica</string> - <string name="pubkey_generate">Stvori</string> - <string name="pubkey_import">Uvoz</string> - <string name="pubkey_delete">Obriši ključ</string> - <string name="pubkey_gather_entropy">Sakupljanje Entropije</string> - <string name="pubkey_touch_prompt">Dotakni ovaj prozor za prikupljanje slučajnosti: %1$d%% gotovo</string> - <string name="pubkey_touch_hint">Da bi osigurali slučajnost, pomičite prst u različitim smjerovima unutar prozora dolje.</string> - <string name="pubkey_generating">Izrada para ključeva</string> - <string name="pubkey_copy_private">Kopiraj privatni ključ</string> - <string name="pubkey_copy_public">Kopiraj javni ključ</string> - <string name="pubkey_list_empty">Dotakni \"Meni\" za izradu\nili uvoz parova ključeva</string> - <string name="pubkey_unknown_format">Nepoznati format</string> - <string name="pubkey_change_password">Promijeni zaporku</string> - <string name="pubkey_list_pick">Odaberi iz /sdcard</string> - <string name="pubkey_import_parse_problem">Problem prilikom tumačenja uvezenog privatnog ključa</string> - <string name="pubkey_unlock">Otključaj ključ</string> - <string name="pubkey_failed_add">Pogrešna zaporka za ključ \'%1$s\'. Neuspješna autentikacija.</string> - <string name="pubkey_memory_load">Učitaj u memoriju</string> - <string name="pubkey_memory_unload">Isprazni iz memorije</string> - <string name="pubkey_load_on_start">Učitaj kluč na početku</string> - <string name="pubkey_confirm_use">Potvrda prije upotrebe</string> - <string name="portforward_list_empty">Dotakni \"Meni\" za izradu\nport forward</string> - <string name="portforward_edit">Uredi port forward</string> - <string name="portforward_delete">Obriši port forward</string> - <string name="prompt_nickname">Nadimak:</string> - <string name="prompt_nickname_hint_pubkey">Moj poslovni ključ</string> - <string name="prompt_source_port">Source port:</string> - <string name="prompt_destination">Destination:</string> - <string name="prompt_old_password">Stara zaporka:</string> - <string name="prompt_password">Zaporka</string> - <string name="prompt_again">(ponovo)</string> - <string name="prompt_type">Type:</string> - <string name="prompt_password_can_be_blank">Uputa: zaporka može biti prazna</string> - <string name="prompt_bits">Bits:</string> - <string name="prompt_pubkey_password">Zaporka za ključ \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Dopusti udaljenom računalu da\nkoristi ključ \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">UPOZORENJE: IDENTIFIKACIJA UDALJENOG RAČUNALA SE PROMIJENILA!</string> - <string name="host_verification_failure_warning">MOGUĆE JE DA NETKO RADI NEŠTO JAKO OPASNO!\nNetko vas možda prisluškuje upravo sada (man-in-the-middle attack!)\nTakođer je moguće da se ključ računala upravo promijenio.</string> - <string name="prompt_host_disconnected">Računalo se odspojilo.\nZatvori sesiju?</string> - <string name="prompt_continue_connecting">Jeste li sigurni da želite\nnastaviti sa spajanjem?</string> - <string name="host_authenticity_warning">Autentičnost računala \'%1$s\' se ne može provjeriti.</string> - <string name="host_fingerprint">%1$s ključ računala je %2$s</string> - <string name="alert_passwords_do_not_match_msg">Zaporke nisu iste!</string> - <string name="alert_wrong_password_msg">Kriva zaporka!</string> - <string name="alert_key_corrupted_msg">Privatni ključ je oštećen!</string> - <string name="alert_sdcard_absent">SD kartica nije umetnuta!</string> - <string name="button_add">Dodaj</string> - <string name="button_change">Promijeni</string> - <string name="button_generate">Izradi ključ</string> - <string name="button_resize">Promijeni veličinu</string> - <string name="alert_disconnect_msg">Veza prekinuta</string> - <string name="pref_emulation_category">Emulacija Terminala</string> - <string name="pref_emulation_title">Način emulacije</string> - <string name="pref_emulation_summary">Način emulacije terminala korišten za PTY veze</string> - <string name="pref_scrollback_title">Veličina ScrollBack-a</string> - <string name="pref_scrollback_summary">Veličina ScrollBack-a koja se čuva u memoriji za svaku konzolu</string> - <string name="pref_ui_category">Korisničko sučelje</string> - <string name="pref_rotation_title">Način rotacije</string> - <string name="pref_rotation_summary">Kako promijeniti rotaciju kada se tipkovnica pojavi/nestane</string> - <string name="pref_fullscreen_title">Cijeli zaslon</string> - <string name="pref_fullscreen_summary">Sakrij statusnu liniju u konzoli</string> - <string name="pref_memkeys_title">Zapamti ključeve u memoriji</string> - <string name="pref_memkeys_summary">Čuvaj otključane ključeve u memoriji dok se ne zatvori pozadinski servis</string> - <string name="pref_update_title">Provjera nadogradnji</string> - <string name="pref_update_summary">Odredi učestalost za provjeru ConnectBot nadogradnji</string> - <string name="pref_conn_persist_title">Održavaj konekcije</string> - <string name="pref_conn_persist_summary">Prisili konekcije da ostanu spojene u pozadini</string> - <string name="pref_keymode_title">Prečaci direktorija</string> - <string name="pref_keymode_summary">Izaberi kako koristiti Alt kao \'/\' i Shift kao Tab</string> - <string name="pref_camera_title">Prečac kamere</string> - <string name="pref_camera_summary">Izaberi koji prečac pokrenuti kada se stisne dugme kamere</string> - <string name="pref_keepalive_title">Održi zaslon budnim</string> - <string name="pref_keepalive_summary">Spriječi gašenje zaslona dok se koristi konzola</string> - <string name="pref_wifilock_title">Održi Wi-Fi aktivnim</string> - <string name="pref_wifilock_summary">Spriječi gašenje Wi-Fi-a dok je aktivna sesija</string> -</resources>
--- a/res/values-hu/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,327 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Egyszerű, hatékony, nyílt-forráskódú SSH kliens.</string> - <string name="service_desc">Fenntartja az SSH kapcsolatokat és a betöltött nyilvános kulcsokat</string> - <string name="auth_agent_service_desc">ssh-agent szolgáltatás más Android Appokhoz a telefonon</string> - <string name="ssh_agent_permission_label">Tárolt SSH kulcsok használata</string> - <string name="ssh_agent_permission_desc">Engedélyezi az privát kulcsok használatát SSH tranzakciókhoz. NAGYON VESZÉLYES, ha kártékony alkalmazás is hozzáfér.</string> - <string name="title_hosts_list">Kiszolgálók</string> - <string name="title_pubkey_list">Publikus kulcsok</string> - <string name="title_port_forwards_list">Port átiránytások</string> - <string name="title_host_editor">Kiszolgáló szerkesztése</string> - <string name="title_help">Súgó</string> - <string name="title_colors">Színek</string> - <string name="resolve_connect">Csatlakozás</string> - <string name="resolve_entropy">Entrópia gyűjtés</string> - <string name="menu_insert">Kiszolgáló hozzáadása</string> - <string name="menu_delete">Kiszolgáló törlése</string> - <string name="menu_preferences">Beállítások</string> - <string name="help_intro">Válasszon témakört az alábbiak közül egy adott téma részletes leírásához.</string> - <string name="help_about">A ConnectBot névjegye</string> - <string name="help_keyboard">Billentyűzet</string> - <string name="pubkey_generate">Kulcs generálása</string> - <string name="pubkey_import">Kulcs importálása</string> - <string name="pubkey_delete">Kulcs törlésee</string> - <string name="pubkey_gather_entropy">Entrópia gyűjtés</string> - <string name="pubkey_touch_prompt">Érintse meg ezt a dobozt a véletlenszerűség gyűjtéséhez: %1$d%% kész</string> - <string name="pubkey_touch_hint">A kulcs egyediségének biztosítása érdekében mozgassa ujját véletlenszerűen az alábbi dobozban.</string> - <string name="pubkey_generating">"Kulcspár generálása…"</string> - <string name="pubkey_copy_private">Privát kulcs másolása</string> - <string name="pubkey_copy_public">Nyilvános kulcs másolása</string> - <string name="pubkey_list_empty">Nyomjon Menu-t, kulcspár\n létrehozáshoz/importáláshoz.</string> - <string name="pubkey_unknown_format">Ismeretlen formátum</string> - <string name="pubkey_change_password">Jelszócsere</string> - <string name="pubkey_list_pick">Kiválaszt /sdcard -ról</string> - <string name="pubkey_import_parse_problem">Probléma a privát kulcs feldolgozása során</string> - <string name="pubkey_unlock">Kulcs feloldása</string> - <string name="pubkey_failed_add">Hibás jelszó a \'%1$s\' kulcshoz. Sikertelen azonosítás.</string> - <string name="pubkey_memory_load">Betöltés a memóriába</string> - <string name="pubkey_memory_unload">Mermória ürítése</string> - <string name="pubkey_load_on_start">Kulcs betöltése induláskor</string> - <string name="pubkey_confirm_use">Jóváhagyás használat előtt</string> - <string name="portforward_list_empty">Nyomjon Menu-t a port\nátirányításhoz.</string> - <string name="portforward_edit">Port átirányítás módosítása</string> - <string name="portforward_delete">Port átirányítás törlése</string> - <string name="prompt_nickname">Becenév:</string> - <string name="prompt_nickname_hint_pubkey">A munkahelyi kulcsom</string> - <string name="prompt_source_port">Forrás port:</string> - <string name="prompt_destination">Cél port:</string> - <string name="prompt_old_password">Régi jelszó:</string> - <string name="prompt_password">Jelszó:</string> - <string name="prompt_again">(újra)</string> - <string name="prompt_type">Típus:</string> - <string name="prompt_password_can_be_blank">Tipp: a jelszóadás nem kötelező</string> - <string name="prompt_bits">Bitek:</string> - <string name="prompt_pubkey_password">A \'%1$s\' kulcs jelszava</string> - <string name="prompt_allow_agent_to_use_key">A \'%1$s\' kulcs engedélyezése\na távoli gépnek?</string> - <string name="host_verification_failure_warning_header">FIGYELEM: A TÁVOLI GÉP AZONOSÍTÓJA MEGVÁLTOZOTT!</string> - <string name="host_verification_failure_warning">FELTEHETŐEN VALAKI GYANÚS DOLGOKAT MŰVEL! \nValaki feltehetően megpróbál lehallgatni (man-in-the-middle attack) téged! \\ nDe az is lehetséges, hogy a távoli fél kulcsa közben megváltozott.</string> - <string name="prompt_host_disconnected">A kapcsolat megszakadt.\nBezárja a folyamatot?</string> - <string name="prompt_continue_connecting">Biztosan folytatja a csatlakozást?</string> - <string name="host_authenticity_warning">A \'%1$s\' kiszolgáló azonosítása sikertelen.</string> - <string name="host_fingerprint">A %1$s kulcs ujjlenyomata a(-z) %2$s</string> - <string name="alert_passwords_do_not_match_msg">Nem egyezik a jelszó!</string> - <string name="alert_wrong_password_msg">Hibás jelszó!</string> - <string name="alert_key_corrupted_msg">Sérült privát kulcs!</string> - <string name="alert_sdcard_absent">Nincs SD kártya!</string> - <string name="button_add">Hozzáadás</string> - <string name="button_change">Módosítás</string> - <string name="button_generate">Kulcs generálása</string> - <string name="button_resize">Átméretezés</string> - <string name="button_resize_reset">Alapértelmezett méret</string> - <string name="alert_disconnect_msg">A kapcsolat megszakadt</string> - <string name="pref_emulation_category">Terminál emulálás</string> - <string name="pref_emulation_title">Emulálási mód</string> - <string name="pref_emulation_summary">Terminál emulálási mód PTY kapcsolatokhoz</string> - <string name="pref_scrollback_title">Előzmények mérete</string> - <string name="pref_scrollback_summary">Az előzmények memóriában tartandó mérete konzolonként</string> - <string name="pref_ui_category">Felhasználói felület</string> - <string name="pref_rotation_title">Forgatási mód</string> - <string name="pref_rotation_summary">Hogyan forduljon a kijelző a billentyűzet ki/becsukása során</string> - <string name="pref_memkeys_title">Kulcsok megőrzése a memóriában</string> - <string name="pref_memkeys_summary">Tartsa nyitva a memóriában lévő kulcsokat amíg a háttérszolgáltatás meg nem szűnik</string> - <string name="pref_update_title">Frissítés ellenőrzése</string> - <string name="pref_update_summary">ConnectBot frissítés ellenőrzésének maximális gyakorisága</string> - <string name="pref_conn_persist_title">Kapcsolatok fenntartása</string> - <string name="pref_conn_persist_summary">A háttérben tartsa fenn a kapcsolatokat</string> - <string name="pref_keymode_title">Könyvtár hivatkozások</string> - <string name="pref_keymode_summary">Válassza ki, hogyan kell használni az Alt-ot\n a \'/\' helyett és a Shift-et a Tab helyett</string> - <string name="pref_camera_title">Kamera gomb hivatkozás</string> - <string name="pref_camera_summary">Válassza ki a kamera gombhoz tartozó hivatkozást</string> - <string name="pref_keepalive_title">Tartsa ébren a képernyőt</string> - <string name="pref_keepalive_summary">Akadályozza meg a képernyővédő bekapcsolását konzolon végzett munka alatt</string> - <string name="pref_wifilock_title">Tartsa fenn a Wi-Fi kapcsolatot</string> - <string name="pref_wifilock_summary">Akadályozza meg a Wi-Fi kikapcsolását amíg a munka zajlik</string> - <string name="pref_bumpyarrows_title">Ugráló nyilak</string> - <string name="pref_bumpyarrows_summary">Vibráljon amikor a hanyattegérrel mozgatjuk a kurzort; hasznos lehet lassú kapcsolatoknál</string> - <string name="pref_bell_category">Terminál csengő</string> - <string name="pref_bell_title">Hallható csengő</string> - <string name="pref_bell_volume_title">Csengő hangereje</string> - <string name="pref_bell_vibrate_title">Vibráljon csengetéskor</string> - <string name="pref_bell_notification_title">Háttér figyelmeztetések</string> - <string name="pref_bell_notification_summary">Küldjön értesítőt amikor a háttérben futó terminál csenget.</string> - <string name="list_keymode_right">A jobboldali gombok használata</string> - <string name="list_keymode_left">A baloldali gombok használata</string> - <string name="list_keymode_none">Tiltás</string> - <string name="list_pubkeyids_none">Kulcsok használatának tiltása</string> - <string name="list_pubkeyids_any">Bármely kinyitott privátkulcs használata</string> - <string name="hostpref_nickname_title">Becenév</string> - <string name="hostpref_color_title">Szín-kategória</string> - <string name="hostpref_fontsize_title">Betűtipus mérete (pt)</string> - <string name="hostpref_pubkeyid_title">Nyilvános kulcs használata azonosításhoz</string> - <string name="hostpref_authagent_title">Az SSH auth agent használata</string> - <string name="hostpref_postlogin_title">Bejelentkezést követő automatikus parancsok</string> - <string name="hostpref_postlogin_summary">Olyan parancsok amelyek a bejelentkezést követően kerülnek futtatásra</string> - <string name="hostpref_compression_title">Tömörítés</string> - <string name="hostpref_compression_summary">Jól jöhet lassú házatok esetén</string> - <string name="hostpref_stayconnected_title">Maradjon csatlakozva</string> - <string name="hostpref_stayconnected_summary">Újracsatlakozás ha a kapcsolat megszakad</string> - <string name="hostpref_delkey_title">DEL billentyű</string> - <string name="hostpref_delkey_summary">Az a billenytű kód amit a DEL lenyomásakor küldünk</string> - <string name="hostpref_encoding_title">Karakterkódolás</string> - <string name="hostpref_encoding_summary">A kiszolgáló karakterkódolása</string> - <string name="hostpref_connection_category">Kapcsolat beállításai</string> - <string name="hostpref_username_title">Felhasználónév</string> - <string name="hostpref_hostname_title">Kiszolgáló</string> - <string name="hostpref_port_title">Port</string> - <string name="bind_never">Még nem csatlakozott</string> - <string name="bind_minutes">%1$s perce</string> - <string name="bind_hours">%1$s órája</string> - <string name="bind_days">%1$s napja</string> - <string name="console_copy_done">%1$d bájt a vágólapra másolva</string> - <string name="console_copy_start">Érintéssel és húzással\nvagy a hanyattegér használatával\njelölje ki a másolandó területet.</string> - <string name="console_menu_close">Bezárás</string> - <string name="console_menu_copy">Másolás</string> - <string name="console_menu_paste">Beillesztés</string> - <string name="console_menu_portforwards">Port átirányítások</string> - <string name="console_menu_resize">Méret kényszerítése</string> - <string name="console_menu_urlscan">URL Keresés</string> - <string name="console_menu_screencapture">Képernyőkép készítése</string> - <string name="console_menu_download">Fájl letöltése</string> - <string name="console_menu_upload">Fájl feltöltése</string> - <string name="button_yes">Igen</string> - <string name="button_no">Nem</string> - <string name="portforward_local">Helyi</string> - <string name="portforward_remote">Távoli</string> - <string name="portforward_dynamic">Dinamikus (SOCKS)</string> - <string name="portforward_pos">Port átirányítás létrehozása</string> - <string name="portforward_done">Sikeres port átirányítás</string> - <string name="portforward_problem">Probléma a port átirányítás létrehozása során, 1024 alatti vagy már használatban lévő portot választott?</string> - <string name="portforward_menu_add">Port átirányítás hozzáadása</string> - <string name="hint_userhost">felhasználó\@gépnév</string> - <string name="list_format_error">A %1$s formátum használata</string> - <string name="format_username">felhasználónév</string> - <string name="format_hostname">gépnév</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Publikus kulcsok kezelése</string> - <string name="list_menu_sortcolor">Rendezés szín szerint</string> - <string name="list_menu_sortname">Rendezés név szerint</string> - <string name="list_menu_settings">Beállítások</string> - <string name="list_host_disconnect">A kapcsolat bontása</string> - <string name="list_host_edit">Kiszolgáló szerkesztése</string> - <string name="list_host_portforwards">Port átirányítások szerkesztése</string> - <string name="list_host_delete">Kiszolgáló törlése</string> - <string name="list_host_empty">Használja a gyors csatlakozás dobozt\n a csatlakozáshoz.</string> - <string name="list_rotation_default">Alapbeállitás</string> - <string name="list_rotation_land">Fekvő mód kényszerítése</string> - <string name="list_rotation_port">Álló mód kényszerítése</string> - <string name="list_rotation_auto">Automatikus</string> - <string name="list_hwbutton_screen_capture">Képernyőkép készítése</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A majd Space</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Semmi</string> - <string name="list_delkey_backspace">Backspace</string> - <string name="list_delkey_del">Delete</string> - <string name="delete_message">Biztosan törli a \'%1$s\'-t?</string> - <string name="delete_pos">Igen, törlés</string> - <string name="delete_neg">Mégsem</string> - <string name="wizard_agree">Elfogad</string> - <string name="wizard_next">Következő</string> - <string name="wizard_back">Vissza</string> - <string name="terminal_no_hosts_connected">Nincs kiszolgáló csatlakozva</string> - <string name="terminal_connecting">Csatlakozás %1$s:%2$d-hoz a %3$s protokollon</string> - <string name="terminal_sucess">Azonosított \'%1$s\' gépnév kulcsa: %2$s</string> - <string name="terminal_failed">Távoli gép, kulcs azonosítása sikertelen.</string> - <string name="terminal_using_s2c_algorithm">Szerver-kliens algoritmus: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Kliens-szerver algoritmus: %1$s %2$s</string> - <string name="terminal_using_algorithm">Használt algoritmus: %1$s %2$s</string> - <string name="terminal_auth">Azonosítási probálkozás</string> - <string name="terminal_auth_pass">Próbálkozás \'password\' azonosítással</string> - <string name="terminal_auth_pass_fail">A \'password\' azonosítás sikertelen.</string> - <string name="terminal_auth_pubkey_any">Próbálkozás \'publickey\' azonosítással, bármely memóriában található nyilvános kulccsal</string> - <string name="terminal_auth_pubkey_invalid">A nyilvános kulcs hibás, próbálja újra kiválasztani a kiszolgáló kezelőből</string> - <string name="terminal_auth_pubkey_specific">Próbálkozás \'publickey\' azonosítással, választott nyilvános kulccsal</string> - <string name="terminal_auth_pubkey_fail">A \'%1$s\' kulccsal történt \'publickey\' azonosítás sikertelen.</string> - <string name="terminal_auth_ki">Próbálkozás \'keyboard-interactive\' azonosítással</string> - <string name="terminal_auth_ki_fail">\'keyboard-interactive\' azonosítás sikertelen</string> - <string name="terminal_auth_fail">[A gépnév nem támogatja a \'password\' vagy \'keyboard-interactive\' azonosítást.]</string> - <string name="terminal_no_session">A munkamenet nem kezdhető el a távoli kiszolgáló beállításai miatt.</string> - <string name="terminal_enable_portfoward">Port átirányítás engedélyezése: %1$s</string> - <string name="local_shell_unavailable">Hiba! Nem elérhető a helyi shell ezen a telefonon.</string> - <string name="notification_text">%1$s a figyelmét kéri.</string> - <string name="no">Nem</string> - <string name="with_confirmation">Csak beleegyezéssel</string> - <string name="yes">Igen</string> - <string name="exceptions_submit_message">Úgy tűnik a ConnectBot a legutóbbi futtatáskor összeomlott. Elküldi a hibanaplót a ConnectBot fejleszőinek?</string> - <string name="menu_colors_reset">Visszaállít</string> - <string name="app_is_running">ConnectBot már fut</string> - <string name="color_red">piros</string> - <string name="color_green">zöld</string> - <string name="color_blue">kék</string> - <string name="color_gray">szürke</string> - <string name="colors_fg">"Előtér":</string> - <string name="color_bg">"Háttér:"</string> - <string name="image_description_connected">"Csatlakoztatva."</string> - <string name="image_description_key_is_locked">"Billentyűzet lezárva."</string> - <string name="image_description_toggle_control_character">Vezérlőkarakter kapcsolása.</string> - <string name="image_description_send_escape_character">Escape karakter küldése.</string> - <string name="image_description_show_keyboard">Billentyűzet megjelenítése.</string> - <string name="image_description_line_input">Egysoros bevitel</string> - <string name="image_description_sym">Karakterválasztó ablak</string> - <string name="button_close">Bezárás</string> - <string name="pref_custom_keymap_title">Egyedi kiosztás</string> - <string name="pref_custom_keymap_summary">Egyedi kiosztás beállítása bizonyos billentyűkre támogatott készülékek esetén.</string> - <string name="pref_custom_keymap_disabled">kikapcsolva</string> - <string name="resize_error_title">Hiba az átméretezés során</string> - <string name="resize_error_width_height">A szélességnek és a magasságnak 0-nál nagyobbnak kell lennie.</string> - <string name="dia_resize_x">x</string> - <string name="pref_screen_capture_category">Képernyőmentés</string> - <string name="pref_screen_capture_folder">Képernyőmentés mappája</string> - <string name="pref_screen_capture_folder_summary">A mappa, ahova a lementett képernyőképek kerülnek.</string> - <string name="pref_screen_capture_popup">Képernyőmentés visszajelzés</string> - <string name="pref_screen_capture_popup_summary">Sikeres képernyőképmentés készítésekor felugró ablak.</string> - <string name="screen_capture">Képernyőmentés</string> - <string name="screenshot_success_title">Sikeres képernyőmentés</string> - <string name="screenshot_saved_as">A képernyőkép mentve:</string> - <string name="screenshot_error_title">Hiba a képernyőkép készítése közben!</string> - <string name="screenshot_not_saved_as">A képernyőképet nem sikerült menteni:</string> - <string name="pref_picker_string">Sym ablak tartalma</string> - <string name="pref_picker_string_summary">Karakterem sorozat a karakterválasztó ablakhoz</string> - <string name="pref_picker_keep_open">Sym ablak nyitva tartása</string> - <string name="pref_picker_keep_open_summary">Csak a Vissza gomb zárja be a karakterválasztó ablakot.</string> - <string name="pref_file_transfer_category">Fájlátvitel</string> - <string name="pref_file_dialog_title">Fájl kijelölés</string> - <string name="pref_file_dialog_summary">Párbeszéd ablak fájlok és mappák kijelöléséhez</string> - <string name="pref_file_dialog_builtin">beépített</string> - <string name="error_starting_app">Hiba indításkor %1$s</string> - <string name="file_chooser_select_file">Válasszon fájlt %1$s</string> - <string name="select_for_download">letöltéshez</string> - <string name="select_for_upload">feltöltéshez</string> - <string name="select_for_key_import">kulcsimportáláshoz</string> - <string name="location">Hely</string> - <string name="cant_read_folder">Nem olvasható a mappa.</string> - <string name="nnew">Új</string> - <string name="select">Válasszon</string> - <string name="file_name">Fájlnév:</string> - <string name="cancel">Mégsem</string> - <string name="save">Mentés</string> - <string name="new_file">Új fájl</string> - <string name="no_data">Nincs adat</string> - <string name="pref_download_folder">Letöltési mappa</string> - <string name="pref_download_folder_summary">Az a mappa, ahova a letöltött fájlok kerülnek</string> - <string name="pref_remote_upload_folder">Távoli feltöltési mappa</string> - <string name="pref_remote_upload_folder_summary">Az a távoli mappa, ahova a feltöltött fájlok kerülnek</string> - <string name="pref_upload_dest_prompt">Rákérdezés a távoli mappára</string> - <string name="pref_upload_dest_prompt_summary">Rákérdez arra a távoli mappára, ahova a fájl fel fog töltődni.</string> - <string name="pref_background_file_transfer">Fájlátvitel a háttérben</string> - <string name="pref_background_file_transfer_summary">A fájlok fel- és letöltése a háttérben zajlik.</string> - <string name="transfer_downloading">Fájl letöltése…</string> - <string name="transfer_downloading_file">Fájl letöltése: %1$s</string> - <string name="transfer_download_complete">A fájl letöltése kész.</string> - <string name="transfer_download_failed">A fájl letöltése nem sikerült.</string> - <string name="transfer_select_remote_download_title">Fájl(ok) letöltése</string> - <string name="transfer_select_remote_download_desc">Adja meg a letöltendő fájlok elérési útvonalát (soronként egy fájl)</string> - <string name="transfer_select_remote_upload_dest_title">Feltöltési cél</string> - <string name="transfer_select_remote_upload_dest_desc">Adja meg a kívánt távoli fájlnevet:</string> - <string name="transfer_button_download">Letöltés</string> - <string name="transfer_button_upload">Feltöltés</string> - <string name="transfer_uploading">Feltöltés…</string> - <string name="transfer_uploading_file">Fájl feltöltés: %1$s</string> - <string name="transfer_upload_complete">Fájlfeltöltés kész.</string> - <string name="transfer_upload_failed">Fájlfeltöltés nem sikerült.</string> - <string name="pubkey_export_private">Privát kulcs exportálása</string> - <string name="pubkey_export_public">"Publikus kulcs exportálása"</string> - <string name="pubkey_public_save_as">Publikus kulcs mentése</string> - <string name="pubkey_public_save_as_desc">Fájlnév (teljes elérési útvonal), ahova a publikus kulcsot menteni szeretné.</string> - <string name="pubkey_private_save_as">Privát kulcs mentése</string> - <string name="pubkey_private_save_as_desc">Fájlnév (teljes elérési útvonal), ahova a privát kulcsot menteni szeretné.</string> - <string name="pubkey_public_export_success">A publikus kulcs exportálása sikeres.</string> - <string name="pubkey_public_export_problem">Hiba a publikus kulcs exportálása során.</string> - <string name="pubkey_private_export_success">A privát kulcs exportálása sikeres.</string> - <string name="pubkey_private_export_problem">Hiba a privát kulcs exportálása során.</string> - <string name="pref_debug_category">Hibakeresési beállítások</string> - <string name="pref_debug_keycodes">Billentyűkódok kiírása</string> - <string name="pref_debug_keycodes_summary">A terminálablakban lenyomott billentyűk kódjait kiírja.</string> - <string name="keycode_pressed">A lenyomott billentyű kódja</string> - <string name="pref_extended_longpress">Bővített hosszan nyomva tartott menü</string> - <string name="pref_extended_longpress_summary">A beviteli párbeszédablakot mutatja érintés és tartás esetén.</string> - <string name="longpress_select_action">Válassza ki a műveletet</string> - <string name="longpress_enable_full_screen_mode">Teljes képernyős mód bekapcsolása</string> - <string name="longpress_disable_full_screen_mode">Teljes képernyős mód kikapcsolása</string> - <string name="longpress_change_font_size">Betűméret változtatása</string> - <string name="longpress_arrows_dialog">Nyilak</string> - <string name="longpress_fkeys_dialog">Funkcióbillentyűk</string> - <string name="longpress_ctrl_dialog">CTRL+?</string> - <string name="longpress_sym_dialog">Karakterválasztó</string> - <string name="pref_ctrl_string">CTRL ablak tartalma</string> - <string name="pref_ctrl_string_summary">Karakterek sorozata a CTRL+? kombinációkhoz.</string> - <string name="fullscreen">Teljes képernyő</string> - <string name="hostpref_wantsession_title">"Héj indítása"</string> - <string name="hostpref_wantsession_summary">"Kapcsoljuk ki, ha csak port átirányításra van szükségünk"</string> - <string name="hostpref_x11_forwarding">"X11 átirányítás"</string> - <string name="hostpref_wantx11forward_title">"X11 átirányítás bekapcsolása"</string> - <string name="hostpref_wantx11forward_summary">"X11 munkamenetek átirányítása a lentebb megadott kiszolgálóra és portra"</string> - <string name="list_hwbutton_ctrl">"CTRL"</string> - <string name="list_hwbutton_tab">"Tab"</string> - <string name="pref_custom_keymap_full">Teljes hardveres billentyűzet</string> - <string name="pref_fullscreen_title">"Teljes képernyő"</string> - <string name="pref_fullscreen_summary">"Terminál indítása teljes képernyőn"</string> - <string name="pref_search_title">"Keresés gomb"</string> - <string name="pref_search_summary">"A keresés gomb megnyomásakor végrehajtott művelet"</string> - <string name="pref_volup_title">"Hangerő fel gomb"</string> - <string name="pref_volup_summary">"A hangerő fel megnyomásakor végrehajtott művelet"</string> - <string name="pref_voldn_title">"Hangerő le gomb"</string> - <string name="pref_voldn_summary">"A hangerő le megnyomásakor végrehajtott művelet"</string> -</resources>
--- a/res/values-id/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,201 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Sederhana, tangguh, klien SSH dengan kode terbuka.</string> - <string name="service_desc">"Mengelola koneksi SSH dan kunci publik yang terrekam"</string> - <string name="title_hosts_list">Host</string> - <string name="title_pubkey_list">Kunci Publik</string> - <string name="title_host_editor">Ubah Host</string> - <string name="title_help">Bantuan</string> - <string name="resolve_connect">Hubungi</string> - <string name="resolve_entropy">Kumpulkan entropy</string> - <string name="menu_insert">Tambahkan host</string> - <string name="menu_delete">Hapus Host</string> - <string name="menu_preferences">Kesukaan</string> - <string name="help_intro">Silahkan pilih sebuah topik dibawah untuk informasi lebih lanjut di suatu subjek tertentu.</string> - <string name="help_about">Mengenai ConnectBot</string> - <string name="help_keyboard">Papan Ketik</string> - <string name="pubkey_generate">Buat</string> - <string name="pubkey_import">Impor</string> - <string name="pubkey_delete">Tombol Hapus</string> - <string name="pubkey_gather_entropy">Kumpulkan Entropy</string> - <string name="pubkey_touch_prompt">Sentuh boks ini untuk mengumpulkan ke tidak tentuan: %1$d%% selesai</string> - <string name="pubkey_touch_hint">Untuk memastikan ketidaktentuan selama pembuatan kunci, gerakkan tangan anda secara acak diatas kotak dibawah ini.</string> - <string name="pubkey_generating">Membuat pasangan kunci...</string> - <string name="pubkey_copy_private">Salin kunci pribadi</string> - <string name="pubkey_copy_public">Salin kunci publik</string> - <string name="pubkey_list_empty">Sentuh Menu untuk membuat/atau mengimpor pasangan kunci.</string> - <string name="pubkey_unknown_format">Format tidak diketahui</string> - <string name="pubkey_change_password">Ubah kata sandi</string> - <string name="pubkey_list_pick">Ambil dari /sdcard</string> - <string name="pubkey_import_parse_problem">Masalah dalam mengambil kunci pribadi yang terimpor</string> - <string name="pubkey_unlock">Buka kunci</string> - <string name="pubkey_failed_add">Kata sandi salah untuk kunci \'%1$s\'. Authentifikasi gagal.</string> - <string name="pubkey_memory_load">Muat ke memori</string> - <string name="pubkey_memory_unload">Hapus dari memori</string> - <string name="pubkey_load_on_start">Muat kunci pada saat memulai</string> - <string name="pubkey_confirm_use">Konfirmasi sebelum digunakan</string> - <string name="portforward_list_empty">Sentu Menu untuk membuat\nport forwards.</string> - <string name="portforward_edit">Ubah port forward</string> - <string name="portforward_delete">Hapus port forward</string> - <string name="prompt_nickname">Nama panggilan:</string> - <string name="prompt_nickname_hint_pubkey">Kunci kerja saya</string> - <string name="prompt_source_port">Port asal</string> - <string name="prompt_destination">Tujuan:</string> - <string name="prompt_old_password">Kata sandi sebelumnya:</string> - <string name="prompt_password">Kata sandi:</string> - <string name="prompt_again">(sekali lagi)</string> - <string name="prompt_type">Tipe:</string> - <string name="prompt_password_can_be_blank">Catatan: sandi dapat dikosongkan</string> - <string name="prompt_bits">Jumlah bit:</string> - <string name="prompt_pubkey_password">Kata sandi untuk kunci \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Ijinkan remote host untuk\nmenggunakan kunci \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">PERINGATAN: IDENTIFIKASI REMOTE HOST TELAH BERUBAH!</string> - <string name="host_verification_failure_warning">KEMUNGKINAN SESEORANG SEDANG BERBUAT KOTOR!\nSeseorang mungkin tengah menyadap anda saat ini (serangan man-in-the-middle)!\nMungkin juga kunci host baru saja diubah.</string> - <string name="prompt_host_disconnected">Sambungan dengan host telah terputus.\nTutup sesi ini?</string> - <string name="prompt_continue_connecting">Apakah Anda yakin ingin\nterus mencoba menyambungkan?</string> - <string name="host_authenticity_warning">Authentifikasi dari host \'%1$s\' tidak dapat dibuat.</string> - <string name="host_fingerprint">Host %1$s tanda tangan kunci adalah %2$s</string> - <string name="alert_passwords_do_not_match_msg">Kata sandi tidak cocok!</string> - <string name="alert_wrong_password_msg">Kata sandi salah!</string> - <string name="alert_key_corrupted_msg">Kunci pribadi nampaknya telah rusak!</string> - <string name="alert_sdcard_absent">SD card belum dimasukan!</string> - <string name="button_add">Tambahkan</string> - <string name="button_change">Ubah</string> - <string name="button_generate">Buat Kunci</string> - <string name="button_resize">Ubah ukuran</string> - <string name="alert_disconnect_msg">Koneksi terputus</string> - <string name="pref_emulation_category">Terminal Emulasi</string> - <string name="pref_emulation_title">Mode Emulasi</string> - <string name="pref_emulation_summary">Mode terminal emulasi digunakan untuk koneksi PTY</string> - <string name="pref_scrollback_title">Ukuran Scrollback</string> - <string name="pref_scrollback_summary">Ukuran penyangga scrollback yang harus tersimpan di memori pada setiap konsol</string> - <string name="pref_ui_category">Antarmuka pengguna</string> - <string name="pref_rotation_title">Mode rotasi</string> - <string name="pref_rotation_summary">Bagaimana mengubah rotasi ketika papan ketik menyembul masuk/keluar</string> - <string name="pref_fullscreen_title">Layar penuh</string> - <string name="pref_fullscreen_summary">Sembunyikan bar status ketika dalam konsol</string> - <string name="pref_memkeys_title">Ingat kunci dalam memori</string> - <string name="pref_memkeys_summary">Simpan kunci yang terbuka kedalam memori hingga layanan backend berakhir</string> - <string name="pref_update_title">Memeriksa pembaharuan</string> - <string name="pref_update_summary">Tentukan frekuensi maksimal untuk memeriksa pembaharuan pada ConnectBot</string> - <string name="pref_conn_persist_title">Pertahankan koneksi</string> - <string name="pref_conn_persist_summary">Paksa koneksi untuk tetap terhubung ketika bekerja di belakang layar</string> - <string name="pref_keymode_title">Jalan pintas direktori</string> - <string name="pref_keymode_summary">Pilih bagaimana menggunakan Alt untuk \'/\' dan Shift untuk Tab</string> - <string name="pref_camera_title">Jalan pintas kamera</string> - <string name="pref_camera_summary">Pilih jalan pintas yang akan diaktifkan saat tombol kamera ditekan</string> - <string name="pref_keepalive_title">Jaga layar tetap terbuka</string> - <string name="pref_keepalive_summary">Mencegah layar menjadi padam ketika bekerja dalam sebuah konsol</string> - <string name="pref_wifilock_title">Wi-Fi selalu aktif</string> - <string name="pref_wifilock_summary">Jaga Wi-Fi agar tidak padam ketika sesi aktif</string> - <string name="pref_bumpyarrows_title">Panah belok</string> - <string name="pref_bumpyarrows_summary">Getarkan saat mengirim tombol panah dari trackball, berguna untuk koneksi lambat</string> - <string name="pref_bell_category">Bel terminal</string> - <string name="pref_bell_title">Bel berdering</string> - <string name="pref_bell_volume_title">Volume dering</string> - <string name="pref_bell_vibrate_title">Getarkan saat berdering</string> - <string name="pref_bell_notification_title">Pemberitahuan di belakang layar</string> - <string name="pref_bell_notification_summary">Kirim pemberitahuan ketika sebuah terminal berjalan di belakang dengan membunyikan sebuah nada dering</string> - <string name="list_keymode_right">Gunakan tombol sisi kanan</string> - <string name="list_keymode_left">Gunakan tombol sisi-kiri</string> - <string name="list_keymode_none">Tidak aktif</string> - <string name="list_pubkeyids_none">Jangan gunakan kunci</string> - <string name="list_pubkeyids_any">Gunakan kunci apapun yang tidak terkunci</string> - <string name="hostpref_nickname_title">Nama panggilan</string> - <string name="hostpref_color_title">Kategori warna</string> - <string name="hostpref_fontsize_title">Ukuran huruf (pt)</string> - <string name="hostpref_pubkeyid_title">Gunakan otentifikasi pubkey</string> - <string name="hostpref_authagent_title">Gunakan SSH auth agent</string> - <string name="hostpref_postlogin_title">otomasi setelah login</string> - <string name="hostpref_postlogin_summary">Perintah yang dijalankan diremote server sekali terotentifikasi</string> - <string name="hostpref_compression_title">Kompresi</string> - <string name="hostpref_compression_summary">Ini mungkin akan membantu dengan jaringan lambat</string> - <string name="hostpref_wantsession_title">Jalankan sesi shell</string> - <string name="hostpref_wantsession_summary">Non-aktifkan kesukaan ini hanya untuk port forwards</string> - <string name="hostpref_stayconnected_summary">Coba menyambungkan kembali ke host jika terputus</string> - <string name="hostpref_delkey_title">Tombol DEL</string> - <string name="hostpref_delkey_summary">Kode kunci terkirim ketika tombol DEL ditekan</string> - <string name="hostpref_encoding_title">Pengkodean</string> - <string name="hostpref_encoding_summary">Karakter pengkodean untuk host</string> - <string name="hostpref_connection_category">Konfigurasi koneksi</string> - <string name="hostpref_username_title">Nama pengguna</string> - <string name="bind_never">Tidak pernah terhubung</string> - <string name="bind_minutes">%1$s menit yang lalu</string> - <string name="bind_hours">%1$s jam yang lalu</string> - <string name="bind_days">%1$s hari yang lalu</string> - <string name="console_copy_done">Tersalin %1$d byte ke papan-klip</string> - <string name="console_copy_start">Sentuh dan tarik\natau gunakan tombol panah\nuntuk memilih area yang akan disalin</string> - <string name="console_menu_close">Tutup</string> - <string name="console_menu_copy">Salin</string> - <string name="console_menu_paste">Tempel</string> - <string name="console_menu_portforwards">Penerusan port</string> - <string name="console_menu_resize">Paksakan ukuran</string> - <string name="console_menu_urlscan">Pindai URL</string> - <string name="portforward_local">Lokal</string> - <string name="portforward_remote">Remote</string> - <string name="portforward_dynamic">Dinamis (SOCKS)</string> - <string name="portforward_pos">Buat penerusan port</string> - <string name="portforward_done">Berhasil membuat penerusan port</string> - <string name="portforward_problem">Masalah dalam membuat penerusan port, mungkin Anda menggunakan nomor port di bawah 1024 atau nomor port telah digunakan?</string> - <string name="portforward_menu_add">Tambah penerusan port</string> - <string name="hint_userhost">pengguna\@namahost</string> - <string name="list_format_error">Gunakan bentuk \"%1$s\"</string> - <string name="format_username">pengguna</string> - <string name="format_hostname">namahost</string> - <string name="list_menu_pubkeys">Atur Pubkey</string> - <string name="list_menu_sortcolor">Urutkan berdasarkan warna</string> - <string name="list_menu_sortname">Urutkan berdasarkan nama</string> - <string name="list_menu_settings">Pengaturan</string> - <string name="list_host_disconnect">Putus koneksi</string> - <string name="list_host_edit">Ubah host</string> - <string name="list_host_portforwards">Ubah penerusan port</string> - <string name="list_host_delete">Hapus host</string> - <string name="list_host_empty">Gunakan kotak cepat-sambung\ndi bawah untuk tersambung dengan sebuah host</string> - <string name="list_rotation_default">Baku</string> - <string name="list_rotation_land">Paksakan bentuk datar</string> - <string name="list_rotation_port">Paksakan bentuk tegak</string> - <string name="list_rotation_auto">Otomatis</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A kemudian spasi</string> - <string name="list_hwbutton_none">Kosong</string> - <string name="delete_message">Apakah anda yakin ingin menghapus %1$s?</string> - <string name="delete_pos">Ya, hapus</string> - <string name="delete_neg">Batal</string> - <string name="wizard_agree">Setuju</string> - <string name="wizard_next">Selanjutnya</string> - <string name="wizard_back">Sebelumnya</string> - <string name="terminal_no_hosts_connected">Tidak ada host yang saat ini terhubung</string> - <string name="terminal_connecting">Menyambungkan ke %1$s:%2$d melalui %3$s</string> - <string name="terminal_sucess">Host terverifikasi \'%1$s\' kunci: %2$s</string> - <string name="terminal_failed">Verifikasi kunci host gagal.</string> - <string name="terminal_using_s2c_algorithm">Algoritma server-ke-klien: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algoritma klien-ke-server: %1$s %2$s</string> - <string name="terminal_using_algorithm">Menggunakan algoritma : %1$s %2$s</string> - <string name="terminal_auth">Mencoba untuk mengotentifikasi</string> - <string name="terminal_auth_pass">Mencoba otentifikasi \'kata sandi\'</string> - <string name="terminal_auth_pass_fail">Metoda otentifikasi \'kata sandi\' gagal</string> - <string name="terminal_auth_pubkey_any">Mencoba otentifikasi \'kunci publik\' dengan kunci publik apapun dalam memori</string> - <string name="terminal_auth_pubkey_invalid">Kunci publik yang dipilih tidak valid, coba pilih kembali kunci dalam editor host</string> - <string name="terminal_auth_pubkey_specific">Mencoba otentifikasi \'kunci publik\' dengan kunci publik spesifik</string> - <string name="terminal_auth_pubkey_fail">Metode otentifikasi \'kunci publik\' dengan kunci \'%1$s\' gagal</string> - <string name="terminal_auth_ki">Mencoba otentifikasi \'papan ketik interaktif\'</string> - <string name="terminal_auth_ki_fail">Metode otentifikasi \'papan ketik interaktif\' gagal</string> - <string name="terminal_auth_fail">[Host anda tidak mendukung otentifikasi \'kata sandi\' atau \'papan ketik interaktif\'.]</string> - <string name="terminal_no_session">Sesi tidak akan dimulai karena preferensi host</string> - <string name="terminal_enable_portfoward">Aktifkan port forward: %1$s</string> - <string name="local_shell_unavailable">Gagal! Shell lokal tidak tersedia di telepon ini.</string> - <string name="notification_text">%1$s memerlukan perhatian anda.</string> - <string name="with_confirmation">Dengan konfirmasi</string> - <string name="exceptions_submit_message">Sepertinya ConnectBot mengalami masalah saat berjalan sebelumnya. Kirim laporan galat ke para pengembang ConnectBot?</string> - <string name="app_is_running">ConnectBot sedang berjalan</string> - <string name="color_red">merah</string> - <string name="color_green">hijau</string> - <string name="color_blue">biru</string> - <string name="color_gray">abu-abu</string> - <string name="colors_fg">WD:</string> - <string name="color_bg">WB:</string> - <string name="image_description_connected">Tersambung.</string> - <string name="image_description_key_is_locked">Pubkey terkunci.</string> - <string name="image_description_toggle_control_character">Ubah-ubah karakter control.</string> - <string name="image_description_send_escape_character">Kirim karakter escape.</string> - <string name="image_description_show_keyboard">Perlihatkan papan ketik.</string> -</resources>
--- a/res/values-is/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="service_desc">Heldur utan um SSH tengingar og geymda \"pubkeys\"</string> - <string name="title_hosts_list">Þjónar</string> - <string name="title_pubkey_list">Almennir lyklar</string> - <string name="title_port_forwards_list">Áframsending ports</string> - <string name="title_host_editor">Breyta þjónum</string> - <string name="title_help">Hjálp</string> - <string name="title_colors">Litir</string> - <string name="resolve_connect">Tengjast</string> - <string name="resolve_entropy">Safna bitum af handahófi</string> - <string name="menu_insert">Bæta við þjóni</string> - <string name="menu_delete">Eyða þjóni</string> - <string name="menu_preferences">Valmöguleikar</string> - <string name="help_intro">Vinsamlegast veldu atriði hér að neðan til þess að fá nánari upplýsingar um það.</string> - <string name="help_about">Um ConnectBot</string> - <string name="help_keyboard">Lyklaborð</string> - <string name="pubkey_generate">Búa til</string> - <string name="pubkey_import">Flytja inn</string> - <string name="pubkey_delete">Eyða lykli</string> - <string name="pubkey_gather_entropy">Safna bitum af handahófi</string> - <string name="pubkey_touch_prompt">Snertu kassann til þess að safna bitum af handahófi, %1$d%% búið.</string> - <string name="pubkey_touch_hint">Til þess að tryggja handahófs kenndan lykil, færðu fingurinn á þér handahófskennt yfir kassann að neðan.</string> - <string name="pubkey_generating">"Framkalla lykla par…"</string> - <string name="pubkey_copy_private">Afrita einka lykil</string> - <string name="pubkey_copy_public">Afrita almennan lykil</string> - <string name="pubkey_list_empty">Ýttu á \"Menu\" til þess að búa til\neða fluttu inn lykla par.</string> - <string name="pubkey_unknown_format">Óþekkt snið</string> - <string name="pubkey_change_password">Breyta lykilorði</string> - <string name="pubkey_list_pick">Velja af /sdcard</string> - <string name="pubkey_import_parse_problem">Ekki tókst að lesa einkalykilinn</string> - <string name="pubkey_unlock">Aflæsa lykli</string> - <string name="pubkey_failed_add">Rangt lykilorð fyrir lykilinn \'%1$s\'. Staðfesting mistókst</string> - <string name="pubkey_memory_load">Hlaða inn í minni</string> - <string name="pubkey_memory_unload">Hlaða úr minni</string> - <string name="pubkey_load_on_start">Hlaða lyklum við ræsingu</string> - <string name="pubkey_confirm_use">Staðfesta fyrir notkun</string> - <string name="portforward_list_empty">Ýttu á \"Menu\" til þess að\nbúa til port áframsendingu</string> - <string name="portforward_edit">Breyta áframsendingu ports</string> - <string name="portforward_delete">Eyða áframsendingu ports</string> - <string name="prompt_nickname">Gælunafn:</string> - <string name="prompt_nickname_hint_pubkey">Lykillinn minn</string> - <string name="prompt_source_port">Frá:</string> - <string name="prompt_destination">Til:</string> - <string name="prompt_old_password">Gamla lykilorðið</string> - <string name="prompt_password">Lykilorð:</string> - <string name="prompt_again">(aftur)</string> - <string name="prompt_type">Tegund:</string> - <string name="prompt_password_can_be_blank">ATH: lykilorðið getur verið tómt</string> - <string name="prompt_bits">Bitar:</string> - <string name="prompt_pubkey_password">Lykilorð fyrir lykilinn \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Leyfa þjóninum að\nnota lykilinn \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">VIÐVÖRUN: AUÐKENNING ÞJÓNSINS HEFUR BREYST!</string> - <string name="host_verification_failure_warning">ÞAÐ ER MÖGULEIKI Á AÐ EINHVER SÉ AÐ GERA EITTHVAÐ LJÓTT!\nÞað gæti verið að einhver sé að fylgjast með með þér (man-in-the-middle árás)!\nEn það gæti líka verið að lykill þjónsins hafi einfaldlega breyst.</string> - <string name="prompt_host_disconnected">Þjónninn hefur verið aftengdur.\nViltu loka?</string> - <string name="prompt_continue_connecting">Ertu viss um að þú\nviljir halda áfram að tengjast?</string> - <string name="host_authenticity_warning">Upprunaleiki lykilsins fyrir þjóninn \'%1$s\' getur ekki verið staðfestur.</string> - <string name="host_fingerprint">Þjónninn er %1$s fingrafar lykilsins er %2$s</string> - <string name="alert_passwords_do_not_match_msg">Lykilorðin passa ekki saman!</string> - <string name="alert_wrong_password_msg">Rangt lykilorð!</string> - <string name="alert_key_corrupted_msg">Einka lykillinn lítur út fyrir að vera skemmdur!</string> - <string name="alert_sdcard_absent">SD kort er ekki til staðar!</string> - <string name="button_add">Bæta við</string> - <string name="button_change">Breyta</string> - <string name="button_generate">Framkalla lykil</string> - <string name="button_resize">Breyta stærð</string> - <string name="alert_disconnect_msg">Tengingu tapað</string> - <string name="pref_ui_category">Notenda viðmót</string> - <string name="pref_rotation_title">Snúnings hamur</string> - <string name="pref_rotation_summary">Hvernig breyta skal snúningnum þegar lyklaborðið er sýnilegt/falið</string> - <string name="pref_fullscreen_title">Fylla skjáinn</string> - <string name="pref_fullscreen_summary">Fela stöðustiku þegar tenging er virk</string> - <string name="pref_memkeys_title">Geyma lykla í minni</string> - <string name="pref_memkeys_summary">Geyma ólæsta lykla í minni þangað til forritinu er lokað</string> - <string name="pref_update_title">Athuga með uppfærslu</string> - <string name="pref_update_summary">Velja hve oft ConnectBot leitar að uppfærslum</string> - <string name="pref_conn_persist_title">Halda tengingum</string> - <string name="pref_conn_persist_summary">Halda tengingum í gangi þegar þær eru í bakgrunni</string> - <string name="pref_keymode_title">Orðabók</string> - <string name="pref_keymode_summary">Veldu hvernig nota skal Alt fyrir \'/\' og Shift fyrir Tab</string> - <string name="pref_camera_title">Myndavéla takkinn</string> - <string name="pref_camera_summary">Veldu hvað gerist þegar þrýst er á myndavéla takkann</string> - <string name="pref_keepalive_title">Halda skjánum í gangi</string> - <string name="pref_keepalive_summary">Banna skjánum að slokkna þegar tenging er virk</string> - <string name="pref_wifilock_title">Halda þráðlausu neti í gangi</string> - <string name="pref_wifilock_summary">Halda þráðlausu neti í gangi þegar tenging er virk</string> - <string name="pref_bumpyarrows_summary">Titra þegar örvar eru sendar með trackball; sniðugt fyrir óstöðugar tengingar</string> - <string name="pref_bell_category">Terminal bjalla</string> - <string name="pref_bell_title">Bjalla með hljóði</string> - <string name="pref_bell_volume_title">Hljóðstyrkur bjöllu</string> - <string name="pref_bell_vibrate_title">Titra þegar bjallan er virk</string> - <string name="pref_bell_notification_title">Boð frá bakgrunni</string> - <string name="pref_bell_notification_summary">Senda boð þegar þónn í bakgrunni sendir frá sé bjöllu.</string> - <string name="list_keymode_right">Nota hægri-hliðar lykla</string> - <string name="list_keymode_left">Nota vinstri-hliðar lykla</string> - <string name="list_keymode_none">Afvirkja</string> - <string name="list_pubkeyids_none">Ekki nota lykla</string> - <string name="list_pubkeyids_any">Nota hvaða ólæsta lykil sem er</string> - <string name="hostpref_nickname_title">Gælunafn</string> - <string name="hostpref_color_title">Lita flokk</string> - <string name="hostpref_fontsize_title">Leturstærð (pt)</string> - <string name="hostpref_pubkeyid_title">Innskráning með almennum lykli</string> - <string name="hostpref_postlogin_summary">Skipanir til þess að keyra á þjóni eftir innskráningu</string> - <string name="hostpref_compression_title">Þjöppun</string> - <string name="hostpref_compression_summary">Þetta getur hjálpað á hægu neti</string> - <string name="hostpref_stayconnected_title">Halda tengingu</string> - <string name="hostpref_stayconnected_summary">Reyna að endurtengjast ef aftenging verður</string> - <string name="hostpref_encoding_title">Kóðun</string> - <string name="hostpref_connection_category">Stillingar fyrir tengingu</string> - <string name="hostpref_username_title">Notendanafn</string> - <string name="hostpref_hostname_title">Þjónn</string> - <string name="hostpref_port_title">Port</string> - <string name="bind_never">Aldrei tengt</string> - <string name="bind_minutes">Fyrir %1$s mínútum síðan</string> - <string name="bind_hours">Fyrir %1$s tímum síðan</string> - <string name="bind_days">Fyrir %1$s dögum síðan</string> - <string name="console_copy_done">Afritaði %1$d bæti</string> - <string name="console_menu_close">Loka</string> - <string name="console_menu_copy">Afrita</string> - <string name="console_menu_paste">Líma</string> - <string name="console_menu_resize">Þvinga stærð</string> - <string name="console_menu_urlscan">Skanna fyrir slóðum</string> - <string name="button_yes">Já</string> - <string name="button_no">Nei</string> - <string name="portforward_dynamic">Breytilegt (SOCKS)</string> - <string name="portforward_pos">Áframsenda port</string> - <string name="portforward_done">Áframsendi port farsællega</string> - <string name="portforward_problem">Gat ekki áframsent portið, varstu að nota port minna en 1024? Eða er portið nú þegar áframsent?</string> - <string name="portforward_menu_add">Áframsenda port</string> - <string name="hint_userhost">notandi\@þjónn</string> - <string name="format_username">notendanafn</string> - <string name="format_hostname">þjónn</string> - <string name="format_port">port</string> - <string name="list_menu_sortcolor">Raða eftir lit</string> - <string name="list_menu_sortname">Raða eftir nafni</string> - <string name="list_menu_settings">Stillingar</string> - <string name="list_host_disconnect">Aftengjast</string> - <string name="list_host_edit">Breyta þjóni</string> - <string name="list_host_portforwards">Breyta áframsendingu ports</string> - <string name="list_host_delete">Eyða þjóni</string> - <string name="list_host_empty">Notaðu boxið hér að neðan\ntil þess að tengjast á þjón.</string> - <string name="list_rotation_default">Sjálfgefið</string> - <string name="list_rotation_land">þvinga á hlið</string> - <string name="list_rotation_port">þvinga beint</string> - <string name="list_rotation_auto">Sjálfgefið</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A og Space</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Ekkert</string> - <string name="list_delkey_del">Eyða</string> - <string name="delete_message">Ert þú viss um að þú viljir eyða \'%1$s\'?</string> - <string name="delete_pos">Já, eyða</string> - <string name="delete_neg">Hætta við</string> - <string name="wizard_agree">Samþykkja</string> - <string name="wizard_next">Næsta</string> - <string name="wizard_back">Til baka</string> - <string name="terminal_no_hosts_connected">Engir þjónar tengdir í augnablikinu</string> - <string name="terminal_connecting">Tengist við %1$s:%2$d með %3$s</string> - <string name="terminal_failed">Ekki tókst að staðfesta lykil þjóns.</string> - <string name="terminal_using_algorithm">Nota algorithmann: %1$s %2$s</string> - <string name="terminal_auth">Reyni að staðfesta</string> - <string name="terminal_auth_pass">Reyni að tengjast með lykilorði</string> - <string name="terminal_auth_pass_fail">Ekki tókst að tengjast með lykilorði</string> - <string name="terminal_enable_portfoward">Áframsenda port: %1$s</string> - <string name="notification_text">%1$s krefst athygli þinnar.</string> - <string name="no">Nei</string> - <string name="with_confirmation">Með staðfestingu</string> - <string name="yes">Já</string> - <string name="exceptions_submit_message">Það lítur út fyrir að ConnectBot hafi verið í vandræðum síðast þegar það keyrði. Viltu senda villu greiningu á höfunda forritsins?</string> - <string name="menu_colors_reset">Endurstilla</string> - <string name="app_is_running">ConnectBot er í gangi</string> - <string name="color_red">rauður</string> - <string name="color_green">grænn</string> - <string name="color_blue">blár</string> - <string name="color_gray">grár</string> -</resources>
--- a/res/values-it/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,214 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Un client SSH semplice, potente ed open-source.</string> - <string name="service_desc">Mantieni le connessioni SSH e le chiavi pubbliche caricate</string> - <string name="title_hosts_list">Connessione</string> - <string name="title_pubkey_list">Chiavi pubbliche</string> - <string name="title_port_forwards_list">Inoltro porte</string> - <string name="title_host_editor">Modifica connessione</string> - <string name="title_help">Guida</string> - <string name="title_colors">Colori</string> - <string name="resolve_connect">Connetti</string> - <string name="resolve_entropy">Raccolta disordinata</string> - <string name="menu_insert">Aggiungi connessione</string> - <string name="menu_delete">Elimina connessione</string> - <string name="menu_preferences">Preferenze</string> - <string name="help_intro">Seleziona un argomento dalla lista per ottenere maggiori informazioni.</string> - <string name="help_about">Informazioni su ConnectBot</string> - <string name="help_keyboard">Tastiera</string> - <string name="pubkey_generate">Genera</string> - <string name="pubkey_import">Importa</string> - <string name="pubkey_delete">Elimina chiave</string> - <string name="pubkey_gather_entropy">Raccolta entropia</string> - <string name="pubkey_touch_prompt">Tocca questo riquadro per raccogliere informazioni casuali: %1$d%% fatto</string> - <string name="pubkey_touch_hint">Per poter assicurare una sorgente di casualità durante la generazione della chiave, muovere le dita casualmente sul riquadro sottostante.</string> - <string name="pubkey_generating">"La coppia di chiavi viene generata…"</string> - <string name="pubkey_copy_private">Copia chiave privata</string> - <string name="pubkey_copy_public">Copia chiave pubblica</string> - <string name="pubkey_list_empty">Seleziona Menu per creare\no importare chiavi.</string> - <string name="pubkey_unknown_format">Formato non riconosciuto</string> - <string name="pubkey_change_password">Cambia password</string> - <string name="pubkey_list_pick">Leggi da /sdcard</string> - <string name="pubkey_import_parse_problem">Problemi durante l\'importazione della chiave privata</string> - <string name="pubkey_unlock">Chiave di sblocco</string> - <string name="pubkey_failed_add">Password errata per la chiave \'%1$s\'. Errore di autenticazione.</string> - <string name="pubkey_memory_load">Carica in memoria</string> - <string name="pubkey_memory_unload">Elimina dalla memoria</string> - <string name="pubkey_load_on_start">Carica la chiave all\'avvio</string> - <string name="pubkey_confirm_use">Conferma prima di usare</string> - <string name="portforward_list_empty">Seleziona Menu per creare\ninoltri delle porte.</string> - <string name="portforward_edit">Modifica inoltro porte</string> - <string name="portforward_delete">Elimina inoltro porta</string> - <string name="prompt_nickname">Nome utente:</string> - <string name="prompt_nickname_hint_pubkey">La mia chiave di lavoro</string> - <string name="prompt_source_port">Porta sorgente:</string> - <string name="prompt_destination">Destinazione:</string> - <string name="prompt_old_password">Vecchia password:</string> - <string name="prompt_password">Password:</string> - <string name="prompt_again">(ripeti)</string> - <string name="prompt_type">Tipo:</string> - <string name="prompt_password_can_be_blank">Nota: la password può essere vuota</string> - <string name="prompt_bits">Bits:</string> - <string name="prompt_pubkey_password">Password per la chiave \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Permetti all\'host remoto di\n usare la chiave \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">ATTENZIONE: L\'IDENTIFICAZIONE DELL\'HOST REMOTO E\' CAMBIATA!</string> - <string name="host_verification_failure_warning">E\' POSSIBILE CHE QUALCUNO STIA FACENDO QUALCOSA DI MALEVOLO!\nQualcuno potrebbe spiarti in questo momento (attacco man-in-the-middle)!\nMa è anche possibile che la chiave dell\'host sia cambiata.</string> - <string name="prompt_host_disconnected">L\'host si è disconnesso.\nChiudere la sessione?</string> - <string name="prompt_continue_connecting">Sei sicuro di voler\ncontinuare a connetterti?</string> - <string name="host_authenticity_warning">L\'autenticità dell\'host \'%1$s\' non può essere accertata.</string> - <string name="host_fingerprint">L\'impronta digitale della chiave dell\'Host %1$s è %2$s</string> - <string name="alert_passwords_do_not_match_msg">Le password non corrispondono!</string> - <string name="alert_wrong_password_msg">Password errata!</string> - <string name="alert_key_corrupted_msg">La chiave privata sembra corrotta!</string> - <string name="alert_sdcard_absent">Scheda SD non trovata!</string> - <string name="button_add">Aggiungi</string> - <string name="button_change">Modifica</string> - <string name="button_generate">Genera le chiavi</string> - <string name="button_resize">Ridimensiona</string> - <string name="alert_disconnect_msg">Connessione persa</string> - <string name="pref_emulation_category">Emulazione terminale</string> - <string name="pref_emulation_title">Modalità emulazione</string> - <string name="pref_emulation_summary">Modalità di emulazione terminale da usare per connessioni PTY</string> - <string name="pref_scrollback_title">Dimensione scrollback</string> - <string name="pref_scrollback_summary">Dimensione del buffer scrollback da tenere in memoria per ciascuna console</string> - <string name="pref_ui_category">Interfaccia utente</string> - <string name="pref_rotation_title">Modalità rotazione</string> - <string name="pref_rotation_summary">Come cambiare rotazione quando la tastiera esce/rientra</string> - <string name="pref_fullscreen_title">Schermo intero</string> - <string name="pref_fullscreen_summary">Nascondi la barra di stato in console</string> - <string name="pref_memkeys_title">Mantieni chiavi in memoria</string> - <string name="pref_memkeys_summary">Mantiene le chiavi in memoria finché il servizio non viene terminato</string> - <string name="pref_update_title">Controlla aggiornamenti</string> - <string name="pref_update_summary">Imposta la frequenza massima per il controllo degli aggiornamenti</string> - <string name="pref_conn_persist_title">Connessioni permanenti</string> - <string name="pref_conn_persist_summary">Forza connessioni a rimanere collegate in sottofondo</string> - <string name="pref_keymode_title">Scorciatoie directory</string> - <string name="pref_keymode_summary">Controlla l\'uso di Alt per \'/\' e di Shift per Tab</string> - <string name="pref_camera_title">Scorciatoia camera</string> - <string name="pref_camera_summary">Seleziona quale scorciatoia azionare quando il bottone della camera viene premuto</string> - <string name="pref_keepalive_title">Impedisci lo spegnimento dello schermo</string> - <string name="pref_keepalive_summary">Impedisce lo spegnimento dello schermo quando si è collegati</string> - <string name="pref_wifilock_title">Mantieni Wi-Fi attivo</string> - <string name="pref_wifilock_summary">Non spegne la connessione Wi-Fi quando una sessione è attiva</string> - <string name="pref_bumpyarrows_title">Vibrazione frecce</string> - <string name="pref_bumpyarrows_summary">Vibra quando si inviano movimenti con la trackball; utile per connessioni lente</string> - <string name="pref_bell_category">Campanella del terminale</string> - <string name="pref_bell_title">Campanella udibile</string> - <string name="pref_bell_volume_title">Volume della campanella</string> - <string name="pref_bell_vibrate_title">Vibra alla campanella</string> - <string name="pref_bell_notification_title">Notifiche in sottofondo</string> - <string name="pref_bell_notification_summary">Invia una notifica quando un terminale eseguito in sottofondo suona una campanella.</string> - <string name="list_keymode_right">Usa tasti sul lato destro</string> - <string name="list_keymode_left">Usa tasti sul lato sinistro</string> - <string name="list_keymode_none">Disabilita</string> - <string name="list_pubkeyids_none">Non usare chiavi</string> - <string name="list_pubkeyids_any">Usa qualsiasi chiave sbloccata</string> - <string name="hostpref_nickname_title">Soprannome</string> - <string name="hostpref_color_title">Categoria colore</string> - <string name="hostpref_fontsize_title">Dimensione caratteri (pt)</string> - <string name="hostpref_pubkeyid_title">Usa autenticazione a chiave pubblica</string> - <string name="hostpref_authagent_title">Usa l\'agente di autorizzazione SSH</string> - <string name="hostpref_postlogin_title">Automazione post-accesso</string> - <string name="hostpref_postlogin_summary">Comandi da eseguire su un server remoto una volta autenticati</string> - <string name="hostpref_compression_title">Compressione</string> - <string name="hostpref_compression_summary">Può essere utile con connessioni lente</string> - <string name="hostpref_wantsession_title">Avvia sessione shell</string> - <string name="hostpref_wantsession_summary">Disabilita questa preferenza per usare solo port forward</string> - <string name="hostpref_stayconnected_title">Mantieni connessioni</string> - <string name="hostpref_stayconnected_summary">Tenta di riconnettersi in caso di disconnessione</string> - <string name="hostpref_delkey_title">Tasto CANC</string> - <string name="hostpref_delkey_summary">Il codice di tastiera inviato quando viene premuto il tasto CANC</string> - <string name="hostpref_encoding_title">Codifica</string> - <string name="hostpref_encoding_summary">Codifica dei caratteri per la connessione</string> - <string name="hostpref_connection_category">Impostazioni di connessione</string> - <string name="hostpref_username_title">Nome utente</string> - <string name="hostpref_hostname_title">Host</string> - <string name="hostpref_port_title">Porta</string> - <string name="bind_never">Mai connesso</string> - <string name="bind_minutes">%1$s minuti fa</string> - <string name="bind_hours">%1$s ore fa</string> - <string name="bind_days">%1$s giorni fa</string> - <string name="console_copy_done">%1$d byte copiati</string> - <string name="console_copy_start">Tocca e trascina\noppure usa il pad direzionale\nper selezionare un\'area da copiare</string> - <string name="console_menu_close">Chiudi</string> - <string name="console_menu_copy">Copia</string> - <string name="console_menu_paste">Incolla</string> - <string name="console_menu_portforwards">Inoltro porte</string> - <string name="console_menu_resize">Forza Dimensione</string> - <string name="console_menu_urlscan">Scansione URL</string> - <string name="button_yes">Sì</string> - <string name="button_no">No</string> - <string name="portforward_local">Locale</string> - <string name="portforward_remote">Remota</string> - <string name="portforward_dynamic">Dinamica (SOCKS)</string> - <string name="portforward_pos">Crea inoltro porta</string> - <string name="portforward_done">Inoltro della porta impostato correttamente</string> - <string name="portforward_problem">Problema configurando l\'inoltro della porta, forse si cerca di usare una porta più bassa di 1024 o la porta è già in uso?</string> - <string name="portforward_menu_add">Aggiungi inoltro di una porta</string> - <string name="hint_userhost">utente\@host</string> - <string name="list_format_error">Usa il formato %1$s</string> - <string name="format_username">nome utente</string> - <string name="format_hostname">nome host</string> - <string name="format_port">porta</string> - <string name="list_menu_pubkeys">Gestione chiavi pubbliche</string> - <string name="list_menu_sortcolor">Ordina per colore</string> - <string name="list_menu_sortname">Ordina per nome</string> - <string name="list_menu_settings">Impostazioni</string> - <string name="list_host_disconnect">Disconnetti</string> - <string name="list_host_edit">Modifica connessione</string> - <string name="list_host_portforwards">Modifica inoltri porta</string> - <string name="list_host_delete">Elimina connessione</string> - <string name="list_host_empty">Usa la casella connessione rapida\nqui sotto per connetterti ad un host.</string> - <string name="list_rotation_default">Predefinita</string> - <string name="list_rotation_land">Forza orizzontale</string> - <string name="list_rotation_port">Forza verticale</string> - <string name="list_rotation_auto">Automatica</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A poi Spazio</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Niente</string> - <string name="list_delkey_backspace">Barra Spaziatrice</string> - <string name="list_delkey_del">Elimina</string> - <string name="delete_message">Sei sicuro di voler eliminare \'%1$s\'?</string> - <string name="delete_pos">Sì, elimina</string> - <string name="delete_neg">Annulla</string> - <string name="wizard_agree">Accetto</string> - <string name="wizard_next">Successiva</string> - <string name="wizard_back">Precedente</string> - <string name="terminal_no_hosts_connected">Nessun host attualmente connesso</string> - <string name="terminal_connecting">Connessione a %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">Host verificato \'%1$s\' chiave: %2$s</string> - <string name="terminal_failed">Verifica della chiave dell\'host fallita.</string> - <string name="terminal_using_s2c_algorithm">Algoritmo server-to-client: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algoritmo client-to-server: %1$s %2$s</string> - <string name="terminal_using_algorithm">Algoritmo in uso: %1$s %2$s</string> - <string name="terminal_auth">Tentativo di autenticazione</string> - <string name="terminal_auth_pass">Provando l\'autenticazione \'password\'</string> - <string name="terminal_auth_pass_fail">Metodo di autenticazione \'password\' fallito</string> - <string name="terminal_auth_pubkey_any">Tentativo di utilizzo autenticazione a \'chiave pubblica\' con una delle chiavi pubbliche in memoria</string> - <string name="terminal_auth_pubkey_invalid">La chiave pubblica selezionata non è valida, provare a riselezionare la chiave nell\'host editor</string> - <string name="terminal_auth_pubkey_specific">Tentativo di autenticazione a \'chiave pubblica\' con una chiave pubblica specifica</string> - <string name="terminal_auth_pubkey_fail">Metodo di autenticazione a \'chiave pubblica\' con la chiave \'%1$s\' fallito</string> - <string name="terminal_auth_ki">Provando l\'autenticazione \'keyboard-interactive\'</string> - <string name="terminal_auth_ki_fail">Metodo di autenticazione \'keyboard-interactive\' fallito</string> - <string name="terminal_auth_fail">[Il tuo host non supporta l\'autenticazione \'password\' o \'keyboard-interactive\'</string> - <string name="terminal_no_session">La sessione non inizierà a causa delle preferenze dell\'host.</string> - <string name="terminal_enable_portfoward">Abilita il port forward: %1$s</string> - <string name="local_shell_unavailable">Fallimento! La shell locale non è disponibile su questo telefono.</string> - <string name="notification_text">%1$s richiede la tua attenzione.</string> - <string name="no">No</string> - <string name="with_confirmation">Richiedi conferma</string> - <string name="yes">Sì</string> - <string name="exceptions_submit_message">Sembrerebbe che ConnectBot abbia avuto un problema durante l\'ultima esecuzione. Inviare una segnalazione d\'errore agli sviluppatori di ConnectBot?</string> - <string name="menu_colors_reset">Reimposta</string> - <string name="app_is_running">ConnectBot è in esecuzione</string> - <string name="color_red">rosso</string> - <string name="color_green">verde</string> - <string name="color_blue">blu</string> - <string name="color_gray">grigio</string> - <string name="image_description_connected">Connesso.</string> - <string name="image_description_key_is_locked">La chiave e\' bloccata.</string> - <string name="image_description_send_escape_character">Mandare un carattere escape.</string> - <string name="image_description_show_keyboard">Mostra la tastiera.</string> -</resources>
--- a/res/values-ja/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">シンプルでパワフルなオープンソースのSSHクライアント</string> - <string name="title_hosts_list">ホスト</string> - <string name="title_pubkey_list">公開鍵</string> - <string name="title_port_forwards_list">ポート転送</string> - <string name="title_host_editor">ホストを編集</string> - <string name="title_help">ヘルプ</string> - <string name="title_colors">配色</string> - <string name="resolve_connect">接続</string> - <string name="resolve_entropy">エントロピーの取得</string> - <string name="menu_insert">ホストを追加</string> - <string name="menu_delete">ホストを削除</string> - <string name="menu_preferences">設定</string> - <string name="help_intro">特定の情報について知りたいときは、以下のトピックを選択してください。</string> - <string name="help_about">ConnectBotについて</string> - <string name="help_keyboard">キーボード</string> - <string name="pubkey_generate">生成</string> - <string name="pubkey_import">インポート</string> - <string name="pubkey_delete">鍵を削除</string> - <string name="pubkey_gather_entropy">エントロピー収集中</string> - <string name="pubkey_touch_prompt">この四角内をランダムに触ってください: %1$d%% 完了</string> - <string name="pubkey_touch_hint">鍵作成時のランダムさを保証するため、下の四角内で指をランダムに動かしてください。</string> - <string name="pubkey_generating">"鍵ペアを生成しています…"</string> - <string name="pubkey_copy_private">秘密鍵をコピー</string> - <string name="pubkey_copy_public">公開鍵をコピー</string> - <string name="pubkey_list_empty">Menuボタンを押して鍵の作成またはインポートを行ってください。</string> - <string name="pubkey_unknown_format">不明なフォーマット</string> - <string name="pubkey_change_password">パスワードを変更</string> - <string name="pubkey_list_pick">SDカードから選ぶ</string> - <string name="pubkey_import_parse_problem">インポートした秘密鍵を解析時に問題発生</string> - <string name="pubkey_unlock">鍵をアンロック</string> - <string name="pubkey_failed_add">鍵 \'%1$s\' のパスワードが正しくありません。認証に失敗しました。</string> - <string name="pubkey_memory_load">メモリにロード</string> - <string name="pubkey_memory_unload">メモリからアンロード</string> - <string name="pubkey_load_on_start">起動時に鍵をロード</string> - <string name="pubkey_confirm_use">使用時に確認する</string> - <string name="portforward_list_empty">MENUをタップして\nポート転送を作成します.</string> - <string name="portforward_edit">ポート転送を編集</string> - <string name="portforward_delete">ポート転送を削除</string> - <string name="prompt_nickname">鍵の名前</string> - <string name="prompt_source_port">ソースポート:</string> - <string name="prompt_destination">転送先:</string> - <string name="prompt_old_password">旧パスワード:</string> - <string name="prompt_password">パスワード:</string> - <string name="prompt_again">(再入力)</string> - <string name="prompt_type">タイプ:</string> - <string name="prompt_password_can_be_blank">備考: パスワードは空欄にできます。</string> - <string name="prompt_bits">ビット長:</string> - <string name="prompt_pubkey_password">鍵 \'%1$s\' のパスワード</string> - <string name="prompt_allow_agent_to_use_key">リモートホストが鍵 \'%1$s\' を使用することを許可しますか?</string> - <string name="host_verification_failure_warning_header">警告: リモートホストのIDが変わっています!</string> - <string name="host_verification_failure_warning">何者かが不正を行っている可能性があります!\n現在誰かに盗聴されているかもしれません (中間者攻撃)!\n単にホストキーが変更されただけの可能性もあります。</string> - <string name="prompt_host_disconnected">ホスト切断されました.\nセッションを閉じますか?</string> - <string name="prompt_continue_connecting">このまま接続しますか?</string> - <string name="host_authenticity_warning">ホスト \'%1$s\' の確認ができませんでした。</string> - <string name="host_fingerprint">ホストの%1$sキーフィンガープリントは%2$s</string> - <string name="alert_passwords_do_not_match_msg">パスワードが一致しません!</string> - <string name="alert_wrong_password_msg">間違ったパスワードです.</string> - <string name="alert_key_corrupted_msg">秘密鍵が壊れています!</string> - <string name="alert_sdcard_absent">SD カードが挿入されていません.</string> - <string name="button_add">追加</string> - <string name="button_change">変更</string> - <string name="button_generate">鍵生成</string> - <string name="button_resize">リサイズ</string> - <string name="alert_disconnect_msg">接続が失われました.</string> - <string name="pref_emulation_category">端末エミュレート</string> - <string name="pref_emulation_title">エミュレートモード</string> - <string name="pref_emulation_summary">PTYで使う端末エミュレーションモード</string> - <string name="pref_scrollback_title">スクロールサイズ</string> - <string name="pref_scrollback_summary">メモリに保持するスクロールバッファのサイズ</string> - <string name="pref_ui_category">ユーザーインターフェース</string> - <string name="pref_rotation_title">画面の向き</string> - <string name="pref_rotation_summary">キーボードのポップイン/アウト時の向きの変更</string> - <string name="pref_fullscreen_title">全画面</string> - <string name="pref_fullscreen_summary">ステータスバーを隠蔽しコンソールとして利用</string> - <string name="pref_memkeys_title">メモリに鍵を保持する</string> - <string name="pref_memkeys_summary">バックエンドのサービスが終了しない限り、アンロックした鍵をメモリに保持します</string> - <string name="pref_update_title">更新を確認</string> - <string name="pref_update_summary">ConnectBotの更新をチェックする頻度を設定します</string> - <string name="pref_conn_persist_title">持続的接続</string> - <string name="pref_conn_persist_summary">バックグラウンドでの実行中に接続の持続を強制する</string> - <string name="pref_keymode_title">ディレクトリのショートカット</string> - <string name="pref_keymode_summary">Altを\'/\'、ShiftをTabに割り当てます</string> - <string name="pref_camera_title">カメラボタンショートカット</string> - <string name="pref_camera_summary">カメラボタンが押されたときのショートカットを選びます</string> - <string name="pref_keepalive_title">画面をスリープしない</string> - <string name="pref_keepalive_summary">コンソール作業中に画面がOFFになるのを防ぎます</string> - <string name="pref_wifilock_title">Wi-Fiをスリープしない</string> - <string name="pref_wifilock_summary">セッションが有効な間Wi-FiがOFFになるのを防ぎます</string> - <string name="pref_bumpyarrows_title">矢印で振動</string> - <string name="pref_bumpyarrows_summary">トラックボールで矢印キーを送信するときに振動します; ラグがある接続時に便利</string> - <string name="pref_bell_category">端末音設定</string> - <string name="pref_bell_title">ベル音</string> - <string name="pref_bell_volume_title">ボリューム設定</string> - <string name="pref_bell_vibrate_title">バイブレーション</string> - <string name="pref_bell_notification_title">バックグラウンド通知</string> - <string name="pref_bell_notification_summary">バックグランドで実行中の端末がベルを鳴らしたとき通知します</string> - <string name="list_keymode_right">右側のキーで使う</string> - <string name="list_keymode_left">左側のキーで使う</string> - <string name="list_keymode_none">無効</string> - <string name="list_pubkeyids_none">公開鍵を使わない</string> - <string name="list_pubkeyids_any">アンロックされた鍵のいずれかを使う</string> - <string name="hostpref_nickname_title">ニックネーム</string> - <string name="hostpref_color_title">色の系統</string> - <string name="hostpref_fontsize_title">フォントのサイズ (pt)</string> - <string name="hostpref_pubkeyid_title">公開鍵認証を使用</string> - <string name="hostpref_authagent_title">SSH認証エージェントを使う</string> - <string name="hostpref_postlogin_title">ログイン後の自動実行</string> - <string name="hostpref_postlogin_summary">認証後にリモートで実行するコマンド</string> - <string name="hostpref_compression_title">圧縮</string> - <string name="hostpref_compression_summary">遅いネットワークで有効かもしれません</string> - <string name="hostpref_wantsession_title">シェルセッションを使う</string> - <string name="hostpref_wantsession_summary">ポート転送のみ行う場合に無効にしてください</string> - <string name="hostpref_stayconnected_title">接続の維持</string> - <string name="hostpref_stayconnected_summary">接続が切れたら再接続を試みます</string> - <string name="hostpref_delkey_title">DELキー</string> - <string name="hostpref_delkey_summary">DELキーが押されたときに送るキーコード</string> - <string name="hostpref_encoding_title">エンコーディング</string> - <string name="hostpref_encoding_summary">ホスト側の文字エンコーディング</string> - <string name="hostpref_connection_category">接続設定</string> - <string name="hostpref_username_title">ユーザ名</string> - <string name="hostpref_hostname_title">ホスト</string> - <string name="hostpref_port_title">ポート</string> - <string name="bind_never">未接続</string> - <string name="bind_minutes">%1$s 分前</string> - <string name="bind_hours">%1$s 時間前</string> - <string name="bind_days">%1$s 日前</string> - <string name="console_copy_done">クリップボードに %1$d バイトコピーしました.</string> - <string name="console_copy_start">タッチしてドラッグ\nまたは方向パッドで\nコピー領域を選択</string> - <string name="console_menu_close">切断</string> - <string name="console_menu_copy">コピー</string> - <string name="console_menu_paste">貼り付け</string> - <string name="console_menu_portforwards">ポート転送</string> - <string name="console_menu_resize">サイズ強制</string> - <string name="console_menu_urlscan">URL スキャン</string> - <string name="button_yes">はい</string> - <string name="button_no">いいえ</string> - <string name="portforward_local">ローカル</string> - <string name="portforward_remote">リモート</string> - <string name="portforward_dynamic">動的 (SOCKS)</string> - <string name="portforward_pos">ポート転送の作成</string> - <string name="portforward_done">ポート転送の作成に成功しました.</string> - <string name="portforward_problem">ポート転送の作成ができません.おそらく1024ポート以下か既に利用されているポートを指定されています.</string> - <string name="portforward_menu_add">ポート転送の追加</string> - <string name="list_format_error">%1$s 形式を使ってください</string> - <string name="format_username">ユーザ名</string> - <string name="format_hostname">ホスト名</string> - <string name="format_port">ポート</string> - <string name="list_menu_pubkeys">公開鍵管理</string> - <string name="list_menu_sortcolor">色でソート</string> - <string name="list_menu_sortname">名前順でソート</string> - <string name="list_menu_settings">設定</string> - <string name="list_host_disconnect">切断</string> - <string name="list_host_edit">接続ホストの編集</string> - <string name="list_host_portforwards">ポート転送の編集</string> - <string name="list_host_delete">接続ホストの削除</string> - <string name="list_host_empty">下のquick-connect box\nを使ってホストに接続できます.</string> - <string name="list_rotation_default">デフォルト</string> - <string name="list_rotation_land">横向き固定</string> - <string name="list_rotation_port">縦向き固定</string> - <string name="list_rotation_auto">自動判定</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+Aに続いてSpace</string> - <string name="list_hwbutton_none">なし</string> - <string name="delete_message">\'%1$s\'を削除してよろしいですか?</string> - <string name="delete_pos">はい、削除します</string> - <string name="delete_neg">キャンセル</string> - <string name="wizard_agree">同意します</string> - <string name="wizard_next">次へ</string> - <string name="wizard_back">戻る</string> - <string name="terminal_no_hosts_connected">接続済みのホストはありません.</string> - <string name="terminal_connecting">%1$s:%2$dに%3$sで接続しています</string> - <string name="terminal_sucess">ホスト\'%1$s\' キー%2$s を検証しました</string> - <string name="terminal_failed">ホストキーが検証できません</string> - <string name="terminal_using_s2c_algorithm">サーバtoクライアント アルゴリズム: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">クライアントからサーバ アルゴリズム: %1$s %2$s</string> - <string name="terminal_using_algorithm">使用アルゴリズム: %1$s %2$s</string> - <string name="terminal_auth">認証を試行中</string> - <string name="terminal_auth_pass">\'password\' 認証を試行</string> - <string name="terminal_auth_pass_fail">\'password\' 認証失敗</string> - <string name="terminal_auth_pubkey_any">メモリ上の公開鍵による \'publickey\' 認証を試行</string> - <string name="terminal_auth_pubkey_invalid">選択された公開鍵は無効です、ホストの編集で選び直してください</string> - <string name="terminal_auth_pubkey_specific">指定された公開鍵による \'publickey\' 認証を試行</string> - <string name="terminal_auth_pubkey_fail">鍵 \'%1$s\' での \'publickey\' 認証に失敗</string> - <string name="terminal_auth_ki">\'keyboard-interactive\' 認証を試行</string> - <string name="terminal_auth_ki_fail">\'keyboard-interactive\' 認証に失敗</string> - <string name="terminal_auth_fail">[ホストは \'password\' や \'keyboard-interactive\' 認証をサポートしていません.]</string> - <string name="terminal_no_session">ホスト設定によりセッションを開始しません</string> - <string name="terminal_enable_portfoward">ポート転送 %1$s を有効化</string> - <string name="local_shell_unavailable">エラー! この電話機にはローカルシェルがありません.</string> - <string name="notification_text">%1$s でベルが鳴りました</string> - <string name="no">いいえ</string> - <string name="with_confirmation">確認が必要</string> - <string name="yes">はい</string> - <string name="exceptions_submit_message">前回ConnectBot実行時に問題が発生したようです。ConnectBotの開発者にエラーレポートを送信しますか?</string> - <string name="menu_colors_reset">リセット</string> - <string name="app_is_running">ConnectBot起動中</string> - <string name="color_red">赤</string> - <string name="color_green">緑</string> - <string name="color_blue">青</string> - <string name="color_gray">グレー</string> -</resources>
--- a/res/values-ka/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="title_host_editor">ჰოსტის შეცვლა</string> - <string name="title_help">დახმარება</string> - <string name="title_colors">ფერი</string> - <string name="resolve_connect">დაკავშირება</string> - <string name="menu_insert">ჰოსტის დამატება</string> - <string name="menu_delete">ჰოსტის წაშლა</string> - <string name="menu_preferences">პარამეტრები</string> - <string name="help_about">ConnectBot-ის შესახებ</string> - <string name="help_keyboard">კლავიატურა</string> - <string name="pubkey_generate">გენერირება</string> - <string name="pubkey_import">იმპორტი</string> - <string name="pubkey_delete">გასაღების წაშლა</string> -</resources>
--- a/res/values-ko/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">간단하고, 강력한, 오픈소스 SSH 클라이언트.</string> - <string name="title_hosts_list">호스트</string> - <string name="title_pubkey_list">공개키</string> - <string name="title_port_forwards_list">포트 포워딩</string> - <string name="title_host_editor">호스트 편집</string> - <string name="title_help">도움말</string> - <string name="title_colors">색상</string> - <string name="resolve_connect">접속</string> - <string name="resolve_entropy">엔트로피 수집</string> - <string name="menu_insert">호스트 추가</string> - <string name="menu_delete">호스트 삭제</string> - <string name="menu_preferences">기본 설정</string> - <string name="help_intro">아래의 제목들을 선택하면 특정 주제의 정보를 더 알 수 있습니다.</string> - <string name="help_about">ConnectBot 정보</string> - <string name="help_keyboard">키보드</string> - <string name="pubkey_generate">생성</string> - <string name="pubkey_import">가져오기</string> - <string name="pubkey_delete">키 삭제</string> - <string name="pubkey_gather_entropy">엔트로피 수집 중</string> - <string name="pubkey_touch_prompt">이 사각형의 랜덤으로 터치하세요: %1$d%% 완료</string> - <string name="pubkey_touch_hint">키 생성시 랜덤을 보장하기 위해 아래의 사각형 안에서 손가락을 랜덤으로 이동하십시오.</string> - <string name="pubkey_generating">"키 쌍 생성 중…"</string> - <string name="pubkey_copy_private">개인 키 복사</string> - <string name="pubkey_copy_public">공개 키 복사</string> - <string name="pubkey_list_empty">메뉴 버튼을 눌러 키 쌍을\n만들거나 가져 옵니다.</string> - <string name="pubkey_unknown_format">알 수 없는 형식</string> - <string name="pubkey_change_password">암호 바꾸기</string> - <string name="pubkey_list_pick">/sdcard에서 선택</string> - <string name="pubkey_import_parse_problem">가져온 개인키 분석 중 문제 발생</string> - <string name="pubkey_unlock">키 잠금 해제</string> - <string name="pubkey_memory_load">메모리에 올리기</string> - <string name="pubkey_memory_unload">메모리에서 내리기</string> - <string name="pubkey_load_on_start">시작할 때 키를 올리기</string> - <string name="pubkey_confirm_use">사용 전에 확인</string> - <string name="portforward_list_empty">메뉴를 눌러\n포트 포워딩을 만듭니다.</string> - <string name="portforward_edit">포트 포워딩 편집</string> - <string name="portforward_delete">포트 포워딩을 삭제</string> - <string name="prompt_nickname">대화명:</string> - <string name="prompt_nickname_hint_pubkey">내 작업 키</string> - <string name="prompt_source_port">원본 포트:</string> - <string name="prompt_destination">설명:</string> - <string name="prompt_old_password">이전 암호:</string> - <string name="prompt_password">암호:</string> - <string name="prompt_again">(다시)</string> - <string name="prompt_type">종류:</string> - <string name="prompt_password_can_be_blank">참고: 암호는 비워둘 수 있습니다.</string> - <string name="prompt_bits">비트:</string> - <string name="host_verification_failure_warning_header">경고: 원격 호스트의 식별이 바뀌었습니다!</string> - <string name="host_verification_failure_warning">누군가가 나쁜 짓을 하고 있는 것일 수 있습니다!\n지금 누군가가 당신을 도청하고 있을 수도 있습니다 (중간자 공격)!\n또는, 단순히 호스트 키가 바뀐 것일 수도 있습니다.</string> - <string name="prompt_host_disconnected">호스트 연결이 끊겼습니다.\n세션을 닫을까요?</string> - <string name="prompt_continue_connecting">정말로 연결을 진행하기\n바랍니까?</string> - <string name="host_fingerprint">호스트 %1$s 키 지문은 %2$s</string> - <string name="alert_passwords_do_not_match_msg">암호가 맞지 않습니다!</string> - <string name="alert_wrong_password_msg">잘못된 암호입니다!</string> - <string name="alert_key_corrupted_msg">개인 키가 손상되었습니다!</string> - <string name="alert_sdcard_absent">SD 카드가 삽입되지 않습니다!</string> - <string name="button_add">추가</string> - <string name="button_change">바꾸기</string> - <string name="button_generate">키 생성</string> - <string name="button_resize">크기 조정</string> - <string name="alert_disconnect_msg">연결이 끊어짐</string> - <string name="pref_emulation_category">터미널 에뮬레이션</string> - <string name="pref_emulation_title">에뮬레이션 모드</string> - <string name="pref_emulation_summary">PTY 연결 용 터미널 에뮬레이션 모드</string> - <string name="pref_scrollback_title">스크롤 크기</string> - <string name="pref_scrollback_summary">각 콘솔별로 메모리에 담아 둘 스크롤 버퍼의 크기</string> - <string name="pref_ui_category">사용자 인터페이스</string> - <string name="pref_rotation_title">회전 모드</string> - <string name="pref_rotation_summary">키보드 팝 인/아웃시 회전 방법</string> - <string name="pref_fullscreen_title">전체 화면</string> - <string name="pref_fullscreen_summary">콘솔일 때 상태 표시줄을 숨김</string> - <string name="pref_memkeys_title">메모리에 키를 기억</string> - <string name="pref_memkeys_summary">백엔드 서비스가 종료되기 전까지 잠금이 풀린 키들을 메모리에 유지합니다</string> - <string name="pref_update_title">업데이트 검사</string> - <string name="pref_update_summary">ConnectBot 업데이트 확인 주기 설정</string> - <string name="pref_conn_persist_title">접속 유지</string> - <string name="pref_conn_persist_summary">백그라운드 동안에도 강제로 연결된 상태 유지</string> - <string name="pref_keymode_title">디렉터리 바로 가기</string> - <string name="pref_camera_title">카메라 바로 가기</string> - <string name="pref_camera_summary">카메라 버튼을 눌러 실행할 바로 가기 선택</string> - <string name="pref_keepalive_title">화면 켜짐 유지</string> - <string name="pref_keepalive_summary">콘솔 작업 중 화면이 꺼지는 것을 방지</string> - <string name="pref_wifilock_title">Wi-Fi 켜짐 유지</string> - <string name="pref_wifilock_summary">세션이 유효한 동안 Wi-Fi가 꺼지지 않도록 함</string> - <string name="pref_bumpyarrows_title">방향키 진동</string> - <string name="pref_bumpyarrows_summary">트랙볼로 방향키를 보낼 때 진동합니다; 연결이 느린 경우 유용</string> - <string name="pref_bell_category">터미널 벨</string> - <string name="pref_bell_title">벨소리</string> - <string name="pref_bell_volume_title">벨 볼륨</string> - <string name="pref_bell_vibrate_title">진동 벨</string> - <string name="pref_bell_notification_title">백그라운드 알림</string> - <string name="pref_bell_notification_summary">백그라운드에서 실행중인 터미널 벨을 울리 때 알립니다.</string> - <string name="list_keymode_right">오른쪽의 키들 사용</string> - <string name="list_keymode_left">왼쪽의 키들 사용</string> - <string name="list_keymode_none">사용 안 함</string> - <string name="list_pubkeyids_none">키 사용 안함</string> - <string name="list_pubkeyids_any">잠금키 사용</string> - <string name="hostpref_nickname_title">닉네임</string> - <string name="hostpref_color_title">색상 카테고리</string> - <string name="hostpref_fontsize_title">글꼴 크기 (pt)</string> - <string name="hostpref_pubkeyid_title">공개 키 인증 사용</string> - <string name="hostpref_authagent_title">SSH 인증 에이전트 사용</string> - <string name="hostpref_postlogin_title">로그인 후 자동 실행</string> - <string name="hostpref_postlogin_summary">인증 후 원격 서버에서 실행될 명령어들</string> - <string name="hostpref_compression_title">압축</string> - <string name="hostpref_compression_summary">네트워크가 느린 경우 유용</string> - <string name="hostpref_wantsession_title">쉘 세션 시작</string> - <string name="hostpref_wantsession_summary">포트 포워드만 사용할 경우 이 설정을 해제 하세요</string> - <string name="hostpref_stayconnected_title">연결 유지</string> - <string name="hostpref_stayconnected_summary">연결이 끊기면 다시 연결을 시도</string> - <string name="hostpref_delkey_title">삭제 키</string> - <string name="hostpref_delkey_summary">삭제 키를 눌렀을 때 보낼 키 코드</string> - <string name="hostpref_encoding_title">인코딩</string> - <string name="hostpref_encoding_summary">호스트의 문자 인코딩</string> - <string name="hostpref_connection_category">접속 설정</string> - <string name="hostpref_username_title">사용자 이름</string> - <string name="hostpref_hostname_title">호스트</string> - <string name="hostpref_port_title">포트</string> - <string name="bind_never">연결된 적 없음</string> - <string name="bind_minutes">%1$s 분 전</string> - <string name="bind_hours">%1$s 시간 전</string> - <string name="bind_days">%1$s 일 전</string> - <string name="console_copy_done">클립 보드에 %1$d 바이트가 복사되었습니다.</string> - <string name="console_copy_start">터치 후 드래그 또는\n방향 키로\n복사 영역을 선택</string> - <string name="console_menu_close">닫기</string> - <string name="console_menu_copy">복사</string> - <string name="console_menu_paste">붙여넣기</string> - <string name="console_menu_portforwards">포트 포워드</string> - <string name="console_menu_resize">크기 고정</string> - <string name="console_menu_urlscan">URL 검색</string> - <string name="button_yes">예</string> - <string name="button_no">아니오</string> - <string name="portforward_local">로컬</string> - <string name="portforward_remote">원격</string> - <string name="portforward_dynamic">동적 (SOCKS)</string> - <string name="portforward_pos">포트 포워딩 만들기</string> - <string name="portforward_done">포트 포워딩을 만드는 데 성공했습니다.</string> - <string name="portforward_menu_add">포트 포워딩 추가</string> - <string name="list_format_error">%1$s 형식을 사용</string> - <string name="format_username">사용자 이름</string> - <string name="format_hostname">호스트 이름</string> - <string name="format_port">포트</string> - <string name="list_menu_pubkeys">개인키 관리자</string> - <string name="list_menu_sortcolor">색상순 정렬</string> - <string name="list_menu_sortname">이름순 정렬</string> - <string name="list_menu_settings">설정</string> - <string name="list_host_disconnect">연결끊기</string> - <string name="list_host_edit">호스트 편집</string> - <string name="list_host_portforwards">포트 포워딩 편집</string> - <string name="list_host_delete">호스트 삭제</string> - <string name="list_host_empty">아래의 빠른-연결 상자로\n호스트에 연결할 수 있습니다.</string> - <string name="list_rotation_default">기본</string> - <string name="list_rotation_land">가로 고정</string> - <string name="list_rotation_port">세로 고정</string> - <string name="list_rotation_auto">자동</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A 후 Space</string> - <string name="list_hwbutton_none">없음</string> - <string name="list_delkey_backspace">백스페이스</string> - <string name="list_delkey_del">삭제</string> - <string name="delete_pos">예, 삭제</string> - <string name="delete_neg">취소</string> - <string name="wizard_agree">동의</string> - <string name="wizard_next">다음</string> - <string name="wizard_back">뒤로</string> - <string name="terminal_no_hosts_connected">현재 연결된 호스트가 없음</string> - <string name="terminal_connecting">%3$s(으)로 %1$s:%2$d에 연결 중</string> - <string name="terminal_failed">호스트 키를 확인할 수 없습니다.</string> - <string name="terminal_using_s2c_algorithm">서버->클라이언트 알고리즘: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">클라이언트->서버 알고리즘: %1$s %2$s</string> - <string name="terminal_using_algorithm">사용중인 알고리즘: %1$s %2$s</string> - <string name="terminal_auth">인증 시도 중</string> - <string name="terminal_auth_pubkey_invalid">선택된 공개 키가 잘못되었습니다. 호스트 편집에서 키를 다시 선택해 보세요</string> - <string name="terminal_no_session">호스트 설정 동안에는 세션이 시작되지 않을 것 입니다.</string> - <string name="terminal_enable_portfoward">포트 포워딩 사용: %1$s</string> - <string name="local_shell_unavailable">실패! 이 폰은 로컬 쉘을 사용할 수 없습니다.</string> - <string name="notification_text">%1$s에서 알림이 있습니다.</string> - <string name="no">아니오</string> - <string name="with_confirmation">확인 작업 수행</string> - <string name="yes">예</string> - <string name="exceptions_submit_message">마지막으로 ConnectBot이 실행했을 때 문제가 있었던 것 같습니다. ConnectBot 개발자에 오류 보고서를 보내시겠습니까?</string> - <string name="menu_colors_reset">초기화</string> - <string name="app_is_running">ConnectBot 실행 중</string> - <string name="color_red">빨간색</string> - <string name="color_green">녹색</string> - <string name="color_blue">파란색</string> - <string name="color_gray">회색</string> -</resources>
--- a/res/values-lt/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="title_help">Pagalba</string> - <string name="title_colors">Spalvos</string> - <string name="resolve_connect">Prisijungti</string> - <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> - <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> -</resources>
--- a/res/values-lv/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources/>
--- a/res/values-mk/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Едноставен но моќен SSH клиент со отворен код.</string> - <string name="service_desc">Ги оддрѓува SSH конекциите и вчитаните pub клучеви</string> - <string name="title_hosts_list">Хостови</string> - <string name="title_pubkey_list">Pub клучеви</string> - <string name="title_host_editor">Промени хост</string> - <string name="title_help">Помош</string> - <string name="title_colors">Бои</string> - <string name="resolve_connect">Поврзи се</string> - <string name="menu_insert">Додај хост</string> - <string name="menu_delete">Одстрани хост</string> - <string name="menu_preferences">Параметри</string> - <string name="help_intro">Одбеи тема од подолу наведените за повеќе информации за таа тема.</string> - <string name="help_about">За ConnectBot</string> - <string name="help_keyboard">Тастатура</string> - <string name="pubkey_generate">Генерирај</string> - <string name="pubkey_import">Увези</string> - <string name="pubkey_delete">Одстрани клуч</string> - <string name="pubkey_generating">Се генерира пар на клучеви</string> - <string name="pubkey_copy_private">Копирај го приватниот клуч</string> - <string name="pubkey_copy_public">Копирај го јавниот клуч</string> - <string name="pubkey_list_empty">Притисни мени за да направиш\nили увезеш нов пар на клучеви</string> - <string name="pubkey_unknown_format">Непознат тип</string> - <string name="pubkey_change_password">Промени лозинка</string> - <string name="pubkey_list_pick">Превземи од /sdcard</string> - <string name="pubkey_import_parse_problem">Проблем со анализирањето на увезениот приватен клуч</string> - <string name="pubkey_unlock">Клуч за отклучување</string> - <string name="pubkey_failed_add">Погрешна лозинка за клучот \'%1$s\'. Неуспешна авторизација.</string> - <string name="pubkey_memory_load">Вчитај во меморија</string> - <string name="pubkey_memory_unload">Извади од меморијата</string> - <string name="pubkey_load_on_start">Вчитај клуч при вклучување</string> - <string name="pubkey_confirm_use">Побарај потврда пред користење</string> - <string name="prompt_nickname">Прекар:</string> - <string name="prompt_nickname_hint_pubkey">Мојот работен клуч</string> - <string name="prompt_source_port">Изворна порта:</string> - <string name="prompt_destination">Дестинација:</string> - <string name="prompt_old_password">Стара лозинка:</string> - <string name="prompt_password">Лозинка:</string> - <string name="prompt_again">(повторно)</string> - <string name="prompt_type">Тип:</string> - <string name="prompt_password_can_be_blank">Белешка: Лозинката не мора да се впише</string> - <string name="prompt_bits">Битови:</string> - <string name="prompt_pubkey_password">Лозинка за \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Дозволи му на одалечениот хост\nда го искористи \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">ПРЕДУПРЕДУВАЊЕ: ИДЕНТИФИКАЦИЈАТА НА ОДАЛЕЧЕНИОТ ХОСТ Е ПРОМЕНЕТА!</string> - <string name="host_verification_failure_warning">МОЖНО Е НЕКОЈ ДА ПРАВИ НЕШТО ЛОШО!\nНекој можеби ве прислушкува сега (напад човек во средина)!\nИсто така можно е да се променил клучот на одалечениот хост.</string> - <string name="prompt_host_disconnected">Хостот се дисконектираше.\nЗатвори ја сесијата?</string> - <string name="prompt_continue_connecting">Дали си сигурен дека\nсакаш да продолжиш со поврзување?</string> - <string name="host_authenticity_warning">Автентичноста на \'%1$s\' не може да биде потврдена.</string> - <string name="alert_passwords_do_not_match_msg">Лозинките не се совпаѓаат!</string> - <string name="alert_wrong_password_msg">Погрешна лозинка!</string> - <string name="alert_key_corrupted_msg">Приватниот клуч е корумпиран!</string> - <string name="alert_sdcard_absent">СД картичката не е ставена!</string> - <string name="button_add">Додај</string> - <string name="button_change">Промени</string> - <string name="button_generate">Направи клуч</string> - <string name="button_resize">Промени големина</string> - <string name="alert_disconnect_msg">Врската е изгубена</string> - <string name="pref_emulation_category">Емулација на терминал</string> - <string name="pref_emulation_title">Вид на емулација</string> - <string name="pref_emulation_summary">Вид на емулација на терминал да се користи за PTY врски</string> - <string name="pref_ui_category">Кориснички интерфејс</string> - <string name="pref_fullscreen_title">На цел екран</string> - <string name="pref_fullscreen_summary">Сокриј ја статусната трака додека си во конзола</string> - <string name="pref_memkeys_title">Запомни ги клучевите во меморија</string> - <string name="pref_update_title">Проверка на ажурирања</string> -</resources>
--- a/res/values-nb/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Enkel og omfattende SSH-klient med åpen kildekode.</string> - <string name="service_desc">Opprettholder SSH-tilkoblinger og innlastede offentlige nøkler</string> - <string name="title_hosts_list">Verter</string> - <string name="title_pubkey_list">Offentlige nøkler</string> - <string name="title_port_forwards_list">Portvideresending</string> - <string name="title_host_editor">Rediger vert</string> - <string name="title_help">Hjelp</string> - <string name="title_colors">Farger</string> - <string name="resolve_connect">Koble til</string> - <string name="resolve_entropy">Samle entropi</string> - <string name="menu_insert">Legg til vert</string> - <string name="menu_delete">Slett vert</string> - <string name="menu_preferences">Innstillinger</string> - <string name="help_intro">Velg en overskrift nedenfor for mer informasjon om et bestemt emne.</string> - <string name="help_about">Om ConnectBot</string> - <string name="help_keyboard">Tastatur</string> - <string name="pubkey_generate">Generer</string> - <string name="pubkey_import">Importer</string> - <string name="pubkey_delete">Slett nøkkel</string> - <string name="pubkey_gather_entropy">Samler entropi</string> - <string name="pubkey_touch_prompt">Berør denne boksen for å samle tilfeldige tall: %1$d%% ferdig</string> - <string name="pubkey_touch_hint">Beveg fingeren over boksen nedenfor for å sikre vilkårlighet ved generering av nøkkel.</string> - <string name="pubkey_generating">"Genererer nøkkelpar…"</string> - <string name="pubkey_copy_private">Kopier privat nøkkel</string> - <string name="pubkey_copy_public">Kopier offentlig nøkkel</string> - <string name="pubkey_list_empty">Trykk \"Meny\" for å opprette\neller importere nøkkelpar.</string> - <string name="pubkey_unknown_format">Ukjent format</string> - <string name="pubkey_change_password">Endre passord</string> - <string name="pubkey_list_pick">Hent fra /sdcard</string> - <string name="pubkey_import_parse_problem">Feil ved innlasting av privat nøkkel</string> - <string name="pubkey_unlock">Frigjør nøkkel</string> - <string name="pubkey_failed_add">Feil passord for nøkkel \'%1$s\'. Autentisering mislyktes.</string> - <string name="pubkey_memory_load">Last inn i minne</string> - <string name="pubkey_memory_unload">Last ut av minne</string> - <string name="pubkey_load_on_start">Last nøkkel ved start</string> - <string name="pubkey_confirm_use">Godkjenn før bruk</string> - <string name="portforward_list_empty">Trykk \"Meny\" for å opprette\nportvideresending.</string> - <string name="portforward_edit">Rediger videresendte porter</string> - <string name="portforward_delete">Slett videresendte porter</string> - <string name="prompt_nickname">Kallenavn:</string> - <string name="prompt_nickname_hint_pubkey">Min arbeidsnøkkel</string> - <string name="prompt_source_port">Kildeport:</string> - <string name="prompt_destination">Mål:</string> - <string name="prompt_old_password">Tidligere passord:</string> - <string name="prompt_password">Passord:</string> - <string name="prompt_again">(en gang til)</string> - <string name="prompt_type">Type:</string> - <string name="prompt_password_can_be_blank">NB: passord kan stå tomt</string> - <string name="prompt_bits">Bits:</string> - <string name="prompt_pubkey_password">Passord for nøkkel \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Godta ekstern vert til\nå bruke nøkkel \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">ADVARSEL: EKSTERN VERT IDENTIFIKASJON HAR BLITT ENDRET!</string> - <string name="host_verification_failure_warning">DET KAN VÆRE UGLER I MOSEN!\nNoen kan lytte på deg akkurat nå (et mellommann-angrep)!\nMen det er også mulig at vertsnøkkelen har blitt endret.</string> - <string name="prompt_host_disconnected">Vert har koblet fra.\nLukk sesjon?</string> - <string name="prompt_continue_connecting">Er du sikker på at\ndu vil koble til?</string> - <string name="host_authenticity_warning">Kan ikke bekrefte integriteten til \'%1$s\'.</string> - <string name="host_fingerprint">Nøkkelfingeravtrykk til vert %1$s er %2$s</string> - <string name="alert_passwords_do_not_match_msg">Passordene er ikke like!</string> - <string name="alert_wrong_password_msg">Feil passord!</string> - <string name="alert_key_corrupted_msg">Privat nøkkel ser ut til å være korrupt!</string> - <string name="alert_sdcard_absent">SD-kortet er ikke satt inn!</string> - <string name="button_add">Legg til</string> - <string name="button_change">Endre</string> - <string name="button_generate">Generer nøkkel</string> - <string name="button_resize">Endre størrelse</string> - <string name="alert_disconnect_msg">Mistet tilkobling</string> - <string name="pref_emulation_category">Terminalemulering</string> - <string name="pref_emulation_title">Etterligningsmodus</string> - <string name="pref_emulation_summary">Etterligningsmodus for terminal for PTY-tilkoblinger</string> - <string name="pref_scrollback_title">Husk skjermtekst</string> - <string name="pref_scrollback_summary">Mengde skjermtekst som skal beholdes i minnet for hvert konsollvindu</string> - <string name="pref_ui_category">Brukergrensesnitt</string> - <string name="pref_rotation_title">Rotasjonsretning</string> - <string name="pref_rotation_summary">Hvordan rotasjonsretning endres når tastatur skyves inn/ut</string> - <string name="pref_fullscreen_title">Full skjerm</string> - <string name="pref_fullscreen_summary">Gjem statuslinje mens du er i konsoll</string> - <string name="pref_memkeys_title">Lagre nøkler</string> - <string name="pref_memkeys_summary">Husk opplåste nøkler helt til programmet avsluttes</string> - <string name="pref_update_title">Se etter oppdateringer</string> - <string name="pref_update_summary">Angi hyppigheten for å se etter oppdateringer til ConnectBot</string> - <string name="pref_conn_persist_title">Oppretthold forbindelser</string> - <string name="pref_conn_persist_summary">Oppretthold forbindelser selv når programmet kjører i bakgrunnen</string> - <string name="pref_keymode_title">Hurtigtaster for mapper</string> - <string name="pref_keymode_summary">Velg hvordan Alt- og Skift-tasten skal brukes for \'/\' og Tab</string> - <string name="pref_camera_title">Snarvei til kamera</string> - <string name="pref_camera_summary">Velg hvilken snarvei som skal benyttes når kameraknapp trykkes</string> - <string name="pref_keepalive_title">Hold skjerm våken</string> - <string name="pref_keepalive_summary">Unngå at skjermen slås av når du jobber konsoll</string> - <string name="pref_wifilock_title">Hold Wi-Fi aktiv</string> - <string name="pref_wifilock_summary">Hindre Wi-Fi å koble fra når en økt er aktiv</string> - <string name="pref_bumpyarrows_title">Vibrerende piler</string> - <string name="pref_bumpyarrows_summary">Vibrer når pilkommandoer sendes med styrekule; nyttig for trege forbindelser</string> - <string name="pref_bell_category">Terminalklokke</string> - <string name="pref_bell_title">Varselklokke</string> - <string name="pref_bell_volume_title">Klokkevolum</string> - <string name="pref_bell_vibrate_title">Vibrere med bjelle</string> - <string name="pref_bell_notification_title">Bakgrunnsvarsling</string> - <string name="pref_bell_notification_summary">Vis varsling når en terminal i bakgrunnen gir et klokkevarsel.</string> - <string name="list_keymode_right">Bruk knapper på høyre side</string> - <string name="list_keymode_left">Bruk knapper på venstre side</string> - <string name="list_keymode_none">Deaktiver</string> - <string name="list_pubkeyids_none">Ikke bruk nøkler</string> - <string name="list_pubkeyids_any">Bruk en vilkårlig ulåst tast</string> - <string name="hostpref_nickname_title">Kallenavn</string> - <string name="hostpref_color_title">Fargeinndeling</string> - <string name="hostpref_fontsize_title">Skriftstørrelse (pt)</string> - <string name="hostpref_pubkeyid_title">Bruk offentlig nøkkel som godkjenning</string> - <string name="hostpref_authagent_title">Bruk SSH auth-agent</string> - <string name="hostpref_postlogin_title">Kommandoer etter innlogging</string> - <string name="hostpref_postlogin_summary">Kommandoer som kjøres på tilkoblet tjener etter vellykket autentisering</string> - <string name="hostpref_compression_title">Komprimering</string> - <string name="hostpref_compression_summary">Dette kan hjelpe på trege nettverk</string> - <string name="hostpref_wantsession_title">Start skallsesjon</string> - <string name="hostpref_wantsession_summary">Deaktiver denne innstillingen og benytt denne kun for portvideresending</string> - <string name="hostpref_stayconnected_title">Oppretthold forbindelse</string> - <string name="hostpref_stayconnected_summary">Forsøk å koble til på nytt ved frakobling</string> - <string name="hostpref_delkey_title">DEL-knapp</string> - <string name="hostpref_delkey_summary">Tastekode som sendes når DEL trykkes</string> - <string name="hostpref_encoding_title">Tegnkoding</string> - <string name="hostpref_encoding_summary">Tegnkoding for verten</string> - <string name="hostpref_connection_category">Tilkoblingsinnstillinger</string> - <string name="hostpref_username_title">Brukernavn</string> - <string name="hostpref_hostname_title">Vert</string> - <string name="hostpref_port_title">Port</string> - <string name="bind_never">Aldri tilkoblet</string> - <string name="bind_minutes">%1$s minutt siden</string> - <string name="bind_hours">%1$s timer siden</string> - <string name="bind_days">%1$s dager siden</string> - <string name="console_copy_done">Kopierte %1$d bytes til utklippstavle</string> - <string name="console_copy_start">Trykk og dra, eller\nbruk styrekule for å\nvelge område å\nkopiere fra</string> - <string name="console_menu_close">Lukk</string> - <string name="console_menu_copy">Kopier</string> - <string name="console_menu_paste">Lim inn</string> - <string name="console_menu_portforwards">Portvideresending</string> - <string name="console_menu_resize">Tving størrelse</string> - <string name="console_menu_urlscan">URL-søk</string> - <string name="button_yes">Ja</string> - <string name="button_no">Nei</string> - <string name="portforward_local">Lokal</string> - <string name="portforward_remote">Ekstern</string> - <string name="portforward_dynamic">Dynamisk (SOCKS)</string> - <string name="portforward_pos">Opprett portvideresending</string> - <string name="portforward_done">Vellykket oppretting av portvideresending</string> - <string name="portforward_problem">Mislyktes å opprette portvideresending. Bruker du porter under 1024, eller er denne porten allerede tatt?</string> - <string name="portforward_menu_add">Legg til portvideresending</string> - <string name="hint_userhost">bruker\@vert</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="format_username">brukernavn</string> - <string name="format_hostname">vertsnavn</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Behandle offentlige nøkler</string> - <string name="list_menu_sortcolor">Sorter etter farge</string> - <string name="list_menu_sortname">Sorter etter navn</string> - <string name="list_menu_settings">Innstillinger</string> - <string name="list_host_disconnect">Koble fra</string> - <string name="list_host_edit">Rediger vert</string> - <string name="list_host_portforwards">Rediger portvidersendinger</string> - <string name="list_host_delete">Slett vert</string> - <string name="list_host_empty">Bruk hurtigtilkoblingsboksen\nunder for å koble til en vert.</string> - <string name="list_rotation_default">Forvalg</string> - <string name="list_rotation_land">Tving landskap</string> - <string name="list_rotation_port">Tving portrett</string> - <string name="list_rotation_auto">Automatisk</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A og mellomrom</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Ingen</string> - <string name="list_delkey_backspace">Tilbaketast</string> - <string name="list_delkey_del">Slett</string> - <string name="delete_message">Er du sikker på at du vil slette \'%1$s\'?</string> - <string name="delete_pos">Ja, slett</string> - <string name="delete_neg">Avbryt</string> - <string name="wizard_agree">Godta</string> - <string name="wizard_next">Neste</string> - <string name="wizard_back">Tilbake</string> - <string name="terminal_no_hosts_connected">Ingen verter tilkoblet for øyeblikket</string> - <string name="terminal_connecting">Kobler til %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">Verifiserte vert \'%1$s\' sin nøkkel: %2$s</string> - <string name="terminal_failed">Verifisering av vertsnøkkelen feilet.</string> - <string name="terminal_using_s2c_algorithm">Algoritme fra tjener til klient: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algoritme fra klient til tjener: %1$s %2$s</string> - <string name="terminal_using_algorithm">Bruker algoritme: %1$s %2$s</string> - <string name="terminal_auth">Forsøker å autentisere</string> - <string name="terminal_auth_pass">Forsøker \'passord\'-autentisering</string> - <string name="terminal_auth_pass_fail">Autentiseringsmetode \'passord\' feilet</string> - <string name="terminal_auth_pubkey_any">Forsøker \'publickey\'-autentisering med lagrede offentlige nøkler</string> - <string name="terminal_auth_pubkey_invalid">Valgt offentlig nøkkel er ugyldig, forsøk å velge en annen nøkkel i vertsvinduet.</string> - <string name="terminal_auth_pubkey_specific">Forsøker \'publickey\'-autentisering med angitt offentlig nøkkel</string> - <string name="terminal_auth_pubkey_fail">Autentisering med \'publickey\' og nøkkel \'%1$s\' mislyktes</string> - <string name="terminal_auth_ki">Forsøker \'keyboard-interactive\' autentisering</string> - <string name="terminal_auth_ki_fail">Autentiseringsmetoden \'keyboard-interactive\' mislyktes</string> - <string name="terminal_auth_fail">[Din vert støtter ikke autentiseringsmetodene \'password\' eller \'keyboard-interactive\'.]</string> - <string name="terminal_no_session">Sesjonen vil ikke bli startet grunnet vertsinnstillinger.</string> - <string name="terminal_enable_portfoward">Aktiver portvideresending: %1$s</string> - <string name="local_shell_unavailable">Feil! Lokalt skall er utilgjengelig på denne telefonen.</string> - <string name="notification_text">%1$s ønsker din oppmerksomhet.</string> - <string name="no">Nei</string> - <string name="with_confirmation">Med bekreftelse</string> - <string name="yes">Ja</string> - <string name="exceptions_submit_message">Det ser ut som ConnectBot hadde et problem forrige gang den kjørte. Vil du sende en feilrapport til utviklerne av ConnectBot?</string> - <string name="menu_colors_reset">Tilbakestill</string> - <string name="app_is_running">ConnectBot kjører</string> - <string name="color_red">rød</string> - <string name="color_green">grønn</string> - <string name="color_blue">blå</string> - <string name="color_gray">grå</string> -</resources>
--- a/res/values-nl/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Simpele, krachtige, open-source SSH client.</string> - <string name="service_desc">Onderhoud SSH verbindingen en geladen pubkeys</string> - <string name="title_hosts_list">Hosts</string> - <string name="title_pubkey_list">Pubkeys</string> - <string name="title_port_forwards_list">Port forwards</string> - <string name="title_host_editor">Host bewerken</string> - <string name="title_help">Help</string> - <string name="title_colors">Kleuren</string> - <string name="resolve_connect">Verbinden</string> - <string name="resolve_entropy">Verzamel Entropie</string> - <string name="menu_insert">Host Toevoegen</string> - <string name="menu_delete">Host verwijderen</string> - <string name="menu_preferences">Voorkeuren</string> - <string name="help_intro">Selecteer hieronder een onderwerp voor meer informatie over een onderwerp.</string> - <string name="help_about">Over ConnectBot</string> - <string name="help_keyboard">Toetsenbord</string> - <string name="pubkey_generate">Genereren</string> - <string name="pubkey_import">Importeren</string> - <string name="pubkey_delete">Sleutel verwijderen</string> - <string name="pubkey_gather_entropy">Bezig met het verzamelen van Entropie</string> - <string name="pubkey_touch_prompt">Raak dit vierkant aan om willekeurigheid te verzamelen: %1$d%% gedaan</string> - <string name="pubkey_touch_hint">Beweeg je vinger in willekeurige volgorde over het vak beneden om er voor te zorgen dat de invoer willekeurig blijft.</string> - <string name="pubkey_generating">"Genereren van een sleutel paar…"</string> - <string name="pubkey_copy_private">Kopieer privé sleutel</string> - <string name="pubkey_copy_public">Kopieer publieke sleutel</string> - <string name="pubkey_list_empty">Tik op Menu om te maken\nof importeer sleutel paren.</string> - <string name="pubkey_unknown_format">Onbekend formaat</string> - <string name="pubkey_change_password">Verander wachtwoord</string> - <string name="pubkey_list_pick">Kies van /sdcard</string> - <string name="pubkey_import_parse_problem">Probleem met het parsen van geimporteerde privé sleutel</string> - <string name="pubkey_unlock">Ontgrendel sleutel</string> - <string name="pubkey_failed_add">Slecht wachtwoord voor sleutel \'%1$s\'. Authenticatie mislukt</string> - <string name="pubkey_memory_load">Laad in geheugen</string> - <string name="pubkey_memory_unload">Ontlaad uit geheugen</string> - <string name="pubkey_load_on_start">Laad sleutel op start</string> - <string name="pubkey_confirm_use">Bevestig voor gebruik</string> - <string name="portforward_list_empty">Tik Menu om poort\nforwards te maken.</string> - <string name="portforward_edit">Bewerk port forward</string> - <string name="portforward_delete">Verwijder port forward</string> - <string name="prompt_nickname">Bijnaam:</string> - <string name="prompt_nickname_hint_pubkey">Mijn werk sleutel</string> - <string name="prompt_source_port">Bron poort:</string> - <string name="prompt_destination">Bestemming:</string> - <string name="prompt_old_password">Oud wachtwoord:</string> - <string name="prompt_password">Wachtwoord:</string> - <string name="prompt_again">(opnieuw)</string> - <string name="prompt_type">Type:</string> - <string name="prompt_password_can_be_blank">Opmerking: wachtwoord kan leeg zijn</string> - <string name="prompt_bits">Bits:</string> - <string name="prompt_pubkey_password">Wachtwoord voor sleutel \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Sta host toe om \'%1$s\' \nsleutel te gebruiken ?</string> - <string name="host_verification_failure_warning_header">WAARSCHUWING: REMOTE HOST IDENTIFICATIE IS VERANDERD!</string> - <string name="host_verification_failure_warning">HET IS MOGELIJK DAT IEMAND ONGEWILD BEZIG IS!\nIemand kan nu misschien mee kijken met wat je aan het doen bent (man-in-the-middle attack)!\nHet is ook mogelijk dat de host sleutel veranderd is.</string> - <string name="prompt_host_disconnected">Host heeft de verbinding verbroken.\nSessie afsluiten?</string> - <string name="prompt_continue_connecting">Weet je zeker dat je\nwilt doorgaan met verbinden?</string> - <string name="host_authenticity_warning">De authenticatie van host \'%1$s\' kan niet worden vastgesteld.</string> - <string name="host_fingerprint">Host %1$s sleutel vingerafdruk is %2$s</string> - <string name="alert_passwords_do_not_match_msg">Wachtwoorden zijn niet hetzelfde!</string> - <string name="alert_wrong_password_msg">Verkeerd wachtwoord!</string> - <string name="alert_key_corrupted_msg">Privé sleutel lijkt corrupt!</string> - <string name="alert_sdcard_absent">SD kaart niet aanwezig!</string> - <string name="button_add">Voeg toe</string> - <string name="button_change">Verander</string> - <string name="button_generate">Genereer sleutel</string> - <string name="button_resize">Verander formaat</string> - <string name="alert_disconnect_msg">Verbinding verloren</string> - <string name="pref_emulation_category">Terminal emulatie</string> - <string name="pref_emulation_title">Emulatie mode</string> - <string name="pref_emulation_summary">Terminal emulatie mode voor gebruik in PTY verbindingen</string> - <string name="pref_scrollback_title">Scrollback grootte</string> - <string name="pref_scrollback_summary">Grootte van scrollback buffer om in geheugen te houden voor elke console</string> - <string name="pref_ui_category">Gebruikers interface</string> - <string name="pref_rotation_title">Rotatie mode</string> - <string name="pref_rotation_summary">Hoe rotatie te veranderen wanneer keyboard in/uit geschoven is</string> - <string name="pref_fullscreen_title">Volledig scherm</string> - <string name="pref_fullscreen_summary">Verberg status balk terwijl in console</string> - <string name="pref_memkeys_title">Onthoud sleutels in geheugen</string> - <string name="pref_memkeys_summary">Houd ontgrendelde sleutels in geheugen tot achtergrond service is gestopt</string> - <string name="pref_update_title">Update controle</string> - <string name="pref_update_summary">Stel de maximale frequentie in om te controleren voor ConnectBot updates</string> - <string name="pref_conn_persist_title">Behoud verbindingen</string> - <string name="pref_conn_persist_summary">Forceer dat de verbindingen actief blijven op de achtergrond</string> - <string name="pref_keymode_title">Folder snelkoppelingen</string> - <string name="pref_keymode_summary">Selecteer hoe Alt voor \'/\' en Shift voor Tab te gebruiken</string> - <string name="pref_camera_title">Camera snelkoppeling</string> - <string name="pref_camera_summary">Selecteer welke snelkoppeling te activeren wanneer camera knop is ingedrukt</string> - <string name="pref_keepalive_title">Houd scherm wakker</string> - <string name="pref_keepalive_summary">Voorkom scherm van uitgaan wanneer er gewerkt word in een console</string> - <string name="pref_wifilock_title">Houd Wi-Fi actief</string> - <string name="pref_wifilock_summary">Voorkom Wi-Fi van uitgaan wanneer er een sessie actief is</string> - <string name="pref_bumpyarrows_title">Hobbelige pijlen</string> - <string name="pref_bumpyarrows_summary">Tril als pijl knoppen worden gestuurd van trackball; handig voor langzame verbindingen</string> - <string name="pref_bell_category">Terminal bel</string> - <string name="pref_bell_title">Hoorbare bel</string> - <string name="pref_bell_volume_title">Bel volume</string> - <string name="pref_bell_vibrate_title">Tril bij bel</string> - <string name="pref_bell_notification_title">Achtergrond notificaties</string> - <string name="pref_bell_notification_summary">Stuur notificatie als terminal in de achtergrond een bel laat klinken.</string> - <string name="list_keymode_right">Gebruik rechter kant sleutels</string> - <string name="list_keymode_left">Gebruik linker kant sleutels</string> - <string name="list_keymode_none">Schakel uit</string> - <string name="list_pubkeyids_none">Gebruik sleutels niet</string> - <string name="list_pubkeyids_any">Gebruik een willekeurige ontgrendelde sleutel</string> - <string name="hostpref_nickname_title">Bijnaam</string> - <string name="hostpref_color_title">Kleur catogorie</string> - <string name="hostpref_fontsize_title">Lettergrootte</string> - <string name="hostpref_pubkeyid_title">Gebruik pubkey authenticatie</string> - <string name="hostpref_authagent_title">Gebruik SSH auth agent</string> - <string name="hostpref_postlogin_title">Na-login automatie</string> - <string name="hostpref_postlogin_summary">Commando\'s om uit te voeren op de remote server wanneer geauthenticeerd</string> - <string name="hostpref_compression_title">Compressie</string> - <string name="hostpref_compression_summary">Dit kan helpen bij langzame netwerken</string> - <string name="hostpref_wantsession_title">Start shell sessie</string> - <string name="hostpref_wantsession_summary">Schakel dit uit om alleen port forwards te gebruiken</string> - <string name="hostpref_stayconnected_title">Blijf verbonden</string> - <string name="hostpref_stayconnected_summary">Verbinding automatisch proberen te herstellen</string> - <string name="hostpref_delkey_title">Del-toets</string> - <string name="hostpref_delkey_summary">De toetscode als de DEL-knop in wordt gedrukt</string> - <string name="hostpref_encoding_title">Codering</string> - <string name="hostpref_encoding_summary">Tekencodering voor de host</string> - <string name="hostpref_connection_category">Verbindings instellingen</string> - <string name="hostpref_username_title">Gebruikersnaam</string> - <string name="hostpref_hostname_title">Host</string> - <string name="hostpref_port_title">Poort</string> - <string name="bind_never">Nooit verbonden</string> - <string name="bind_minutes">%1$s minuten geleden</string> - <string name="bind_hours">%1$s uren geleden</string> - <string name="bind_days">%1$s dagen geleden</string> - <string name="console_copy_done">%1$d bytes gekopieerd naar het klembord</string> - <string name="console_copy_start">Tik en sleep\nof gebruik directioneel pad\nom velden te selecteren omte kopiëren</string> - <string name="console_menu_close">Sluit</string> - <string name="console_menu_copy">Kopieer</string> - <string name="console_menu_paste">Plak</string> - <string name="console_menu_portforwards">Port Forwards</string> - <string name="console_menu_resize">Forceer grootte</string> - <string name="console_menu_urlscan">URK Scan</string> - <string name="button_yes">Ja</string> - <string name="button_no">Nee</string> - <string name="portforward_local">Lokaal</string> - <string name="portforward_remote">Op afstand</string> - <string name="portforward_dynamic">Dynamisch (SOCKS)</string> - <string name="portforward_pos">Maak port forward</string> - <string name="portforward_done">Succesvol port forward gemaakt</string> - <string name="portforward_problem">Probleem met het maken van een port forward, misschien gebruik je poort onder 1024 of is de poort al gebruikt?</string> - <string name="portforward_menu_add">Voeg port forward toe</string> - <string name="hint_userhost">gebruiker\@hostnaam</string> - <string name="list_format_error">Gebruik het formaat %1$s</string> - <string name="format_username">gebruiker</string> - <string name="format_hostname">hostnaam</string> - <string name="format_port">poort</string> - <string name="list_menu_pubkeys">Beheer Pubkeys</string> - <string name="list_menu_sortcolor">Sorteer op kleur</string> - <string name="list_menu_sortname">Sorteer op naam</string> - <string name="list_menu_settings">Instellingen</string> - <string name="list_host_disconnect">Verbreek verbinding</string> - <string name="list_host_edit">Bewerk host</string> - <string name="list_host_portforwards">Bewerk port forwards</string> - <string name="list_host_delete">Verwijder hosts</string> - <string name="list_host_empty">Gebruik het snel-verbindings vierkant\nonder om een host te verbinden.</string> - <string name="list_rotation_default">Standaard</string> - <string name="list_rotation_land">Forceer landschap</string> - <string name="list_rotation_port">Forceer portret</string> - <string name="list_rotation_auto">Automatisch</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A en dan Spatie</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Geen</string> - <string name="list_delkey_backspace">Backspace</string> - <string name="list_delkey_del">Verwijderen</string> - <string name="delete_message">Weet je zeker dat je \'%1$s\' wilt verwijderen?</string> - <string name="delete_pos">Ja, verwijder</string> - <string name="delete_neg">Annuleren</string> - <string name="wizard_agree">Ga akkoord</string> - <string name="wizard_next">Volgende</string> - <string name="wizard_back">Terug</string> - <string name="terminal_no_hosts_connected">Momenteel geen hosts verbonden</string> - <string name="terminal_connecting">Bezig met verbinden naar %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">Gecontroleerde host \'%1$s\' sleutel: %2$s</string> - <string name="terminal_failed">Host sleutel verificatie mislukt</string> - <string name="terminal_using_s2c_algorithm">Server-naar-cliënt algoritme: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Cliënt-naar-server algoritme: %1$s %2$s</string> - <string name="terminal_using_algorithm">Gebruikt algoritme: %1$s %2$s</string> - <string name="terminal_auth">Probeert te authenticeren</string> - <string name="terminal_auth_pass">Probeert \'wachtwoord\' authenticatie</string> - <string name="terminal_auth_pass_fail">Authenticatie methode \'wachtwoord\' mislukt</string> - <string name="terminal_auth_pubkey_any">Probeert \'publieke sleutel\' authenticatie met een willekeurige in-geheugen publieke sleutel</string> - <string name="terminal_auth_pubkey_invalid">Geselecteerde publieke sleutel is ongeldig, probeer herselecteren van de sleutel in de host bewerker</string> - <string name="terminal_auth_pubkey_specific">Probeert \'publickey\' authenticatie met een specifieke publieke sleutel</string> - <string name="terminal_auth_pubkey_fail">Authenticatie methode \'publickey\' met sleutel \'%1$s\' gefaald</string> - <string name="terminal_auth_ki">Probeert \'keyboard-interactive\' authenticatie</string> - <string name="terminal_auth_ki_fail">Authenticatie methode \'keyboard-interactive\' mislukt</string> - <string name="terminal_auth_fail">[Uw host ondersteund \'wachtwoord\' of \'keyboard-interactive\' authenticatie niet.]</string> - <string name="terminal_no_session">Sessie zal niet gestart worden door host instelling</string> - <string name="terminal_enable_portfoward">Activeer port forward: %1$s</string> - <string name="local_shell_unavailable">Mislukking! Lokale shell is niet beschikbaar op deze telefoon.</string> - <string name="notification_text">%1$s wil je aandacht.</string> - <string name="no">Nee</string> - <string name="with_confirmation">Met toestemming</string> - <string name="yes">Ja</string> - <string name="exceptions_submit_message">Het lijkt erop dat ConnectBot een probleem had de laatste keer dat het gebruikt werd. Wilt u een foutenrapport naar de ConnectBot ontwikkelaars sturen?</string> - <string name="menu_colors_reset">Terug naar standaardinstellingen</string> - <string name="app_is_running">ConnectBot werkt (Connecties zijn actief)</string> - <string name="color_red">rood</string> - <string name="color_green">groen</string> - <string name="color_blue">blauw</string> - <string name="color_gray">grijs</string> -</resources>
--- a/res/values-oc/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Un client SSH simple, open-source e poderós.</string> - <string name="title_hosts_list">Òstes</string> - <string name="title_pubkey_list">Claus publicas</string> - <string name="title_port_forwards_list">Redireccions de pòrts</string> - <string name="title_host_editor">Modificar lo servidor</string> - <string name="title_help">Ajuda</string> - <string name="resolve_connect">Connexion</string> - <string name="resolve_entropy">Generacion d\'aleatòri</string> - <string name="menu_insert">Apondre un servidor</string> - <string name="menu_delete">Supprimir lo servidor</string> - <string name="menu_preferences">Preferéncias</string> - <string name="help_intro">Seleccionatz un subjècte çaijós per mai d\'entresenhas.</string> - <string name="help_about">A prepaus de ConnectBot</string> - <string name="help_keyboard">Clavièr</string> - <string name="pubkey_generate">Generar</string> - <string name="pubkey_import">Importar</string> - <string name="pubkey_delete">Suprimir la clau</string> - <string name="pubkey_gather_entropy">Generacion d\'aleatòri</string> - <string name="pubkey_touch_prompt">Tocatz aquesta bóstia per recuperar un nombre aleatòri : %1$d%% fach</string> - <string name="pubkey_copy_private">Copiar la clau privada</string> - <string name="pubkey_copy_public">Copiar la clau publica</string> - <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> - <string name="pubkey_unknown_format">Format desconegut</string> - <string name="pubkey_change_password">Modificar lo senhal</string> - <string name="pubkey_list_pick">Recuperar dempuèi /sdcard</string> - <string name="pubkey_confirm_use">Confirmar abans utilizacion</string> - <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> - <string name="prompt_nickname">Escais :</string> - <string name="prompt_nickname_hint_pubkey">Ma clau de trabalh</string> - <string name="prompt_destination">Destinacion :</string> - <string name="prompt_old_password">Senhal ancian :</string> - <string name="prompt_password">Senhal :</string> - <string name="prompt_again">(encara)</string> - <string name="prompt_type">Tipe :</string> - <string name="prompt_bits">Bits :</string> - <string name="alert_wrong_password_msg">Marrit senhal</string> - <string name="button_add">Apondre</string> - <string name="button_change">Cambiar</string> - <string name="button_generate">Generar una clau</string> - <string name="button_resize">Redimensionar</string> - <string name="alert_disconnect_msg">Connexion perduda</string> - <string name="pref_ui_category">Interfàcia d\'utilizaire</string> - <string name="pref_fullscreen_title">Ecran complet</string> - <string name="pref_update_title">Verificar las mesas a jorn</string> - <string name="pref_conn_persist_title">Connexions persistentas</string> - <string name="pref_keymode_title">Acorchis de navigacion</string> - <string name="list_keymode_none">Desactivar</string> - <string name="hostpref_nickname_title">Escais</string> - <string name="hostpref_encoding_title">Encodatge</string> - <string name="hostpref_connection_category">Paramètre de connexion</string> - <string name="hostpref_username_title">Nom d\'utilizaire</string> - <string name="hostpref_hostname_title">Òste</string> - <string name="hostpref_port_title">Pòrt</string> - <string name="console_menu_close">Tampar</string> - <string name="console_menu_copy">Copiar</string> - <string name="console_menu_paste">Empegar</string> - <string name="button_yes">Òc</string> - <string name="button_no">Non</string> - <string name="portforward_remote">Distant</string> - <string name="portforward_dynamic">Dinamic (SOCKS)</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="format_username">nom d\'utilizaire</string> - <string name="format_hostname">nom d\'òste</string> - <string name="list_menu_sortname">Triar per nom</string> - <string name="list_menu_settings">Paramètres</string> - <string name="list_host_disconnect">Desconnectar</string> - <string name="list_rotation_default">Per defaut</string> - <string name="list_hwbutton_esc">Escap</string> - <string name="list_hwbutton_none">Pas cap</string> - <string name="list_delkey_backspace">Retorn enrèire</string> - <string name="list_delkey_del">Suprimir</string> - <string name="delete_neg">Anullar</string> - <string name="wizard_agree">Acceptar</string> - <string name="wizard_next">Seguent</string> - <string name="wizard_back">Precedent</string> - <string name="terminal_connecting">Connexion a %1$s:%2$d via %3$s</string> - <string name="no">Non</string> - <string name="with_confirmation">Aprèp confirmacion</string> - <string name="yes">Òc</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> - <string name="menu_colors_reset">Reïnicializar</string> - <string name="color_red">roge</string> - <string name="color_green">verd</string> - <string name="color_blue">blau</string> - <string name="color_gray">gris</string> -</resources>
--- a/res/values-pl/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Prosty, wszechstronny i otwarty klient SSH</string> - <string name="service_desc">Zarządza połączeniami SSH i załadowanymi kluczami publicznymi</string> - <string name="title_hosts_list">Hosty</string> - <string name="title_pubkey_list">Klucze publiczne</string> - <string name="title_port_forwards_list">Przekierowania portów</string> - <string name="title_host_editor">Edytuj host</string> - <string name="title_help">Pomoc</string> - <string name="title_colors">Kolory</string> - <string name="resolve_connect">Połącz</string> - <string name="resolve_entropy">Zbierz dane losowe</string> - <string name="menu_insert">Dodaj host</string> - <string name="menu_delete">Usuń host</string> - <string name="menu_preferences">Ustawienia</string> - <string name="help_intro">Proszę wybrać temat poniżej aby uzyskać więcej informacji na konkretny temat.</string> - <string name="help_about">O ConnectBot</string> - <string name="help_keyboard">Klawiatura</string> - <string name="pubkey_generate">Wygeneruj</string> - <string name="pubkey_import">Importuj</string> - <string name="pubkey_delete">Usuń klucz</string> - <string name="pubkey_gather_entropy">Zbieranie danych losowych</string> - <string name="pubkey_touch_prompt">Dotknij to pole, żeby losowo wygenerować dane. Ukończono: %1$d%%</string> - <string name="pubkey_touch_hint">Dla niepowtarzalności klucza, poruszaj losowo palcem po polu poniżej.</string> - <string name="pubkey_generating">"Generowanie pary kluczy…"</string> - <string name="pubkey_copy_private">Kopiuj klucz prywatny</string> - <string name="pubkey_copy_public">Kopiuj klucz publiczny</string> - <string name="pubkey_list_empty">Naciśnij \"Menu\", by utworzyć\nlub zaimportować parę kluczy.</string> - <string name="pubkey_unknown_format">Nieznany format</string> - <string name="pubkey_change_password">Zmień hasło</string> - <string name="pubkey_list_pick">Wybierz z karty SD</string> - <string name="pubkey_import_parse_problem">Niewłaściwy format importowanego klucza prywatnego</string> - <string name="pubkey_unlock">Odblokuj klucz</string> - <string name="pubkey_failed_add">Nieprawidłowe hasło dla klucza \'%1$s\'. Uwierzytelnienie nie powiodło się.</string> - <string name="pubkey_memory_load">Załaduj do pamięci</string> - <string name="pubkey_memory_unload">Usuń z pamięci</string> - <string name="pubkey_load_on_start">Załaduj klucz przy uruchamianiu</string> - <string name="pubkey_confirm_use">Potwierdź przed użyciem</string> - <string name="portforward_list_empty">Naciśnij \"Menu\",\nżeby stworzyć przekierowanie portu.</string> - <string name="portforward_edit">Edytuj przekierowanie portu</string> - <string name="portforward_delete">Usuń przekierowanie portu</string> - <string name="prompt_nickname">Skrócona nazwa:</string> - <string name="prompt_nickname_hint_pubkey">Klucz służbowy</string> - <string name="prompt_source_port">Port żródłowy</string> - <string name="prompt_destination">Host docelowy:</string> - <string name="prompt_old_password">Stare hasło:</string> - <string name="prompt_password">Hasło:</string> - <string name="prompt_again">(ponownie)</string> - <string name="prompt_type">Typ:</string> - <string name="prompt_password_can_be_blank">Uwaga: hasło może być puste</string> - <string name="prompt_bits">Bity:</string> - <string name="prompt_pubkey_password">Proszę podać hasło dla klucza \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Zezwolić zdalnemu hostowi na\nużycie klucza \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">OSTRZEŻENIE: DANE IDENTYFIKACYJNE ZDALNEGO HOSTU ZMIENIŁY SIĘ!</string> - <string name="host_verification_failure_warning">MOŻLIWE, ŻE STAŁEŚ SIĘ OFIARĄ ATAKU!\nPrawdopodobnie jest to atak: man-in-the-middle!\nJednak możliwe jest to, że zmienił się tylko klucz hostu.</string> - <string name="prompt_host_disconnected">Host rozłączył się.\nZamknąć sesję?</string> - <string name="prompt_continue_connecting">Czy na pewno chcesz\nkontynuować połączenie?</string> - <string name="host_authenticity_warning">Autentyczność hostu \'%1$s\' nie może zostać ustalona.</string> - <string name="host_fingerprint">Odcisk hostu %1$s to %2$s</string> - <string name="alert_passwords_do_not_match_msg">Hasła nie zgadzają się!</string> - <string name="alert_wrong_password_msg">Nieprawidłowe hasło!</string> - <string name="alert_key_corrupted_msg">Klucz prywatny wydaje się być uszkodzony!</string> - <string name="alert_sdcard_absent">Brak karty SD</string> - <string name="button_add">Dodaj</string> - <string name="button_change">Zmień</string> - <string name="button_generate">Generuj klucz</string> - <string name="button_resize">Zmień rozmiar</string> - <string name="alert_disconnect_msg">Połączenie utracone</string> - <string name="pref_emulation_category">Emulacja terminalu</string> - <string name="pref_emulation_title">Tryb emulacji</string> - <string name="pref_emulation_summary">Emulacja terminalu dla połączeń PTY</string> - <string name="pref_scrollback_title">Rozmiar buforu przewijania</string> - <string name="pref_scrollback_summary">Rozmiar pamięci dla buforu przewijania dla każdej konsoli</string> - <string name="pref_ui_category">Interfejs użytkownika</string> - <string name="pref_rotation_title">Sposób orientacji ekranu</string> - <string name="pref_rotation_summary">Sposób orientacji ekranu przy wysuniętej/wsuniętej klawiaturze</string> - <string name="pref_fullscreen_title">Pełny ekran</string> - <string name="pref_fullscreen_summary">Ukryj pasek statusu podczas pracy w konsoli</string> - <string name="pref_memkeys_title">Zapamiętaj klucze w pamięci</string> - <string name="pref_memkeys_summary">Trzymaj odblokowane klucze w pamięci dopóki usługa się nie rozłączy</string> - <string name="pref_update_title">Sprawdź aktualizacje</string> - <string name="pref_update_summary">Ustawienie częstości sprawdzania aktualizacji</string> - <string name="pref_conn_persist_title">Utrzymuj połącznia</string> - <string name="pref_conn_persist_summary">Wymuś utrzymanie połączeń, gdy aplikacja działa w tle</string> - <string name="pref_keymode_title">Skróty klawiaturowe</string> - <string name="pref_keymode_summary">Wybierz, którego Alt, Shift używać dla \'/\' oraz \'Tab\'</string> - <string name="pref_camera_title">Klawisz aparatu</string> - <string name="pref_camera_summary">Wybierz jaki skrót ma być wywoływany po wciśnięciu klawisza aparatu</string> - <string name="pref_keepalive_title">Wstrzymaj uśpienie ekranu</string> - <string name="pref_keepalive_summary">Wstrzymaj uśpienie ekranu kiedy konsola jest aktywna</string> - <string name="pref_wifilock_title">Wstrzymaj usypianie Wi-Fi</string> - <string name="pref_wifilock_summary">Wstrzymaj usypianie Wi-Fi gdy sesja jest aktywna</string> - <string name="pref_bumpyarrows_title">Podskakujące strzałki</string> - <string name="pref_bumpyarrows_summary">Wibruj kiedy emulowane są klawisze strzałek; użyteczne dla wolnych połączeń</string> - <string name="pref_bell_category">Brzęczyk terminalu</string> - <string name="pref_bell_title">Brzęczyk słyszalny</string> - <string name="pref_bell_volume_title">Głośność brzęczyka</string> - <string name="pref_bell_vibrate_title">Włącz wibracje</string> - <string name="pref_bell_notification_title">Powiadomienia w tle</string> - <string name="pref_bell_notification_summary">Uruchom powiadomienie podczas akcji w zminimalizowanej aplikacji.</string> - <string name="list_keymode_right">Używaj klawiszy z prawej strony</string> - <string name="list_keymode_left">Używaj klawiszy z lewej strony</string> - <string name="list_keymode_none">Wyłącz</string> - <string name="list_pubkeyids_none">Nie używaj kluczy</string> - <string name="list_pubkeyids_any">Użyj dowolnego odblokowanego klucza</string> - <string name="hostpref_nickname_title">Nazwa skrócona</string> - <string name="hostpref_color_title">Kolor kategorii</string> - <string name="hostpref_fontsize_title">Rozmiar czcionki</string> - <string name="hostpref_pubkeyid_title">Używaj kluczy publicznych do uwierzytelnienia</string> - <string name="hostpref_authagent_title">Używaj agenta SSH dla uwierzytelniania</string> - <string name="hostpref_postlogin_title">Wykonaj po zalogowaniu</string> - <string name="hostpref_postlogin_summary">Komendy do wykonania po stronie serwera po zalogowaniu</string> - <string name="hostpref_compression_title">Kompresja</string> - <string name="hostpref_compression_summary">Może pomóc przy wolniejszych łączach</string> - <string name="hostpref_wantsession_title">Uruchom sesję powłoki</string> - <string name="hostpref_wantsession_summary">Wyłącz jeśli chcesz tylko przekierować porty</string> - <string name="hostpref_stayconnected_title">Pozostań połączony</string> - <string name="hostpref_stayconnected_summary">Spróbuj połączyć się z hostem ponownie po przerwaniu połączenia</string> - <string name="hostpref_delkey_title">Klawisz DEL</string> - <string name="hostpref_delkey_summary">Kod klawisza wysyłany przy wciśnięciu DEL</string> - <string name="hostpref_encoding_title">Kodowanie</string> - <string name="hostpref_encoding_summary">Kodowanie znaków dla hostu</string> - <string name="hostpref_connection_category">Ustawienia połączenia</string> - <string name="hostpref_username_title">Nazwa użytkownika</string> - <string name="hostpref_hostname_title">Host</string> - <string name="hostpref_port_title">Port</string> - <string name="bind_never">Nigdy nie połączono</string> - <string name="bind_minutes">%1$s minut temu</string> - <string name="bind_hours">%1$s godzin temu</string> - <string name="bind_days">%1$s dni temu</string> - <string name="console_copy_done">Skopiowano %1$d bajtów do schowka</string> - <string name="console_copy_start">Dotknij i przeciągnij\nlub użyj trackball\'a\naby zaznaczyć obszar do skopiowania</string> - <string name="console_menu_close">Zamknij</string> - <string name="console_menu_copy">Kopiuj</string> - <string name="console_menu_paste">Wklej</string> - <string name="console_menu_portforwards">Przekierowania portów</string> - <string name="console_menu_resize">Wymuś rozmiar</string> - <string name="console_menu_urlscan">Szukaj URLi</string> - <string name="button_yes">Tak</string> - <string name="button_no">Nie</string> - <string name="portforward_local">Lokalny</string> - <string name="portforward_remote">Zdalny</string> - <string name="portforward_dynamic">Dynamiczny (SOCKS)</string> - <string name="portforward_pos">Utwórz przekierowanie portu</string> - <string name="portforward_done">Pomyślnie utworzono przekierowanie portu</string> - <string name="portforward_problem">Wystąpił problem podczas tworzenia przekierowania, być może użyłeś portu niższego niż 1024 lub port jest już używany?</string> - <string name="portforward_menu_add">Dodaj przekierowanie portu</string> - <string name="hint_userhost">użytkownik\@host</string> - <string name="list_format_error">Proszę użyć formatu %1$s</string> - <string name="format_username">Nazwa użytkownika</string> - <string name="format_hostname">nazwa_hostu</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Zarządzaj kluczami publicznymi</string> - <string name="list_menu_sortcolor">Sortuj według koloru</string> - <string name="list_menu_sortname">Sortuj według nazwy</string> - <string name="list_menu_settings">Ustawienia</string> - <string name="list_host_disconnect">Rozłącz</string> - <string name="list_host_edit">Edytuj host</string> - <string name="list_host_portforwards">Edytuj przekierowania portów</string> - <string name="list_host_delete">Usuń host</string> - <string name="list_host_empty">Użyj pola szybkiego połączenia\nponiżej, żeby połączyć się z hostem.</string> - <string name="list_rotation_default">Domyślne</string> - <string name="list_rotation_land">Wymuś orientację poziomą</string> - <string name="list_rotation_port">Wymuś orientację pionową</string> - <string name="list_rotation_auto">Automatycznie</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A następnie Spacja</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Brak akcji</string> - <string name="list_delkey_backspace">Backspace</string> - <string name="list_delkey_del">Usuń</string> - <string name="delete_message">Jesteś pewien, że chcesz usunąć \'%1$s\'?</string> - <string name="delete_pos">Tak, usuń</string> - <string name="delete_neg">Anuluj</string> - <string name="wizard_agree">Akceptuj</string> - <string name="wizard_next">Dalej</string> - <string name="wizard_back">Wróć</string> - <string name="terminal_no_hosts_connected">Żaden host nie jest obecnie połączony</string> - <string name="terminal_connecting">Łączenie z hostem %1$s:%2$d przez %3$s</string> - <string name="terminal_sucess">Host \'%1$s \' zweryfikowany kluczem: %2$s</string> - <string name="terminal_failed">Weryfikacja klucza dla hostu nie powiodła się.</string> - <string name="terminal_using_s2c_algorithm">Algorytm serwer-klient: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algorytm klient-serwer: %1$s %2$s</string> - <string name="terminal_using_algorithm">Użyty algorytm: %1$s %2$s</string> - <string name="terminal_auth">Próba uwierzytelnienia</string> - <string name="terminal_auth_pass">Próba uwierzytelnienia za pomocą hasła</string> - <string name="terminal_auth_pass_fail">Uwierzytelnienie hasłem nie powiodło się</string> - <string name="terminal_auth_pubkey_any">Próba uwierzytelnienia za pomocą dowolnego zapamiętanego klucza publicznego</string> - <string name="terminal_auth_pubkey_invalid">Wybrany klucz publiczny jest nieprawidłowy, spróbuj wybrać inny w ustawieniach hostu</string> - <string name="terminal_auth_pubkey_specific">"Próba uwierzytelnienia za pomocą wybranego klucza publicznego"</string> - <string name="terminal_auth_pubkey_fail">Uwierzytelnienie metodą klucza publicznego z kluczem \'%1$s\' nie powiodło się</string> - <string name="terminal_auth_ki">Próba uwierzytelnienia za pomocą klawiatury</string> - <string name="terminal_auth_ki_fail">Uwierzytelnienie za pomocą klawiatury nie powiodło się</string> - <string name="terminal_auth_fail">[Twój host nie obsługuje uwierzytelnienia za pomocą klawiatury lub hasła]</string> - <string name="terminal_no_session">Sesja nie zostanie rozpoczęta z powodu ustawień hostu</string> - <string name="terminal_enable_portfoward">Włącz przekierowanie portu: %1$s</string> - <string name="local_shell_unavailable">Niepowodzenie! Lokalna powłoka nie jest obsługiwana na tym telefonie.</string> - <string name="notification_text">%1$s wymaga reakcji</string> - <string name="no">Nie</string> - <string name="with_confirmation">Z potwierdzeniem</string> - <string name="yes">Tak</string> - <string name="exceptions_submit_message">ConnectBot miał prawdopodobnie problem podczas ostatniego uruchomienia. Wysłać raport o błędzie?</string> - <string name="menu_colors_reset">Przywróć</string> - <string name="app_is_running">ConnectBot jest uruchomiony</string> - <string name="color_red">czerwony</string> - <string name="color_green">zielony</string> - <string name="color_blue">niebieski</string> - <string name="color_gray">szary</string> - <string name="colors_fg">FG:</string> - <string name="color_bg">BG:</string> - <string name="image_description_connected">Połączono</string> - <string name="image_description_key_is_locked">Klucz zablokowany</string> - <string name="image_description_toggle_control_character">Przełącz znak kontrolny</string> - <string name="image_description_send_escape_character">Wyślij znak ESC</string> - <string name="image_description_show_keyboard">Pokarz klawiaturę</string> -</resources>
--- a/res/values-pt-rBR/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,216 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Cliente SSH simples e poderoso de código aberto</string> - <string name="service_desc">Mantém conexões SSH e de Chaves Públicas</string> - <string name="title_hosts_list">Hosts</string> - <string name="title_pubkey_list">Chaves Públicas</string> - <string name="title_port_forwards_list">Redirecionamento de Portas</string> - <string name="title_host_editor">Edição de Host</string> - <string name="title_help">Ajuda</string> - <string name="title_colors">Cores</string> - <string name="resolve_connect">Conectar</string> - <string name="resolve_entropy">Sensibilidade</string> - <string name="menu_insert">Adicionar Host</string> - <string name="menu_delete">Apagar host</string> - <string name="menu_preferences">Preferências</string> - <string name="help_intro">Escolha um dos tópicos abaixo para maiores informações</string> - <string name="help_about">Sobre o ConnectBot</string> - <string name="help_keyboard">Teclado</string> - <string name="pubkey_generate">Gerar</string> - <string name="pubkey_import">Importar</string> - <string name="pubkey_delete">Apagar chave</string> - <string name="pubkey_gather_entropy">Ajustando sensibilidade</string> - <string name="pubkey_touch_prompt">Toque na caixa para testar sensibilidade: %1$d%% pronto</string> - <string name="pubkey_touch_hint">Para garantir aleatoriedade durante a geração da chave, mova seu dedo aleatoriamente na caixa abaixo.</string> - <string name="pubkey_generating">""Gerando par de chaves…"</string> - <string name="pubkey_copy_private">Copiar chave privada</string> - <string name="pubkey_copy_public">Copiar chave pública</string> - <string name="pubkey_list_empty">Pressione Menu para criar ou importar pares de chaves.</string> - <string name="pubkey_unknown_format">Formato desconhecido</string> - <string name="pubkey_change_password">Mudar senha</string> - <string name="pubkey_list_pick">Escolher do /sdcard</string> - <string name="pubkey_import_parse_problem">Erro na leitura da chave privada importada</string> - <string name="pubkey_unlock">Abrir chave</string> - <string name="pubkey_failed_add">Senha inválida para Chave \'%1$s\'.Falha na autenticação.</string> - <string name="pubkey_memory_load">Carregar na memória</string> - <string name="pubkey_memory_unload">Descarregar da memória</string> - <string name="pubkey_load_on_start">Carregar chave ao iniciar</string> - <string name="pubkey_confirm_use">Confirmar antes de usar</string> - <string name="portforward_list_empty">Pressione Menu para criar encaminhamentos de porta.</string> - <string name="portforward_edit">Editar encaminhamento de porta</string> - <string name="portforward_delete">Apagar encaminhamento de porta</string> - <string name="prompt_nickname">Apelido:</string> - <string name="prompt_nickname_hint_pubkey">Minha chave de trabalho</string> - <string name="prompt_source_port">Porta de origem:</string> - <string name="prompt_destination">Destino:</string> - <string name="prompt_old_password">Senha antiga:</string> - <string name="prompt_password">Senha:</string> - <string name="prompt_again">(novamente)</string> - <string name="prompt_type">Tipo:</string> - <string name="prompt_password_can_be_blank">Nota: a senha pode ser em branco</string> - <string name="prompt_bits">Bits:</string> - <string name="prompt_pubkey_password">Senha para chave %1$s</string> - <string name="prompt_allow_agent_to_use_key">Permitir que a máquina remota use a chave %1$s?</string> - <string name="host_verification_failure_warning_header">ATENÇÃO: A IDENTIFICAÇÃO DO HOST REMOTO FOI ALTERADA!</string> - <string name="host_verification_failure_warning">É POSSÍVEL QUE ALGUÉM ESTEJA QUERENDO TE ENGANAR!\nAlguém pode estar tentando um ataque do tipo man-in-the-middle!\nTambém é possível que a chave do host remoto tenha mesmo sido modificada.</string> - <string name="prompt_host_disconnected">Host desconectado.\nFechar sessão?</string> - <string name="prompt_continue_connecting">Você tem certeza que\ndeseja se conectar?</string> - <string name="host_authenticity_warning">A autenticidade do Host \'%1$s\' não pode ser estabelecida</string> - <string name="host_fingerprint">O host %1$s tem a impressão digital %2$s</string> - <string name="alert_passwords_do_not_match_msg">As senhas são diferentes!</string> - <string name="alert_wrong_password_msg">Senha incorreta!</string> - <string name="alert_key_corrupted_msg">A chave privada parece estar corrompida!</string> - <string name="alert_sdcard_absent">O cartão SD não está inserido!</string> - <string name="button_add">Adicionar</string> - <string name="button_change">Alterar</string> - <string name="button_generate">Gerar chave</string> - <string name="button_resize">Redimensionar</string> - <string name="alert_disconnect_msg">Conexão perdida</string> - <string name="pref_emulation_category">Emulação de Terminal</string> - <string name="pref_emulation_title">Modo de emulação</string> - <string name="pref_emulation_summary">Modo de emulação do terminal com conexões PTY</string> - <string name="pref_scrollback_title">Tamanho do buffer da tela</string> - <string name="pref_scrollback_summary">Tamanho do buffer de memória a manter para cada terminal</string> - <string name="pref_ui_category">Interface do usuário</string> - <string name="pref_rotation_title">Rotação da tela</string> - <string name="pref_rotation_summary">Como alterar a rotação da tela quando se conecta/desconecta um teclado</string> - <string name="pref_fullscreen_title">Tela cheia</string> - <string name="pref_fullscreen_summary">Ocultar a barra de estatus no modo terminal</string> - <string name="pref_memkeys_title">Guardar as chaves em memória</string> - <string name="pref_memkeys_summary">Manter chaves desbloqueadas na memória até que o serviço seja terminado</string> - <string name="pref_update_title">Procurar por atualizações</string> - <string name="pref_update_summary">Configurar frequencia para checar atualizações do ConnectBot</string> - <string name="pref_conn_persist_title">Conexões persistentes</string> - <string name="pref_conn_persist_summary">Forçar as conexões para que continuem conectadas mesmo em segundo plano</string> - <string name="pref_keymode_title">Teclas de atalho</string> - <string name="pref_keymode_summary">Selecione para usar Alt para \'/\' e Shift para Tab</string> - <string name="pref_camera_title">Atalho para a câmera</string> - <string name="pref_camera_summary">Selecione o que fazer quando o botão da câmera for pressionado</string> - <string name="pref_keepalive_title">Manter tela ligada</string> - <string name="pref_keepalive_summary">Evitar desligamento de tela quando conectado em um terminal</string> - <string name="pref_wifilock_title">Manter a rede Wi-Fi ativo</string> - <string name="pref_wifilock_summary">Evitar que a rede Wi-Fi seja desligada quando alguma sesão está ativa</string> - <string name="pref_bumpyarrows_title">Feedback de rolagem</string> - <string name="pref_bumpyarrows_summary">Vibrar quando pressionar o botão principal (trackball)</string> - <string name="pref_bell_category">Alerta do terminal</string> - <string name="pref_bell_title">Alerta audível</string> - <string name="pref_bell_volume_title">Volume dos alerta</string> - <string name="pref_bell_vibrate_title">Vibrar ao alertar</string> - <string name="pref_bell_notification_title">Enviar notificações visuais quando em segundo plano</string> - <string name="pref_bell_notification_summary">Enviar notificações sonoras quando em segundo plano</string> - <string name="list_keymode_right">Usar atalhos especiais da direita</string> - <string name="list_keymode_left">Usar atalhos especiais da esquerda</string> - <string name="list_keymode_none">Desabilitar</string> - <string name="list_pubkeyids_none">Não usar chaves</string> - <string name="list_pubkeyids_any">Usar qualquer chave pública</string> - <string name="hostpref_nickname_title">Apelido</string> - <string name="hostpref_color_title">Categoria de cor</string> - <string name="hostpref_fontsize_title">Tamanho da fonte (pontos)</string> - <string name="hostpref_pubkeyid_title">Usar autenticação por chave púbilca</string> - <string name="hostpref_authagent_title">Usar agente de autenticação SSH</string> - <string name="hostpref_postlogin_title">Automação pós-login</string> - <string name="hostpref_postlogin_summary">Comandos a serem executados no servidor remoto na autenticação</string> - <string name="hostpref_compression_title">Compressão</string> - <string name="hostpref_compression_summary">Útil em conexões lentas (2G)</string> - <string name="hostpref_wantsession_title">Iniciar sessão de terminal na conexão</string> - <string name="hostpref_wantsession_summary">Desabilite esta preferência para usar apenas encaminhamento de portas</string> - <string name="hostpref_stayconnected_title">Manter conectado</string> - <string name="hostpref_stayconnected_summary">Tentar reconectar ao host caso a conexão seja perdida</string> - <string name="hostpref_delkey_title">Tecla DEL</string> - <string name="hostpref_delkey_summary">Código a ser enviado quando a tecla DEL for pressionada</string> - <string name="hostpref_encoding_title">Codificação</string> - <string name="hostpref_encoding_summary">Codificação de caracteres para o host</string> - <string name="hostpref_connection_category">Configurações de conexão</string> - <string name="hostpref_username_title">Usuário</string> - <string name="hostpref_hostname_title">Anfitrião (host)</string> - <string name="hostpref_port_title">Porta</string> - <string name="bind_never">Nunca usado</string> - <string name="bind_minutes">%1$s minutos atrás</string> - <string name="bind_hours">%1$s horas atrás</string> - <string name="bind_days">%1$s dias atrás</string> - <string name="console_copy_done">%1$d bytes copiados para a área de tranferência</string> - <string name="console_copy_start">Toque e arraste\nou use o trackball\npara selecionar uma área para copiar</string> - <string name="console_menu_close">Fechar</string> - <string name="console_menu_copy">Copiar</string> - <string name="console_menu_paste">Colar</string> - <string name="console_menu_portforwards">Encaminhamento de portas</string> - <string name="console_menu_resize">Forçar tamanho</string> - <string name="console_menu_urlscan">Localizar URLs</string> - <string name="button_yes">Sim</string> - <string name="button_no">Não</string> - <string name="portforward_local">Porta local</string> - <string name="portforward_remote">Remoto</string> - <string name="portforward_dynamic">Dinâmico (SOCKS)</string> - <string name="portforward_pos">Criar encaminhamento de porta</string> - <string name="portforward_done">Encaminhamento de porta criado com sucesso</string> - <string name="portforward_problem">Problema na criação do redirecionamento de portas, talvez você esteja usando portas menores que 1024 ou a porta já esteja sendo usada.</string> - <string name="portforward_menu_add">Adicionar encaminhamento de porta</string> - <string name="hint_userhost">usuario\@nome_do_host</string> - <string name="list_format_error">Use o formato %1$s</string> - <string name="format_username">usuário</string> - <string name="format_hostname">nome do host</string> - <string name="format_port">porta</string> - <string name="list_menu_pubkeys">Gerenciar chaves públicas</string> - <string name="list_menu_sortcolor">Ordenar por cor</string> - <string name="list_menu_sortname">Ordenar por nome</string> - <string name="list_menu_settings">Configurações</string> - <string name="list_host_disconnect">Desconectar</string> - <string name="list_host_edit">Editar host</string> - <string name="list_host_portforwards">Editar encaminhamento de porta</string> - <string name="list_host_delete">Apagar host</string> - <string name="list_host_empty">Use a conexão rápida abaixo\npara conectar a um host.</string> - <string name="list_rotation_default">Padrão</string> - <string name="list_rotation_land">Forçar modo paisagem</string> - <string name="list_rotation_port">Forçar modo retrato</string> - <string name="list_rotation_auto">Automático</string> - <string name="list_hwbutton_ctrlaspace">Ctrl + A + Espaço</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Nada</string> - <string name="list_delkey_backspace">Tecla Backspace</string> - <string name="list_delkey_del">Apagar</string> - <string name="delete_message">Certeza que quer deletar \'%1$s\' ?</string> - <string name="delete_pos">Sim, apagar</string> - <string name="delete_neg">Cancelar</string> - <string name="wizard_agree">Aceito</string> - <string name="wizard_next">Próximo</string> - <string name="wizard_back">Voltar</string> - <string name="terminal_no_hosts_connected">Sem host conectado atualmente</string> - <string name="terminal_connecting">Conectando no %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">"Anfitrião comprovado \'%1$s\' chave: %2$s"</string> - <string name="terminal_failed">Falha na verificação da chave do host</string> - <string name="terminal_using_s2c_algorithm">Algoritmo do servidor para o cliente: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algoritmo do cliente para o servidor: %1$s %2$s</string> - <string name="terminal_using_algorithm">Usando o algoritmo: %1$s %2$s</string> - <string name="terminal_auth">Tentando autenticação</string> - <string name="terminal_auth_pass">Tentativa de autenticação de \'senha\' em andamento</string> - <string name="terminal_auth_pass_fail">Método de autenticação por \'senha\' falhou</string> - <string name="terminal_auth_pubkey_any">Tentando autenticação \'chave pública\' com qualquer chave pública na memória</string> - <string name="terminal_auth_pubkey_invalid">A chave pública selecionada é inválida, tente selecionar outra no editor de hosts</string> - <string name="terminal_auth_pubkey_specific">Tentando autenticação \'chave pública\' com uma chave pública específica</string> - <string name="terminal_auth_pubkey_fail">Metodo de autenticação \'publickey\' com a chave \'%1$s\' falhou</string> - <string name="terminal_auth_ki">Tentando autenticação \'teclado-interativo\'</string> - <string name="terminal_auth_ki_fail">Metodo de autenticação \'interativa por teclado\' falhou</string> - <string name="terminal_auth_fail">[Seu host não suporta autenticação por \'senha\' ou \'interativa por teclado\'.</string> - <string name="terminal_no_session">A sessão não será iniciada devido à configurações do host.</string> - <string name="terminal_enable_portfoward">Habilitar encaminhamento de porta: %1$s</string> - <string name="local_shell_unavailable">Erro! O terminal local não está disponível neste telefone.</string> - <string name="notification_text">%1$s deseja sua atenção.</string> - <string name="no">Não</string> - <string name="with_confirmation">Com confirmação</string> - <string name="yes">Sim</string> - <string name="exceptions_submit_message">Aparentemente o ConnectBot teve um problema na última execução. Deseja enviar relatório de erro aos desenvolvedores do aplicativo?</string> - <string name="menu_colors_reset">Reiniciar</string> - <string name="app_is_running">ConnectBot está executando</string> - <string name="color_red">vermelho</string> - <string name="color_green">verde</string> - <string name="color_blue">azul</string> - <string name="color_gray">cinza</string> - <string name="colors_fg">PP:</string> - <string name="color_bg">SP:</string> - <string name="image_description_connected">Conectado.</string> - <string name="image_description_key_is_locked">A chave está bloqueada.</string> - <string name="image_description_send_escape_character">Enviar caractere de escape.</string> - <string name="image_description_show_keyboard">Exibir teclado</string> -</resources>
--- a/res/values-pt/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Simples e poderoso cliente SSH open-source</string> - <string name="service_desc">Manter ligações SSH e chaves públicas carregadas</string> - <string name="title_hosts_list">Máquinas</string> - <string name="title_pubkey_list">Chaves Públicas</string> - <string name="title_port_forwards_list">Redireciomento de portas</string> - <string name="title_host_editor">Editar a Máquina</string> - <string name="title_help">Ajuda</string> - <string name="title_colors">Cores</string> - <string name="resolve_connect">Ligar</string> - <string name="resolve_entropy">Gerar Entropia</string> - <string name="menu_insert">Adicionar uma Máquina</string> - <string name="menu_delete">Eliminar anfitrião</string> - <string name="menu_preferences">Preferências</string> - <string name="help_intro">Selecione um tópico para mais informações sobre o assunto.</string> - <string name="help_about">Sobre ConnectBot</string> - <string name="help_keyboard">Teclado</string> - <string name="pubkey_generate">Gerar</string> - <string name="pubkey_import">Importar</string> - <string name="pubkey_delete">Apagar a chave</string> - <string name="pubkey_gather_entropy">Recolhendo entropia</string> - <string name="pubkey_touch_prompt">Toque nesta caixa para gerar aleariedade: %1$d%% completo</string> - <string name="pubkey_touch_hint">Para assegurar aleatoriedade durante a geração da chave, mova o dedo aleatoriamente sobre a caixa a baixo.</string> - <string name="pubkey_generating">A gerar par de chaves</string> - <string name="pubkey_copy_private">Copiar chave privada</string> - <string name="pubkey_copy_public">Copiar chave pública</string> - <string name="pubkey_list_empty">Carregue em Menu para criar\nou importar as chaves.</string> - <string name="pubkey_unknown_format">Formato desconhecido</string> - <string name="pubkey_change_password">Alterar password</string> - <string name="pubkey_list_pick">Escolher de /sdcard</string> - <string name="pubkey_import_parse_problem">Problema de análise com a chave privada importada</string> - <string name="pubkey_unlock">Desbloquear chave</string> - <string name="pubkey_failed_add">Password inválida para a chave \'%1$s\'. Erro na autenticação.</string> - <string name="pubkey_memory_load">Carregar para a memória</string> - <string name="pubkey_memory_unload">retirar da memória</string> - <string name="pubkey_load_on_start">carregar chave no Inicio</string> - <string name="pubkey_confirm_use">Confirmar antes de usar</string> - <string name="portforward_list_empty">Carregue Menu para criar\nport forward</string> - <string name="portforward_edit">Editar port forward</string> - <string name="portforward_delete">Apagar port forward</string> - <string name="prompt_nickname">Alcunha:</string> - <string name="prompt_nickname_hint_pubkey">A minha chave de trabalho</string> - <string name="prompt_source_port">Porta de origem:</string> - <string name="prompt_destination">Destino:</string> - <string name="prompt_old_password">Palavra-passe Antiga:</string> - <string name="prompt_password">Palavra-passe:</string> - <string name="prompt_again">(novamente)</string> - <string name="prompt_type">Tipo:</string> - <string name="prompt_password_can_be_blank">Nota: password pode ser em branco</string> - <string name="prompt_bits">bits:</string> - <string name="prompt_pubkey_password">Password para a chave \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Permitir ao anfitrião remoto\nusar a chave \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">AVISO: a identificação do anfitrião remoto mudou!</string> - <string name="host_verification_failure_warning">É POSSÍVEL QUE ALGUÉM ESTEJA A FAZER ALGO ERRADO!\n Alguém pode estar espiando ( ataque man-in-the-middle)!\nTambém e possível que a chave do hospede tenha sido alterada</string> - <string name="prompt_host_disconnected">Hospede desconectou-se.\nFechar sessão?</string> - <string name="prompt_continue_connecting">Tem a certeza que quer\ncontinuar a connectar?</string> - <string name="host_authenticity_warning">A autenticidade do anfitrião \'%1$s\' não pode ser verificada.</string> - <string name="host_fingerprint">Hospede %1$s id da chave é %2$s</string> - <string name="alert_passwords_do_not_match_msg">As palavras passe não coincidem!</string> - <string name="alert_wrong_password_msg">Palavra passe errada!</string> - <string name="alert_key_corrupted_msg">Chave privada parece estar corrupta.</string> - <string name="alert_sdcard_absent">Cartão SD não parece estar inserido!</string> - <string name="button_add">Adicionar</string> - <string name="button_change">Alterar</string> - <string name="button_generate">Gerar Chave</string> - <string name="button_resize">Redimensionar</string> - <string name="alert_disconnect_msg">Ligação Perdida</string> - <string name="pref_emulation_category">Terminal de emulação</string> - <string name="pref_emulation_title">Modo de emulação</string> - <string name="pref_emulation_summary">Terminal de emulação para usar conecções PTY</string> - <string name="pref_scrollback_title">Tamanho de Scrollback</string> - <string name="pref_scrollback_summary">Tamanho do buffer de scrollback em memória para cada consola</string> - <string name="pref_ui_category">Interface de utilizador</string> - <string name="pref_rotation_title">Modo de rotação</string> - <string name="pref_rotation_summary">Como alterar a rotação quando o teclado é aberto/fechado</string> - <string name="pref_fullscreen_title">Ecrã completo</string> - <string name="pref_fullscreen_summary">Esconder a barra de notificação quando estiver na consola</string> - <string name="pref_memkeys_title">Lembrar chaves em memoria</string> - <string name="pref_memkeys_summary">Manter chaves desbloqueadas em memória até ao serviço de fundo terminar</string> - <string name="pref_update_title">Verificar actualizações</string> - <string name="pref_update_summary">Definir a frequência máxima para verificar actualizações do ConnectBot</string> - <string name="pref_conn_persist_title">Persistir ligações</string> - <string name="pref_conn_persist_summary">Forçar ligações a ficarem ligadas quando em segundo plano</string> - <string name="pref_keymode_title">Atalhos de directoria</string> - <string name="pref_keymode_summary">Escolher como usar Alt para \'/\' e Shift para Tab</string> - <string name="pref_camera_title">Atalho para a camera</string> - <string name="pref_camera_summary">Escolha o atalho a activar quando o botão da camara é pressionado</string> - <string name="pref_keepalive_title">Mantar ecrã activo</string> - <string name="pref_keepalive_summary">Previne que o ecrã seja desligado quando se esta a utilizar a consola</string> - <string name="pref_wifilock_title">Manter Wi-Fi activo</string> - <string name="pref_wifilock_summary">Evitar que o Wi-Fi desligue quando uma sessão está activa</string> - <string name="pref_bumpyarrows_title">Cursores com vibração</string> - <string name="pref_bumpyarrows_summary">Vibrar quando enviar teclas de cursor com a trackball; útil para ligações com atraso</string> - <string name="pref_bell_category">Aviso sonoro do terminal</string> - <string name="pref_bell_title">Aviso sonoro audível</string> - <string name="pref_bell_volume_title">Volume do aviso sonoro</string> - <string name="pref_bell_vibrate_title">Vibrar em aviso sonoro</string> - <string name="pref_bell_notification_title">Notificações em segundo plano</string> - <string name="pref_bell_notification_summary">Enviar notificação quando um terminal a correr em segundo plano enviar um aviso sonoro.</string> - <string name="list_keymode_right">Usar teclas do lado direito</string> - <string name="list_keymode_left">Usar teclas do lado esquerdo</string> - <string name="list_keymode_none">Desactivar</string> - <string name="list_pubkeyids_none">Não usar teclas</string> - <string name="list_pubkeyids_any">Usar qualquer tecla não bloqueada</string> - <string name="hostpref_nickname_title">Alcunha</string> - <string name="hostpref_color_title">Categoria de cor</string> - <string name="hostpref_fontsize_title">Tamanho da fonte (pt)</string> - <string name="hostpref_pubkeyid_title">Utilizar autenticação de chave publica (pubkey)</string> - <string name="hostpref_authagent_title">Usar agente de autenticação SSH</string> - <string name="hostpref_postlogin_title">Automação pós-login</string> - <string name="hostpref_postlogin_summary">Comandos a correr no servidor remoto após autenticar</string> - <string name="hostpref_compression_title">Compressão</string> - <string name="hostpref_compression_summary">Isto pode ajudar em redes mais lentas</string> - <string name="hostpref_wantsession_title">Iniciar sessão de shell</string> - <string name="hostpref_wantsession_summary">Desactivar esta preferência para usar apenas redirecionamento de portas</string> - <string name="hostpref_stayconnected_title">Permanecer ligado</string> - <string name="hostpref_stayconnected_summary">Tentar ligar de novo ao anfitrião se desligar</string> - <string name="hostpref_delkey_title">Tecla DEL</string> - <string name="hostpref_delkey_summary">O código de tecla a enviar quando a tecla DEL é pressionada</string> - <string name="hostpref_encoding_title">Codificação</string> - <string name="hostpref_encoding_summary">Codificação de caractéres para o anfitrião</string> - <string name="hostpref_connection_category">Configuração da Ligação</string> - <string name="hostpref_username_title">Nome do Utilizador</string> - <string name="hostpref_hostname_title">Anfitrião</string> - <string name="hostpref_port_title">Porto</string> - <string name="bind_never">Nunca ligado</string> - <string name="bind_minutes">%1$s minutos atrás</string> - <string name="bind_hours">%1$s horas atrás</string> - <string name="bind_days">%1$s dias atrás</string> - <string name="console_copy_done">Copiados %1$d bytes para a área de transferência</string> - <string name="console_copy_start">Toque e arraste\nou use as teclas direcionais\npara selecionar a área a copiar</string> - <string name="console_menu_close">Fechar</string> - <string name="console_menu_copy">Copiar</string> - <string name="console_menu_paste">Colar</string> - <string name="console_menu_portforwards">Redirecionamento de portas</string> - <string name="console_menu_resize">Forçar Tamanho</string> - <string name="console_menu_urlscan">Detecção de URL</string> - <string name="button_yes">Sim</string> - <string name="button_no">Não</string> - <string name="portforward_local">Local</string> - <string name="portforward_remote">Remoto</string> - <string name="portforward_dynamic">Dinamico (SOCKS)</string> - <string name="portforward_pos">Criar redirecionamento de portas</string> - <string name="portforward_done">Redirecionamento de porta criado com sucesso</string> - <string name="portforward_problem">Problema ao criar redirecionamento de porta, talvez esteja a usar portas abaixo de 1024 ou a porta já esteja em uso?</string> - <string name="portforward_menu_add">Adicionar redirecionamento de porta</string> - <string name="hint_userhost">utilizador\@servidor</string> - <string name="list_format_error">Use o formato %1$s</string> - <string name="format_username">nome do utilizador</string> - <string name="format_hostname">endereço</string> - <string name="format_port">porto</string> - <string name="list_menu_pubkeys">Gerir Chaves Públicas</string> - <string name="list_menu_sortcolor">Ordenar por cor</string> - <string name="list_menu_sortname">Ordenar por nome</string> - <string name="list_menu_settings">Definições</string> - <string name="list_host_disconnect">Desconectar</string> - <string name="list_host_edit">Editar anfitrião</string> - <string name="list_host_portforwards">Editar redirecionamento de portas</string> - <string name="list_host_delete">Eliminar anfitrião</string> - <string name="list_host_empty">Usar a caixa de ligação rápida\nabaixo para ligar a um anfitrião.</string> - <string name="list_rotation_default">Padrão</string> - <string name="list_rotation_land">Forçar panoramico</string> - <string name="list_rotation_port">Forçar retrato</string> - <string name="list_rotation_auto">Automática</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A seguido de Espaço</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Nenhum</string> - <string name="list_delkey_backspace">Retrocesso</string> - <string name="list_delkey_del">Apagar</string> - <string name="delete_message">Tem a certeza que deseja eliminar \'%1$s\'?</string> - <string name="delete_pos">Sim, apagar</string> - <string name="delete_neg">Cancelar</string> - <string name="wizard_agree">Aceitar</string> - <string name="wizard_next">Seguinte</string> - <string name="wizard_back">Retroceder</string> - <string name="terminal_no_hosts_connected">Nenhum anfitrião ligado actualmente</string> - <string name="terminal_connecting">A ligar a %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">Verificado anfitrião \'%1$s\' chave: %2$s</string> - <string name="terminal_failed">Verificação da chave do anfitrião falhou.</string> - <string name="terminal_using_s2c_algorithm">Algoritmo servidor-cliente: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Algoritmo cliente-servidor: %1$s %2$s</string> - <string name="terminal_using_algorithm">A usar algoritmo %1$s %2$s</string> - <string name="terminal_auth">A tentar autenticação</string> - <string name="terminal_auth_pass">A tentar autenticação por \'password\'</string> - <string name="terminal_auth_pass_fail">Autenticação pelo método \'password\' falhou</string> - <string name="terminal_auth_pubkey_any">A tentar autenticação de chave pública (pubkey) com todas as chaves públicas em memória</string> - <string name="terminal_auth_pubkey_invalid">A chave pública escolhida é inválida, tente escolher outra chave no editor de anfitriões</string> - <string name="terminal_auth_pubkey_specific">A tentar autenticação de chave pública (publickey) com uma chave pública específica</string> - <string name="terminal_auth_pubkey_fail">Autenticação pelo método de chave pública (publickey) com a chave \'%1$s\' falhou</string> - <string name="terminal_auth_ki">A tentar autenticação pelo método \'teclado-interactivo\'</string> - <string name="terminal_auth_ki_fail">Autenticação pelo método \'teclado-interactivo\' falhou</string> - <string name="terminal_auth_fail">[O seu anfitrião não suporta autenticação por \'password\' ou \'teclado-interactivo\'.]</string> - <string name="terminal_no_session">A sessão não será iniciada devido a preferência do anfitrião.</string> - <string name="terminal_enable_portfoward">Permitir redirecionamento de porta: %1$s</string> - <string name="local_shell_unavailable">Falha! Shell local não está disponível neste telemóvel.</string> - <string name="notification_text">%1$s requer a sua atenção.</string> - <string name="no">Não</string> - <string name="with_confirmation">com confirmação</string> - <string name="yes">Sim</string> - <string name="exceptions_submit_message">Aparentemente o ConnectBot teve um problema na ultima vez que foi executado. Enviar relatório de erros para os programadores do ConnectBot?</string> - <string name="menu_colors_reset">Limpar</string> - <string name="app_is_running">O ConnectBot esta a ser executado</string> - <string name="color_red">vermelho</string> - <string name="color_green">verde</string> - <string name="color_blue">azul</string> - <string name="color_gray">cinzento</string> -</resources>
--- a/res/values-ro/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Un client SSH simplu, flexibil, open-source</string> - <string name="service_desc">Managementul conexiunilor si al cheilor publice</string> - <string name="title_hosts_list">Gazde</string> - <string name="title_pubkey_list">Chei publice</string> - <string name="title_port_forwards_list">Redirectări trafic</string> - <string name="title_host_editor">Editare gazdă</string> - <string name="title_help">Ajutor</string> - <string name="title_colors">Culori</string> - <string name="resolve_connect">Conectează-te</string> - <string name="resolve_entropy">Genereaza sursă entropie</string> - <string name="menu_insert">Adaugă gazdă</string> - <string name="menu_delete">Sterge gazdă</string> - <string name="menu_preferences">Setări</string> - <string name="help_intro">Selecteaza un subiect pentru a accesa mai multe informatii</string> - <string name="help_about">Despre ConnectBot</string> - <string name="help_keyboard">Tastatură</string> - <string name="pubkey_generate">Generează</string> - <string name="pubkey_import">Importă</string> - <string name="pubkey_delete">Șterge cheia</string> - <string name="pubkey_gather_entropy">Genereaza sursa entropie</string> - <string name="pubkey_touch_prompt">Apasa aceasta zona pentru a genera entropie: %1$d%% finalizat</string> - <string name="pubkey_touch_hint">Pentru a va asigura un grad inalt de stocasticitate in timpul generarii cheii, miscati cat mai aleator degetul in zona de mai jos</string> - <string name="pubkey_generating">Generare cheie ...</string> - <string name="pubkey_copy_private">Copiaza cheia privata</string> - <string name="pubkey_copy_public">Copiaza cheia publica</string> - <string name="pubkey_list_empty">Apasa \"Menu\" pentru a crea sau pentru a importa chei.</string> - <string name="pubkey_unknown_format">Format necunoscut</string> - <string name="pubkey_change_password">Schimbă parola</string> - <string name="pubkey_list_pick">Selecteaza de pe /card SD</string> - <string name="pubkey_import_parse_problem">A aparut o eroare in timpul citirii cheii private</string> - <string name="pubkey_unlock">Decripteaza cheia</string> - <string name="pubkey_failed_add">Parola gresita pentru cheia \'%1$s\'. Autenticitatea cererii nu poate fi verificata.</string> - <string name="pubkey_memory_load">Incarca in memorie</string> - <string name="pubkey_memory_unload">Sterge din memorie</string> - <string name="pubkey_load_on_start">Incarca cheia la start</string> - <string name="pubkey_confirm_use">Confirma alegerea inainte de folosirea cheii</string> - <string name="portforward_list_empty">Apasa \"Menu\" pentru a crea redirectari de trafic</string> - <string name="portforward_edit">Editeaza redirectari trafic</string> - <string name="portforward_delete">Sterge redirectari trafic</string> - <string name="prompt_nickname">Poreclă:</string> - <string name="prompt_nickname_hint_pubkey">Cheia mea</string> - <string name="prompt_source_port">Port sursă</string> - <string name="prompt_destination">Destinație</string> - <string name="prompt_old_password">Parola veche:</string> - <string name="prompt_password">Parolă:</string> - <string name="prompt_again">(din nou)</string> - <string name="prompt_type">Mod redirectare:</string> - <string name="prompt_password_can_be_blank">Nota: parola</string> - <string name="prompt_bits">Biți:</string> - <string name="prompt_pubkey_password">Parola pentru cheia \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Acceptați utilizarea cheii \'%1$s\' \nde către agentul de autentificare?</string> - <string name="host_verification_failure_warning_header">ATENTIE: IDENTITATEA SISTEMULUI CONECTAT S-A SCHIMBAT!</string> -</resources>
--- a/res/values-ru/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Простой и мощный SSH-клиент с открытым исходным кодом.</string> - <string name="service_desc">Управляет SSH-соединениями и загруженными публичными ключами</string> - <string name="title_hosts_list">Серверы</string> - <string name="title_pubkey_list">Публичные ключи</string> - <string name="title_port_forwards_list">Проброс портов</string> - <string name="title_host_editor">Изменить сервер</string> - <string name="title_help">Помощь</string> - <string name="title_colors">Настройка цветов</string> - <string name="resolve_connect">Подключиться</string> - <string name="resolve_entropy">Сбор случайных данных</string> - <string name="menu_insert">Добавить сервер</string> - <string name="menu_delete">Удалить сервер</string> - <string name="menu_preferences">Настройки</string> - <string name="help_intro">Выберите то, о чём Вы хотите узнать</string> - <string name="help_about">О ConnectBot</string> - <string name="help_keyboard">Клавиатура</string> - <string name="pubkey_generate">Генерировать</string> - <string name="pubkey_import">Импортировать</string> - <string name="pubkey_delete">Удалить ключ</string> - <string name="pubkey_gather_entropy">Сбор случайной информации</string> - <string name="pubkey_touch_prompt">Нажмите сюда для генерирования случайной информации: %1$d%% готово</string> - <string name="pubkey_touch_hint">Для использования случайной выборки во время генерации ключа - перемещайте палец в области экрана ниже.</string> - <string name="pubkey_generating">Генерирование пары ключей</string> - <string name="pubkey_copy_private">Копировать приватный ключ</string> - <string name="pubkey_copy_public">Копировать публичный ключ</string> - <string name="pubkey_list_empty">Выберите Меню для создания или импорта пары ключей</string> - <string name="pubkey_unknown_format">Неизвестный формат</string> - <string name="pubkey_change_password">Сменить пароль</string> - <string name="pubkey_list_pick">Загрузить с SD карты</string> - <string name="pubkey_import_parse_problem">Проблема при распозновании импортированного частного ключа</string> - <string name="pubkey_unlock">Разблокировать ключ</string> - <string name="pubkey_failed_add">Неверный пароль для ключа \'%1$s\'. Аутентификация не удалась</string> - <string name="pubkey_memory_load">Загрузить в память</string> - <string name="pubkey_memory_unload">Выгрузить из памяти</string> - <string name="pubkey_load_on_start">Загружать ключ при старте</string> - <string name="pubkey_confirm_use">Подтверждение перед использованием</string> - <string name="portforward_list_empty">Выберите Меню для переадресации порта</string> - <string name="portforward_edit">Правка переадресации порта</string> - <string name="portforward_delete">Удалить переадресацию порта</string> - <string name="prompt_nickname">Псевдоним:</string> - <string name="prompt_nickname_hint_pubkey">Мой рабочий ключ</string> - <string name="prompt_source_port">С порта</string> - <string name="prompt_destination">На порт</string> - <string name="prompt_old_password">Старый пароль:</string> - <string name="prompt_password">Пароль:</string> - <string name="prompt_again">(повторить)</string> - <string name="prompt_type">Тип переадресации</string> - <string name="prompt_password_can_be_blank">Поле для ввода пароля не может быть пустым</string> - <string name="prompt_bits">Размер в битах</string> - <string name="prompt_pubkey_password">Пароль для ключа \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Использовать ключ \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">ВНИМАНИЕ! ИДЕНТИФИКАЦИЯ УДАЛЕННОГО ХОСТА ЗАМЕНЕНА</string> - <string name="host_verification_failure_warning">Похоже есть возможность что вас ломают. Или кто то изменил ключ на удаленном хосте.</string> - <string name="prompt_host_disconnected">Хост отвалился.\nЗакрыть сессию ?</string> - <string name="prompt_continue_connecting">Хотите продолжить\nпопытки соединения?</string> - <string name="host_authenticity_warning">Подлинность хоста \'%1$s\' не может быть установлена</string> - <string name="host_fingerprint">Подпись (fingerprint) host-ключа для сервера %1$s - %2$s</string> - <string name="alert_passwords_do_not_match_msg">Пароли не совпадают!</string> - <string name="alert_wrong_password_msg">Неверный пароль!</string> - <string name="alert_key_corrupted_msg">Возможно частный ключ повреждён!</string> - <string name="alert_sdcard_absent">SD карта не вставлена!</string> - <string name="button_add">Добавить</string> - <string name="button_change">Изменить</string> - <string name="button_generate">Генерировать ключ</string> - <string name="button_resize">Изменить размер</string> - <string name="alert_disconnect_msg">Соединение потеряно</string> - <string name="pref_emulation_category">Эмулятор терминала</string> - <string name="pref_emulation_title">Режим эмуляции</string> - <string name="pref_emulation_summary">Режим эмуляции терминала для использования PTY соединений</string> - <string name="pref_scrollback_title">Размер прокрутки</string> - <string name="pref_scrollback_summary">Размер буфера прокруктки в памяти для каждой консоли</string> - <string name="pref_ui_category">Пользовательский интерфейс</string> - <string name="pref_rotation_title">Настройки ориентации экрана</string> - <string name="pref_rotation_summary">Настройки смены ориентации дисплея при пользовании клавиатурой</string> - <string name="pref_fullscreen_title">Полный экран</string> - <string name="pref_fullscreen_summary">Убирать область статуса во время работы с консолью</string> - <string name="pref_memkeys_title">Запомнить ключи в памяти</string> - <string name="pref_memkeys_summary">Держать ключи в памяти пока процессы работают</string> - <string name="pref_update_title">Проверка обновления</string> - <string name="pref_update_summary">Как часто проверять обновления для ConnectBot</string> - <string name="pref_conn_persist_title">Постоянные соединения</string> - <string name="pref_conn_persist_summary">Принудительно сохранять соединение в фоновом режиме.</string> - <string name="pref_keymode_title">Ярлыки папок</string> - <string name="pref_keymode_summary">Выберите, как использовать Alt вместо \'/\' и Shift вместо Tab</string> - <string name="pref_camera_title">Ярлык камеры</string> - <string name="pref_camera_summary">Выберите ярлык, запускаемый при нажатии клавиши камеры</string> - <string name="pref_keepalive_title">Держать экран включенным</string> - <string name="pref_keepalive_summary">Препятствовать отключению экрана при работе в консоли</string> - <string name="pref_wifilock_title">Держать Wi-Fi включенным</string> - <string name="pref_wifilock_summary">Препятствовать отключению Wi-Fi при активном сеансе</string> - <string name="pref_bumpyarrows_title">Настройки обратной связи при нажатии</string> - <string name="pref_bumpyarrows_summary">Вибросигнал при передаче клавиш управления курсором с трекбола; полезно при медленном соединении</string> - <string name="pref_bell_category">Настройки звукового сигнала в терминале</string> - <string name="pref_bell_title">Включить звонок</string> - <string name="pref_bell_volume_title">Громкость сигнала</string> - <string name="pref_bell_vibrate_title">Виброзвонок</string> - <string name="pref_bell_notification_title">Фоновые уведомления</string> - <string name="pref_bell_notification_summary">Включить уведомления для терминала работающего в фоновом процессе</string> - <string name="list_keymode_right">Для специальных функций использовать клавиши с правой стороны</string> - <string name="list_keymode_left">Использовать клавиши с левой стороны</string> - <string name="list_keymode_none">Отключить</string> - <string name="list_pubkeyids_none">Не использовать ключи</string> - <string name="list_pubkeyids_any">Использовать любую свободную клавишу</string> - <string name="hostpref_nickname_title">Псевдоним</string> - <string name="hostpref_color_title">Цвет для категории</string> - <string name="hostpref_fontsize_title">Размер шрифта</string> - <string name="hostpref_pubkeyid_title">Использовать аутентификацию по открытому ключу</string> - <string name="hostpref_authagent_title">Использовать SSH протокол для соединения</string> - <string name="hostpref_postlogin_title">Автоматизация после авторизации</string> - <string name="hostpref_postlogin_summary">Комманды, выполняемые на удаленной машине после подключения</string> - <string name="hostpref_compression_title">Сжатие</string> - <string name="hostpref_compression_summary">Это может быть полезным в медленных сетях</string> - <string name="hostpref_wantsession_title">Начать сеанс оболочки</string> - <string name="hostpref_wantsession_summary">Выключить для использования только переадресации портов</string> - <string name="hostpref_stayconnected_title">Держать подключение</string> - <string name="hostpref_stayconnected_summary">Пытаться переподключиться при отключении узла</string> - <string name="hostpref_delkey_title">Клавиша DEL</string> - <string name="hostpref_delkey_summary">Послать данный код при нажатие клавиши DEL</string> - <string name="hostpref_encoding_title">Кодировка</string> - <string name="hostpref_encoding_summary">Кодировка символов узла</string> - <string name="hostpref_connection_category">Настройки соединения</string> - <string name="hostpref_username_title">Имя пользователя</string> - <string name="hostpref_hostname_title">Узел</string> - <string name="hostpref_port_title">Порт</string> - <string name="bind_never">Не подключен</string> - <string name="bind_minutes">%1$s минут назад</string> - <string name="bind_hours">%1$s час(ов) назад</string> - <string name="bind_days">%1$s дней назад</string> - <string name="console_copy_done">Скопировано %1$d байт в буфер обмена</string> - <string name="console_copy_start">Для выделения области на экране используйте Touch and Drag или Directional Pad</string> - <string name="console_menu_close">Закрыть</string> - <string name="console_menu_copy">Копировать</string> - <string name="console_menu_paste">Вставить</string> - <string name="console_menu_portforwards">Перенаправления портов</string> - <string name="console_menu_resize">Зафиксировать размер</string> - <string name="console_menu_urlscan">Список URL</string> - <string name="button_yes">Да</string> - <string name="button_no">Нет</string> - <string name="portforward_local">Локальный</string> - <string name="portforward_remote">Удалённый</string> - <string name="portforward_dynamic">Динамический (SOCKS)</string> - <string name="portforward_pos">Создать перенаправление порта</string> - <string name="portforward_done">Перенаправление порта успешно завершено</string> - <string name="portforward_problem">Не удалось создать перенаправление порта. Может быть вы используете порты меньше чем 1024 или пор уже используется?</string> - <string name="portforward_menu_add">Добавить перенаправление порта</string> - <string name="hint_userhost">пользователь\@имяхоста</string> - <string name="list_format_error">Используйте формат %1$s</string> - <string name="format_username">имя пользователя</string> - <string name="format_hostname">имяхоста</string> - <string name="format_port">порт</string> - <string name="list_menu_pubkeys">Управление открытыми ключами</string> - <string name="list_menu_sortcolor">Сортировать по цвету</string> - <string name="list_menu_sortname">Сортировать по имени</string> - <string name="list_menu_settings">Настройки</string> - <string name="list_host_disconnect">Разорвать соединение</string> - <string name="list_host_edit">Редактировать хост</string> - <string name="list_host_portforwards">Редактировать перенаправление портов</string> - <string name="list_host_delete">Удалить хост</string> - <string name="list_host_empty">Для быстрого подключения к хосту используйте чекбокс внизу</string> - <string name="list_rotation_default">По умолчанию</string> - <string name="list_rotation_land">Только альбомная ориентация</string> - <string name="list_rotation_port">Только портретная ориетация</string> - <string name="list_rotation_auto">Автоматически</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A затем пробел</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Нет</string> - <string name="list_delkey_backspace">Backspace</string> - <string name="list_delkey_del">Удалить</string> - <string name="delete_message">Вы уверены, что хотите удалить \'%1$s\'?</string> - <string name="delete_pos">Да, удалить</string> - <string name="delete_neg">Отменить</string> - <string name="wizard_agree">Соглашаюсь</string> - <string name="wizard_next">Далее</string> - <string name="wizard_back">Назад</string> - <string name="terminal_no_hosts_connected">Нет подключенных узлов</string> - <string name="terminal_connecting">Подключение к %1$s:%2$d через %3$s</string> - <string name="terminal_sucess">Проверенный узел \'%1$s\' ключ: %2$s</string> - <string name="terminal_failed">Проверка ключа узла провалена</string> - <string name="terminal_using_s2c_algorithm">Алгоритм сервер-клиент: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Алгоритм клиент-сервер: %1$s %2$s</string> - <string name="terminal_using_algorithm">Используемый алгоритм: %1$s %2$s</string> - <string name="terminal_auth">Пытаюсь аутентифицироваться</string> - <string name="terminal_auth_pass">Попытка \'password\' авторизации</string> - <string name="terminal_auth_pass_fail">Неуспешная попытка \'password\' авторизации</string> - <string name="terminal_auth_pubkey_any">Попытка \'publickey\' авторизации с публичными ключами в памяти</string> - <string name="terminal_auth_pubkey_invalid">Выбранный открытый ключ неверен, выберите другой в редакторе узлов</string> - <string name="terminal_auth_pubkey_specific">Попытка \'publickey\' авторизации</string> - <string name="terminal_auth_pubkey_fail">Неуспешная авторизация \'publickey\' с ключом \'%1$s\'</string> - <string name="terminal_auth_ki">Попытка \'keyboard-interactive\' авторизации</string> - <string name="terminal_auth_ki_fail">Неуспешная авторизация</string> - <string name="terminal_auth_fail">Ваш хост не поддерживает \'password\' и \'keyboard-interactive\' типа авторизации</string> - <string name="terminal_no_session">Настройки хоста не позволяют запустить данную сессию</string> - <string name="terminal_enable_portfoward">Включить переадресацию порта: %1$s</string> - <string name="local_shell_unavailable">Ошибка! На этом телефоне отсутствует локальная оболочка.</string> - <string name="notification_text">%1$s требует внимания</string> - <string name="no">Нет</string> - <string name="with_confirmation">С подтверждением</string> - <string name="yes">Да</string> - <string name="exceptions_submit_message">Возможно, при последнем запуске программы возникла проблема. Отправить разработчикам отчет об ошибке?</string> - <string name="menu_colors_reset">Сбросить</string> - <string name="app_is_running">ConnectBot запущен</string> - <string name="color_red">красный</string> - <string name="color_green">зелёный</string> - <string name="color_blue">синий</string> - <string name="color_gray">серый</string> - <string name="image_description_connected">Подключено</string> - <string name="image_description_show_keyboard">Показать клавиатуру</string> -</resources>
--- a/res/values-sk/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,316 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Jednoduchý, výkonný, open-source SSH klient.</string> - <string name="service_desc">Spravuje SSH spojenia a načítané verejné kľúče</string> - <string name="auth_agent_service_desc">"Pracuje ako SSH-Agent pre iné aplikácie na tomto zarieadení"</string> - <string name="ssh_agent_permission_label">použíť SSH kľúče uložené vo Vašom SSH-Agentovi</string> - <string name="ssh_agent_permission_desc">Povolí aplikácií autentifikáciu SSH transakcií pomocou Vašich súkromných kľúčov uložených v aplikácii ConnectBot. - VEĽMI NEBEZPEČNÉ ak zneužité zlomyselnou aplikáciou.</string> - <string name="title_hosts_list">Hostitelia</string> - <string name="title_pubkey_list">Verejné kľúče</string> - <string name="title_port_forwards_list">Presmerovanie portov</string> - <string name="title_host_editor">Upraviť Hostiteľa</string> - <string name="title_help">Nápoveda</string> - <string name="title_colors">Farby</string> - <string name="resolve_connect">Pripojiť</string> - <string name="resolve_entropy">Získať entropiu</string> - <string name="menu_insert">Pridať hostiteľa</string> - <string name="menu_delete">Zmazať hostiteľa</string> - <string name="menu_preferences">Nastavenia</string> - <string name="help_intro">Prosím, vyberte si tému pre viac informácií o danom subjekte.</string> - <string name="help_about">O programe ConnectBot</string> - <string name="help_keyboard">Klávesnica</string> - <string name="pubkey_generate">Vygenerovať</string> - <string name="pubkey_import">Importovať</string> - <string name="pubkey_delete">Zmazať kľúč</string> - <string name="pubkey_gather_entropy">Získavanie entropie</string> - <string name="pubkey_touch_prompt">Dotknite sa plochy pre získanie náhodnosti: %1$d%% hotovo</string> - <string name="pubkey_touch_hint">Pre zabezpečenie náhodnosti počas generovania kľúča pohybujte prstom náhodne po ploche nižšie.</string> - <string name="pubkey_generating">"Generujem kľúčový pár…"</string> - <string name="pubkey_copy_private">Kopírovať súkromný kľúč</string> - <string name="pubkey_copy_public">Kopírovať verejný kľúč</string> - <string name="pubkey_list_empty">Ťukni na Menu pre vytvorenie\nalebo importovanie páru kľúčov.</string> - <string name="pubkey_unknown_format">Neznámy formát</string> - <string name="pubkey_change_password">Zmeniť heslo</string> - <string name="pubkey_list_pick">Vyberte z /sdcard</string> - <string name="pubkey_import_parse_problem">Chyba pri importe súkromného kľúča</string> - <string name="pubkey_unlock">Odomknúť kľúč</string> - <string name="pubkey_failed_add">Nesprávne heslo pre kľúč \'%1$s\'. Overenie zlyhalo.</string> - <string name="pubkey_memory_load">Nahrať do pamäte</string> - <string name="pubkey_memory_unload">Odstrániť z pamäte</string> - <string name="pubkey_load_on_start">Načítať kľúč pri štarte</string> - <string name="pubkey_confirm_use">Potvrdiť pred použitím</string> - <string name="portforward_list_empty">Ťukni na Menu pre vytvorenie\npresmerovania portov.</string> - <string name="portforward_edit">Upraviť presmerovanie portov</string> - <string name="portforward_delete">Zmazať smerovanie portu</string> - <string name="prompt_nickname">Prezývka:</string> - <string name="prompt_nickname_hint_pubkey">Môj pracovný kľúč</string> - <string name="prompt_source_port">Zdrojový port:</string> - <string name="prompt_destination">Cieľ:</string> - <string name="prompt_old_password">Staré heslo:</string> - <string name="prompt_password">Heslo:</string> - <string name="prompt_again">(znovu)</string> - <string name="prompt_type">Typ:</string> - <string name="prompt_password_can_be_blank">Poznámka: heslo nemôže byť prázdne</string> - <string name="prompt_bits">Veľkost v bitoch:</string> - <string name="prompt_pubkey_password">Heslo pre kľúč \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Povoliť vzdialenému hostitelovi\npoužíť kľúč \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">VAROVANIE! IDENTIFIKÁCIA VZDIALENÉHO HOSTITEĽA SA ZMENILA!</string> - <string name="host_verification_failure_warning">JE MOŽNÉ, ŽE IDE O NEKALÚ AKTIVITU!\nNiekto vás môže sledovať (man-in-the-middle útok)!\nTiež je možné, že kľúč hostiteľa bol zmenený.</string> - <string name="prompt_host_disconnected">Hostiteľ sa odpojil.\nUkončiť sedenie?</string> - <string name="prompt_continue_connecting">Naozaj chcete\npokračovať v pripájaní?</string> - <string name="host_authenticity_warning">Autenticita hostiteľa \'%1$s\' nemohla byť overená.</string> - <string name="host_fingerprint">Odtlačok kľúča hostiteľa %1$s je %2$s</string> - <string name="alert_passwords_do_not_match_msg">Heslo sa nezhoduje!</string> - <string name="alert_wrong_password_msg">Nesprávne heslo!</string> - <string name="alert_key_corrupted_msg">Súkromný kľúč vyzerá poškodene!</string> - <string name="alert_sdcard_absent">Nie je vložená SD karta!</string> - <string name="button_add">Pridať</string> - <string name="button_change">Zmeniť</string> - <string name="button_generate">Vygenerovať kľúč</string> - <string name="button_resize">Zmeniť veľkosť</string> - <string name="button_resize_reset">Prednastavená veľkosť</string> - <string name="alert_disconnect_msg">Spojenie stratené</string> - <string name="pref_emulation_category">Emulácia terminálu</string> - <string name="pref_emulation_title">Mód emulácie</string> - <string name="pref_emulation_summary">Použiť mód emulácie terminálu pri PTY spojeniach</string> - <string name="pref_scrollback_title">Veľkosť histórie</string> - <string name="pref_scrollback_summary">Veľkosť histórie uložená v pamäti pre každú konzolu</string> - <string name="pref_ui_category">Používateľské rozhranie</string> - <string name="pref_rotation_title">Mód otáčania</string> - <string name="pref_rotation_summary">Ako zmeniť rotáciu, keď sa zobrazí / skryje klávesnica</string> - <string name="pref_memkeys_title">Zapamätať kľúče v pamäti</string> - <string name="pref_memkeys_summary">Ponechať odomknuté kľúče v pamäti pokiaľ nie je ukončená služba na pozadí.</string> - <string name="pref_update_title">Kontrolovať aktualizácie</string> - <string name="pref_update_summary">Nastaviť maximálnu frekvenciu kontroly aktualizácií pre ConnectBot</string> - <string name="pref_conn_persist_title">Perzistentné pripojenia</string> - <string name="pref_conn_persist_summary">Vynútiť spojenie aj v pozadí</string> - <string name="pref_keymode_title">Skratky adresárov</string> - <string name="pref_keymode_summary">Vyberte ako použiť Alt pre \'/\' a Shift pre Tab</string> - <string name="pref_camera_title">Tlačidlo fotoaparát</string> - <string name="pref_camera_summary">Činnosť, ktorá sa vykoná po stlačení tlačidla fotoaparátu</string> - <string name="pref_volup_title">Tlačidlo hlasnejšie</string> - <string name="pref_volup_summary">Činnosť, ktorá sa vykoná po stlačení tlačidla hlasnejšie</string> - <string name="pref_voldn_title">Tlačidlo tichšie</string> - <string name="pref_voldn_summary">Činnosť, ktorá sa vykoná po stlačení tlačidla tichšie</string> - <string name="pref_search_title">Tlačidlo hľadať</string> - <string name="pref_search_summary">Činnosť, ktorá sa vykoná po stlačení tlačidla hľadať</string> - <string name="pref_keepalive_title">Ponechať obrazovku zapnutú</string> - <string name="pref_keepalive_summary">Zabrániť vypnutiu obrazovky pri práci s konzolou</string> - <string name="pref_wifilock_title">Ponechať Wi-Fi aktívne</string> - <string name="pref_wifilock_summary">Ponechať Wi-Fi aktívne pokiaľ je otvorené spojenie</string> - <string name="pref_bumpyarrows_title">Hrboľaté šípky</string> - <string name="pref_bumpyarrows_summary">Vibrovať pri posielaní kurzorových tlačidiel z trackballu; užitočné pre chybové spojenia</string> - <string name="pref_bell_category">Zvonček terminálu</string> - <string name="pref_bell_title">Akustický zvonček</string> - <string name="pref_bell_volume_title">Hlasitosť zvončeka</string> - <string name="pref_bell_vibrate_title">Vibrovať pri zvončeku</string> - <string name="pref_bell_notification_title">Upozornenia na pozadí</string> - <string name="pref_bell_notification_summary">Zobraziť upozorneni ak zazvoní zvonček terminálu bežiaceho v pozadí.</string> - <string name="list_keymode_right">Použite klávesy vpravo</string> - <string name="list_keymode_left">Použite klávesy vľavo</string> - <string name="list_keymode_none">Vypnúť</string> - <string name="list_pubkeyids_none">Nepoužívať kľúče</string> - <string name="list_pubkeyids_any">Použiť ktorýkoľvek odomknutý kľúč</string> - <string name="hostpref_nickname_title">Prezývka</string> - <string name="hostpref_color_title">Farebná kategória</string> - <string name="hostpref_fontsize_title">Veľkosť písma (bodov)</string> - <string name="hostpref_pubkeyid_title">Použiť verejný kľúč pre autentifikáciu</string> - <string name="hostpref_authagent_title">Použiť SSH autorizačného agenta</string> - <string name="hostpref_postlogin_title">Automatizácia po prihlásení</string> - <string name="hostpref_postlogin_summary">Príkazy, ktoré sa spustia na vzdialenom serveri po prihlásení</string> - <string name="hostpref_compression_title">Kompresia</string> - <string name="hostpref_compression_summary">Môže pomôcť pri pomalých sieťach</string> - <string name="hostpref_wantsession_title">Spustiť sedenie shellu</string> - <string name="hostpref_wantsession_summary">Vypnite túto možnosť ak chcete len presmerovať porty</string> - <string name="hostpref_stayconnected_title">Zostať pripojený</string> - <string name="hostpref_stayconnected_summary">Znovu sa pripojiť pri odpojení</string> - <string name="hostpref_delkey_title">Klávesa DEL</string> - <string name="hostpref_delkey_summary">Kód stlačenej DEL klávesy</string> - <string name="hostpref_encoding_title">Kódovanie</string> - <string name="hostpref_encoding_summary">Kódovanie znakov hostiteľa</string> - <string name="hostpref_connection_category">Nastavenia pripojenia</string> - <string name="hostpref_username_title">Používateľské meno</string> - <string name="hostpref_hostname_title">Hostiteľ</string> - <string name="hostpref_port_title">Port</string> - <string name="hostpref_x11_forwarding">"Presmerovanie X11"</string> - <string name="hostpref_wantx11forward_title">"Zapnúť presmerovanie X11"</string> - <string name="hostpref_wantx11forward_summary">"Sedenia X11 budú presmerované na hostiteľa a port uvedený nižšie"</string> - <string name="hostpref_x11host_title">"Hostiteľ pre presmerovanie X11"</string> - <string name="hostpref_x11port_title">"Port pre presmerovanie X11"</string> - <string name="bind_never">Nikdy nepripojený</string> - <string name="bind_minutes">Pred %1$s minútami</string> - <string name="bind_hours">Pred %1$s hodinami</string> - <string name="bind_days">Pred %1$s dňami</string> - <string name="console_copy_done">%1$d bajtov skopírovaných do schránky</string> - <string name="console_copy_start">Pre výber kopírovanej oblasti \nsa dotknite a ťahajte\nalebo použite smerové tlačidlo</string> - <string name="console_menu_close">Zatvoriť</string> - <string name="console_menu_copy">Kopírovať</string> - <string name="console_menu_paste">Vložiť</string> - <string name="console_menu_portforwards">Presmerovanie portov</string> - <string name="console_menu_resize">Vynútiť veľkosť</string> - <string name="console_menu_urlscan">Nájsť URL</string> - <string name="console_menu_screencapture">Snímka obrazovky</string> - <string name="console_menu_download">"Prevziať súbor"</string> - <string name="console_menu_upload">"Odoslať súbor"</string> - <string name="button_yes">Áno</string> - <string name="button_no">Nie</string> - <string name="portforward_local">Lokálny</string> - <string name="portforward_remote">Vzdialený</string> - <string name="portforward_dynamic">Dynamický (SOCKS)</string> - <string name="portforward_pos">Vytvoriť presmerovanie portu</string> - <string name="portforward_done">Premerovanie portu úspešne vytvorené</string> - <string name="portforward_problem">Chyba pri vytvorení presmerovania portu, možno používate port menší ako 1024 alebo je už obsadený?</string> - <string name="portforward_menu_add">Pridať presmerovanie portu</string> - <string name="hint_userhost">používateľ\@hostiteľ</string> - <string name="list_format_error">Použite formát \"%1$s\"</string> - <string name="format_username">používateľ</string> - <string name="format_hostname">hostiteľ</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Spravovať verejné kľúče</string> - <string name="list_menu_sortcolor">Usporiadať podľa farby</string> - <string name="list_menu_sortname">Usporiadať podľa názvu</string> - <string name="list_menu_settings">Nastavenia</string> - <string name="list_host_disconnect">Odpojiť</string> - <string name="list_host_edit">Upraviť nastavenia hostiteľa</string> - <string name="list_host_portforwards">Upraviť presmerovanie portov</string> - <string name="list_host_delete">Zmazať hostiteľa</string> - <string name="list_host_empty">Použite pole rýchleho pripojenia\nnižšie pre pripojenie k hostiteľovi.</string> - <string name="list_rotation_default">Predvolené</string> - <string name="list_rotation_land">Vynútiť na šírku</string> - <string name="list_rotation_port">Vynútiť na výšku</string> - <string name="list_rotation_auto">Automaticky</string> - <string name="list_hwbutton_screen_capture">Snímka obrazovky</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A , potom medzerník</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Klávesa Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Žiadny</string> - <string name="list_delkey_backspace">Backspace</string> - <string name="list_delkey_del">Delete</string> - <string name="delete_message">Naozaj chcete zmazať \'%1$s\'?</string> - <string name="delete_pos">Áno, vymazať</string> - <string name="delete_neg">Zrušiť</string> - <string name="wizard_agree">Súhlasím</string> - <string name="wizard_next">Ďalej</string> - <string name="wizard_back">Späť</string> - <string name="terminal_no_hosts_connected">Žiadny hostiteľ nie je pripijený</string> - <string name="terminal_connecting">Pripájanie k %1$s:%2$d cez %3$s</string> - <string name="terminal_sucess">Hostiteľ overený \'%1$s\' kľúč: %2$s</string> - <string name="terminal_failed">Overenie kľúča hostiteľa neúspešné.</string> - <string name="terminal_using_s2c_algorithm">Server-klient algoritmus: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Klient-server algoritmus: %1$s %2$s</string> - <string name="terminal_using_algorithm">Použitie algoritmu: %1$s %2$s</string> - <string name="terminal_auth">Pokus o overenie</string> - <string name="terminal_auth_pass">Pokus o overenie heslom</string> - <string name="terminal_auth_pass_fail">Overenie heslom neúspešné</string> - <string name="terminal_auth_pubkey_any">Pokus o overenie verejným kľúčom z pamäti</string> - <string name="terminal_auth_pubkey_invalid">Vybraný verejný kľúč je neplatný, skúste zvoliť kľúč v editore hostiteľov</string> - <string name="terminal_auth_pubkey_specific">Pokus o overenie konkrétnym verejným kľúčom</string> - <string name="terminal_auth_pubkey_fail">Overenie verejným kľúčom \'%1$s\' zlyhalo</string> - <string name="terminal_auth_ki">Pokus o overenie cez interaktívnu klávesnicu</string> - <string name="terminal_auth_ki_fail">Overenie cez interaktívnu klávesnicu zlyhalo</string> - <string name="terminal_auth_fail">[Váš hostiteľ nepodporuje overenie heslom alebo overenie cez interaktívnu klávesnicu.]</string> - <string name="terminal_no_session">Sedenie nebude spustené z dôvodu nastavenia hostiteľa.</string> - <string name="terminal_enable_portfoward">Zapnúť presmerovanie portu: %1$s</string> - <string name="local_shell_unavailable">Chyba! Lokálny shell je nedostupný na tomto telefóne.</string> - <string name="notification_text">%1$s vyžaduje vašu pozornosť.</string> - <string name="no">Nie</string> - <string name="with_confirmation">S potvrdením</string> - <string name="yes">Áno</string> - <string name="exceptions_submit_message">Ostatné spustenie ConnectBot asi skončilo chybou. Zaslať chýbovú správu vývojárom ConnectBot?</string> - <string name="menu_colors_reset">Pôvodné</string> - <string name="app_is_running">ConnectBot je spustený</string> - <string name="color_red">červená</string> - <string name="color_green">zelená</string> - <string name="color_blue">modrá</string> - <string name="color_gray">sivá</string> - <string name="button_close">Zavrieť</string> - <string name="pref_custom_keymap_title">Prispôsobenie klávesnice</string> - <string name="pref_custom_keymap_summary">Presmerovanie vybraných kláves na podporovaných zariadeniach</string> - <string name="pref_custom_keymap_full">plnohodnotná klávesnica</string> - <string name="pref_custom_keymap_disabled">vypnuté</string> - <string name="resize_error_title">Chyba pri zmene veľkosti</string> - <string name="resize_error_width_height">Šírka a výška musia byť väčšie ako 0</string> - <string name="pref_screen_capture_category">Snímka obrazovky</string> - <string name="pref_screen_capture_folder">Cesta pre snímku obrazovky</string> - <string name="pref_screen_capture_folder_summary">Priečinok, kam sa budú ukladať snímky obrazovky</string> - <string name="pref_screen_capture_popup">Správa o snímke obrazovky</string> - <string name="pref_screen_capture_popup_summary">Zobraziť vyskakovacie okno pri úspešnej snímke obrazovky</string> - <string name="screen_capture">Snímka obrazovky</string> - <string name="screenshot_success_title">Snímka obrazovky úspešná</string> - <string name="screenshot_saved_as">Snímka obrazovky bola uložená do</string> - <string name="screenshot_error_title">Chyba pri snímke obrazvky</string> - <string name="screenshot_not_saved_as">Snímka obrazovky nemohla byť uložená do</string> - <string name="pref_picker_string">Obsah okna Sym</string> - <string name="pref_picker_string_summary">Sada znakov do dialógového okna na výber znaku</string> - <string name="pref_picker_keep_open">Ponechať okno Sym otvorené</string> - <string name="pref_picker_keep_open_summary">Iba tlačidlo zrušiť zavrie dialógové okno na výber znaku</string> - <string name="pref_file_transfer_category">Prenos súborov</string> - <string name="pref_file_dialog_title">Výber súbora</string> - <string name="pref_file_dialog_summary">Formulár na výber súborov a priečinkov</string> - <string name="pref_file_dialog_builtin">zabudovaný</string> - <string name="error_starting_app">Nepodarilo sa spustiť %1$s</string> - <string name="file_chooser_select_file">Vybrať súbor %1s</string> - <string name="select_for_download">na prevzatie</string> - <string name="select_for_upload">na odoslanie</string> - <string name="select_for_key_import">na import kľúča</string> - <string name="location">Umiestnenie</string> - <string name="cant_read_folder">Chyba pri čítaní priečinka.</string> - <string name="nnew">Nové</string> - <string name="select">Vybrať</string> - <string name="file_name">Názov súbora:</string> - <string name="cancel">Zrušiť</string> - <string name="save">Uložiť</string> - <string name="new_file">Nový súbor</string> - <string name="no_data">Žiadne dáta</string> - <string name="pref_download_folder">Priečinok pre preberanie</string> - <string name="pref_download_folder_summary">Cesta pre ukladanie prevzatých súborov</string> - <string name="pref_remote_upload_folder">Vzdialený priečinok pre odosielanie</string> - <string name="pref_remote_upload_folder_summary">Vzdialená cesta pre odosielanie súborov</string> - <string name="pref_upload_dest_prompt">Pýtať sa na vzdialené umiestnenie</string> - <string name="pref_upload_dest_prompt_summary">Zadávať vzdialený nazov alebo cestu pre odosielaný súbor</string> - <string name="pref_background_file_transfer">Prenos súborov na pozadí</string> - <string name="pref_background_file_transfer_summary">Odosielanie a preberanie súborov uskutočniť na pozadí.</string> - <string name="transfer_downloading">"Preberanie súborov…"</string> - <string name="transfer_downloading_file">Preberanie súbora: %1$s</string> - <string name="transfer_download_complete">Preberanie ukončené</string> - <string name="transfer_download_failed">Chyba pri preberaní:%1$s</string> - <string name="transfer_select_remote_download_title">Prevziať súbor(y)</string> - <string name="transfer_select_remote_download_desc">Cesty k vzdialeným súborom na prevzatie (jeden na riadok)</string> - <string name="transfer_select_remote_upload_dest_title">Umiestnenie odosielaného súbora</string> - <string name="transfer_select_remote_upload_dest_desc">Vzdialené umiestnenie pre:</string> - <string name="transfer_button_download">Prevziať</string> - <string name="transfer_button_upload">Odoslať</string> - <string name="transfer_uploading">"Odosielanie súborov…"</string> - <string name="transfer_uploading_file">Odosielanie súbora: %1$s</string> - <string name="transfer_upload_complete">Odosielanie ukončené</string> - <string name="transfer_upload_failed">Chyba pri odosielaní:%1$s</string> - <string name="pubkey_export_private">"Exportovať súkromný kľúč"</string> - <string name="pubkey_export_public">"Exportovať verejný kľúč"</string> - <string name="pubkey_public_save_as">Uložiť verejný kľúč</string> - <string name="pubkey_public_save_as_desc">Názov súboru (s cestou) pre uloženie verejného kľúča</string> - <string name="pubkey_private_save_as">Uložiť súkromný kľúč</string> - <string name="pubkey_private_save_as_desc">Názov súboru (s cestou) pre uloženie súkromného kľúča</string> - <string name="pubkey_public_export_success">Verejný kľúč bol uložený ako %1$s</string> - <string name="pubkey_public_export_problem">Chyba pri exporte verejného kľúča</string> - <string name="pubkey_private_export_success">Súkromný kľúč bol uložený ako %1$s</string> - <string name="pubkey_private_export_problem">Chyba pri exporte súkromného kľúča</string> - <string name="pref_debug_category">Nastavenia pre vývoj</string> - <string name="pref_debug_keycodes">Zobrazovať kódy kláves</string> - <string name="pref_debug_keycodes_summary">Zobrazovať kódy stlačených kláves v termináli</string> - <string name="keycode_pressed">Kód stlačenej klávesy</string> - <string name="pref_extended_longpress">Rozšírené menu dlhého stlačenia</string> - <string name="pref_extended_longpress_summary">Zobraziť možnosti vstupu v menu dlhého stlačenia</string> - <string name="longpress_select_action">Vybrať akciu</string> - <string name="longpress_enable_full_screen_mode">Zapnúť režim celej obrazovky</string> - <string name="longpress_disable_full_screen_mode">Vypnúť režim celej obrazovky</string> - <string name="longpress_change_font_size">Zmeniť veľkosť písma</string> - <string name="longpress_arrows_dialog">Šípky</string> - <string name="longpress_ctrl_dialog">CTRL+?</string> - <string name="longpress_fkeys_dialog">Funkčné klávesy</string> - <string name="longpress_sym_dialog">Výber znaku</string> - <string name="pref_ctrl_string">Obsah okna Ctrl</string> - <string name="pref_ctrl_string_summary">Sada znakov na výber kombinácie CTRL+?</string> - <string name="fullscreen">Celá obrazovka</string> -</resources>
--- a/res/values-sl/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Enostaven, močan, odprtokodni SSH odjemalec.</string> - <string name="service_desc">Vzdržuje SSH povezave in naložene javne ključe</string> - <string name="title_hosts_list">Gostitelji</string> - <string name="title_pubkey_list">Javni ključi</string> - <string name="title_port_forwards_list">Posredovana vrata</string> - <string name="title_host_editor">Urejanje gostitelja</string> - <string name="title_help">Pomoč</string> - <string name="title_colors">Barve</string> - <string name="resolve_connect">Poveži</string> - <string name="resolve_entropy">Zberi entropijo</string> - <string name="menu_insert">Dodaj gostitelja</string> - <string name="menu_delete">Odstrani gostitelja</string> - <string name="menu_preferences">Možnosti</string> - <string name="help_intro">Izberite temo spodaj za več informacij o določeni zadevi.</string> - <string name="help_about">O ConnectBotu</string> - <string name="help_keyboard">Tipkovnica</string> - <string name="pubkey_generate">Ustvari</string> - <string name="pubkey_import">Uvozi javni ključ</string> - <string name="pubkey_delete">Izbriši ključ</string> - <string name="pubkey_gather_entropy">Zbiranje entropije</string> - <string name="pubkey_touch_prompt">Dotaknite to polje za zbiranje naključnih vrednosti: %1$d%% končano</string> - <string name="pubkey_touch_hint">Da bi zagotovili naključnost med ustvarjanjem ključa, naključno premikajte prst po polju spodaj.</string> - <string name="pubkey_generating">Ustvarjanje para ključev</string> - <string name="pubkey_copy_private">Kopirajte zasebni ključ</string> - <string name="pubkey_copy_public">Kopirajte javni ključ</string> - <string name="pubkey_list_empty">Dotaknite \"Meni\" za ustvarjanje\nali uvažanje para ključev</string> - <string name="pubkey_unknown_format">Neznana vrsta</string> - <string name="pubkey_change_password">Spremenite geslo</string> - <string name="pubkey_list_pick">Izberite iz /sdcard</string> - <string name="pubkey_import_parse_problem">Problem pri razčlenjevanju uvoženega zasebnega ključa</string> - <string name="pubkey_unlock">Odkleni ključ</string> - <string name="pubkey_failed_add">Napačno geslo za ključ \'%1$s. Overitev spodletela.</string> - <string name="pubkey_memory_load">Naloži v spomin</string> - <string name="pubkey_memory_unload">Razloži s spomina</string> - <string name="pubkey_load_on_start">Naloži ključ ob začetku</string> - <string name="pubkey_confirm_use">Potrdi pred uporabo</string> - <string name="portforward_list_empty">Dotakni \"Meni\" za ustvarjanje\nposredovanih vrat.</string> - <string name="portforward_edit">Urejaj posredovana vrata</string> - <string name="portforward_delete">Izbriši posredovana vrata</string> - <string name="prompt_nickname">Vzdevek:</string> - <string name="prompt_nickname_hint_pubkey">Moj delovni ključ</string> - <string name="prompt_source_port">Izvorna vrata:</string> - <string name="prompt_destination">Cilj:</string> - <string name="prompt_old_password">Staro geslo:</string> - <string name="prompt_password">Geslo:</string> - <string name="prompt_again">(ponovno)</string> - <string name="prompt_type">Vrsta:</string> - <string name="prompt_password_can_be_blank">Opomba: geslo je lahko prazno</string> - <string name="prompt_bits">Biti:</string> - <string name="prompt_pubkey_password">Geslo za ključ \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Dovoli oddaljenemu gostitelju\nuporabo ključa \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">OPOZORILO: ISTOVETENJE ODDALJENEGA GOSTITELJA SE JE SPREMENILO!</string> - <string name="host_verification_failure_warning">MOŽNO JE, DA NEKDO POČNE NEKAJ ZLOBNEGA!\nNekdo vam lahko prisluškuje (napad s posrednikom)!\nMožno pa je tudi, da se je spremenil ključ gostitelja.</string> - <string name="prompt_host_disconnected">Gostitelj je prekinil povezavo.\nZaprem sejo?</string> - <string name="prompt_continue_connecting">Ali ste prepričani, da želite\nnadaljevati s povezovanjem?</string> - <string name="host_authenticity_warning">Istovetnost gostitelja \'%1$s\' ni mogoče ugotoviti.</string> - <string name="host_fingerprint">Ključ gostitelja %1$s ima zgoščeno vrednost %2$s</string> - <string name="alert_passwords_do_not_match_msg">Gesla se ne ujemajo!</string> - <string name="alert_wrong_password_msg">Napačno geslo!</string> - <string name="alert_key_corrupted_msg">Zasebni ključ izgleda pokvarjen!</string> - <string name="alert_sdcard_absent">Kartica SD ni vstavljena!</string> - <string name="button_add">Dodaj</string> - <string name="button_change">Spremeni</string> - <string name="button_generate">Ustvari ključ</string> - <string name="button_resize">Spremeni velikost</string> - <string name="alert_disconnect_msg">Povezava prekinjena</string> - <string name="pref_emulation_category">Posnemanje terminala</string> - <string name="pref_emulation_title">Način posnemanja</string> - <string name="pref_emulation_summary">Način posnemanja terminala za uporabo za PTY povezave</string> - <string name="pref_scrollback_title">Velikost pomnjenja vrstic</string> - <string name="pref_scrollback_summary">Velikost medpomnilnika pomnjenih vrstic ohraniti v spomnu za vsako konzolo</string> - <string name="pref_ui_category">Uporabniški vmesnik</string> - <string name="pref_rotation_title">Način za sukanje</string> - <string name="pref_rotation_summary">Kako spremeniti sukanje, ko tipkovnica skoči ven/noter</string> - <string name="pref_fullscreen_title">Celozaslonski način</string> - <string name="pref_fullscreen_summary">Skrij vrstico stanja, ko v konzoli</string> - <string name="pref_memkeys_title">Zapomni ključe v spominu</string> - <string name="pref_memkeys_summary">Hrani odklenjene ključe v spomnu dokler storitev v zaledju ni zaključena</string> - <string name="pref_update_title">Pregled posodobitev</string> - <string name="pref_update_summary">Nastavite največjo pogostost za preverjanje posodobitev za ConnectBota</string> - <string name="pref_conn_persist_title">Obstojne povezave</string> - <string name="pref_conn_persist_summary">Prisili povezave, da ostanejo povezane v ozadju</string> - <string name="pref_keymode_title">Bližnjice mape</string> - <string name="pref_keymode_summary">Izberite kako uporabiti Alt za \'/\' ter Shift za Tab</string> - <string name="pref_camera_title">Bližnjica kamere</string> - <string name="pref_camera_summary">Izberite, katera bližnjica se sproži, ko se pritisne gumb kamere</string> - <string name="pref_keepalive_title">Ohrani zaslon dejaven</string> - <string name="pref_keepalive_summary">Prepreči ugašanje zaslona med delom v konzoli</string> - <string name="pref_wifilock_title">Ohrani Wi-Fi dejaven</string> - <string name="pref_wifilock_summary">Prepreči ugašanje Wi-Fija med dejavno sejo</string> - <string name="pref_bumpyarrows_title">Izbočene puščice</string> - <string name="pref_bell_category">Zvonec terminala</string> - <string name="pref_bell_title">Slišen zvonec</string> - <string name="pref_bell_volume_title">Glasnost zvonca</string> - <string name="pref_bell_vibrate_title">Vibriraj ob zvoncu</string> - <string name="pref_bell_notification_title">Obvestila ozadja</string> - <string name="list_keymode_left">Uporabi ključe z leve strani</string> - <string name="list_keymode_none">Onemogoči</string> - <string name="list_pubkeyids_none">Ne uporabljaj ključev</string> - <string name="list_pubkeyids_any">Uporabi kateregakoli odklenjenega ključa</string> - <string name="hostpref_nickname_title">Vzdevek</string> - <string name="hostpref_color_title">Barvna kategorija</string> - <string name="hostpref_fontsize_title">Velikost pisave (pt)</string> - <string name="hostpref_pubkeyid_title">Uporabi overitev z javnim ključem</string> - <string name="hostpref_authagent_title">Uporabi SSH overitvenega agenta</string> - <string name="hostpref_compression_title">Stiskanje</string> - <string name="hostpref_compression_summary">To vam lahko pomaga pri počasnejših omrežjih</string> - <string name="hostpref_wantsession_title">Začni sejo lupine</string> - <string name="hostpref_stayconnected_title">Ostanite povezani</string> - <string name="hostpref_stayconnected_summary">Poskusi se ponovno povezati, če se prekine povezava</string> - <string name="hostpref_delkey_title">Tipka DEL</string> - <string name="hostpref_delkey_summary">Poslana koda tipke, ko je tipka DEL pritisnjena</string> - <string name="hostpref_encoding_title">Kodiranje</string> - <string name="hostpref_encoding_summary">Kodiranje znakov za gostitelja</string> - <string name="hostpref_connection_category">Nastavitve povezave</string> - <string name="hostpref_username_title">Uporabniško ime</string> - <string name="hostpref_hostname_title">Gostitelj</string> - <string name="hostpref_port_title">Vrata</string> - <string name="bind_never">Nikoli povezani</string> - <string name="bind_minutes">%1$s minut nazaj</string> - <string name="bind_hours">%1$s ur nazaj</string> - <string name="bind_days">%1$s dni nazaj</string> - <string name="console_menu_close">Zapri</string> - <string name="console_menu_copy">Kopiraj</string> - <string name="console_menu_paste">Prilepi</string> - <string name="console_menu_portforwards">Posredovanje vrat</string> - <string name="button_yes">Da</string> - <string name="button_no">Ne</string> - <string name="portforward_local">Krajevno</string> - <string name="portforward_remote">Oddaljeno</string> - <string name="portforward_pos">Ustvari posredovanje vrat</string> - <string name="portforward_done">Uspešno ustvarjeno posredovanje vrat</string> - <string name="portforward_menu_add">Dodaj posredovanje vrat</string> - <string name="hint_userhost">uporabnik\@gostitelj</string> - <string name="list_format_error">Uporabi vrsto %1$s</string> - <string name="format_username">Uporabniško ime</string> - <string name="format_hostname">ime gostitelja</string> - <string name="format_port">vrata</string> - <string name="list_menu_pubkeys">Upravljanje z javnimi ključi</string> - <string name="list_menu_sortcolor">Razvrsti po barvi</string> - <string name="list_menu_sortname">Razvrsti po imenu</string> - <string name="list_menu_settings">Nastavitve</string> - <string name="list_host_disconnect">Prekini povezavo</string> - <string name="list_host_edit">Urejaj gostitelja</string> - <string name="list_host_portforwards">Urejaj posredovanja vrat</string> - <string name="list_host_delete">Izbriši gostitelja</string> - <string name="list_rotation_default">Privzeto</string> - <string name="list_rotation_land">Prisili ležeče</string> - <string name="list_rotation_port">Prisili pokončno</string> - <string name="list_rotation_auto">Samodejno</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A nato Space</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Nič</string> - <string name="list_delkey_backspace">Vračalka</string> - <string name="list_delkey_del">Delete</string> - <string name="delete_message">Ali ste prepričani, da želite izbrisati \'%1$s\'?</string> - <string name="delete_pos">Da, izbriši.</string> - <string name="delete_neg">Prekliči</string> - <string name="wizard_agree">Se strinjam</string> - <string name="wizard_next">Naprej</string> - <string name="wizard_back">Nazaj</string> - <string name="terminal_no_hosts_connected">Trenutno ni noben gostitelj povezan</string> - <string name="terminal_connecting">Povezujem se na %1$s:%2$d preko %3$s</string> - <string name="terminal_sucess">Preverjen gostitelj \'%1$s\' ključ: %2$s</string> - <string name="terminal_failed">Preverjanje ključa gostitelja spodletelo.</string> - <string name="terminal_using_s2c_algorithm">Strežnik - odjemalec algoritem: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Odjemalec - strežnik algoritem: %1$s %2$s</string> - <string name="terminal_using_algorithm">Uporabljam algoritem: %1$s %2$s</string> - <string name="terminal_auth">Poskušam se overit</string> - <string name="terminal_auth_pass">Poskušam overitev z geslom</string> - <string name="terminal_auth_pass_fail">Overitev z geslom spodletela</string> - <string name="terminal_auth_pubkey_fail">Spodletela avtentikacijska metoda \'publickey\' z ključem \'%1$s\'</string> - <string name="terminal_auth_fail">[Vaš gostitelj ne podpira \'password\' ali \'keyboard-interactive\' avtentikacije.]</string> - <string name="notification_text">%1$s želi vašo pozornost.</string> - <string name="no">Ne</string> - <string name="with_confirmation">S potrditvijo</string> - <string name="yes">Da</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> - <string name="menu_colors_reset">Ponastavi</string> - <string name="app_is_running">ConnectBot je dejaven</string> - <string name="color_red">rdeča</string> - <string name="color_green">zelena</string> - <string name="color_blue">modra</string> - <string name="color_gray">siva</string> -</resources>
--- a/res/values-sv/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Enkel och kraftfull SSH-klient baserad på öppen källkod.</string> - <string name="service_desc">Upprätthåller SSH-anslutningar och laddade publika nycklar</string> - <string name="title_hosts_list">Värddatorer</string> - <string name="title_pubkey_list">Publika nycklar</string> - <string name="title_port_forwards_list">Vidarebefordring av portar</string> - <string name="title_host_editor">Redigera värddator</string> - <string name="title_help">Hjälp</string> - <string name="title_colors">Färger</string> - <string name="resolve_connect">Anslut</string> - <string name="resolve_entropy">Samla in entropi</string> - <string name="menu_insert">Lägg till värd</string> - <string name="menu_delete">Ta bort värd</string> - <string name="menu_preferences">Inställningar</string> - <string name="help_intro">Var god välj ett ämne nedan som du skulle vilja ha mer information om.</string> - <string name="help_about">Om ConnectBot</string> - <string name="help_keyboard">Tangentbord</string> - <string name="pubkey_generate">Generera</string> - <string name="pubkey_import">Importera</string> - <string name="pubkey_delete">Ta bort nyckel</string> - <string name="pubkey_gather_entropy">Samlar in entropi</string> - <string name="pubkey_touch_prompt">Rör vid rutan för att samla in slumpdata: %1$d%% klart</string> - <string name="pubkey_touch_hint">För att försäkra dig om att nyckeln som skapas är slumpmässig, rör fingret slumpmässigt över skärmen.</string> - <string name="pubkey_generating">"Genererar nyckelpar…"</string> - <string name="pubkey_copy_private">Kopiera privat nyckel</string> - <string name="pubkey_copy_public">Kopiera publik nyckel</string> - <string name="pubkey_list_empty">Tryck på Meny för att\nskapa eller importera nyckelpar</string> - <string name="pubkey_unknown_format">Okänt format</string> - <string name="pubkey_change_password">Ändra lösenord</string> - <string name="pubkey_list_pick">Välj från /sdcard</string> - <string name="pubkey_import_parse_problem">Svårigheter med att tyda den importerade privata nyckeln</string> - <string name="pubkey_unlock">Lås upp nyckel</string> - <string name="pubkey_failed_add">Felaktigt lösenord för nyckeln \'%1$s\'. Autentiseringen misslyckades.</string> - <string name="pubkey_memory_load">Ladda in i minnet</string> - <string name="pubkey_memory_unload">Ladda ur minnet</string> - <string name="pubkey_load_on_start">Ladda nyckel från start</string> - <string name="pubkey_confirm_use">Bekräfta innan användning</string> - <string name="portforward_list_empty">Rör vid Menu för att skapa\nvidarebefodringar av portar.</string> - <string name="portforward_edit">Ändra vidarebefordring av port</string> - <string name="portforward_delete">Ta bort vidarebefodring av port</string> - <string name="prompt_nickname">Namn:</string> - <string name="prompt_nickname_hint_pubkey">Min jobbnyckel</string> - <string name="prompt_source_port">Inkommande portnummer:</string> - <string name="prompt_destination">Destination:</string> - <string name="prompt_old_password">Gammalt lösenord:</string> - <string name="prompt_password">Lösenord:</string> - <string name="prompt_again">(igen)</string> - <string name="prompt_type">Typ:</string> - <string name="prompt_password_can_be_blank">Notis: lösenordet kan vara blankt</string> - <string name="prompt_bits">Bitar:</string> - <string name="prompt_pubkey_password">Lösenord för nyckel \'%1$s\'</string> - <string name="prompt_allow_agent_to_use_key">Tillåt fjärrvärd att\nanvända nyckel \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">VARNING: IDENTIFIERING AV FJÄRRVÄRD HAR ÄNDRATS!</string> - <string name="host_verification_failure_warning">MÖJLIGT INTRÅNGSFÖRSÖK!\nNågon skulle kunna avlyssna dig nu (man-in-the-middle attack)!\nDet är även möjligt att värdnyckeln just har ändrats.</string> - <string name="prompt_host_disconnected">Värden har kopplat ner anslutningen.\nStäng?</string> - <string name="prompt_continue_connecting">Är du säker att du vill\nfortsätta att ansluta?</string> - <string name="host_authenticity_warning">Identiteten av värden \'%1$s\' går ej att fastställa.</string> - <string name="host_fingerprint">Värd %1$s nyckel-fingeravtryck är %2$s</string> - <string name="alert_passwords_do_not_match_msg">Lösenorden överenstämmer inte med varandra!</string> - <string name="alert_wrong_password_msg">Felaktigt lösenord!</string> - <string name="alert_key_corrupted_msg">Privata nyckeln ser ut att vara korrupt!</string> - <string name="alert_sdcard_absent">SD-kort ej isatt!</string> - <string name="button_add">Lägg till</string> - <string name="button_change">Ändra</string> - <string name="button_generate">Generera nyckel</string> - <string name="button_resize">Ändra storlek</string> - <string name="alert_disconnect_msg">Anslutningen förlorad</string> - <string name="pref_emulation_category">Terminalemulering</string> - <string name="pref_emulation_title">Emuleringsläge</string> - <string name="pref_emulation_summary">Emuleringsläge för PTY-anslutningar</string> - <string name="pref_scrollback_title">Textbufferstorlek</string> - <string name="pref_scrollback_summary">Storlek på textbuffer för varje konsol</string> - <string name="pref_ui_category">Användargränssnitt</string> - <string name="pref_rotation_title">Rotationsläge</string> - <string name="pref_rotation_summary">Hur rotation skall ändras när tangentbord aktiveras/avaktiveras</string> - <string name="pref_fullscreen_title">Helskärm</string> - <string name="pref_fullscreen_summary">Göm status medan konsol visas</string> - <string name="pref_memkeys_title">Kom ihåg nycklar</string> - <string name="pref_memkeys_summary">Behåll olåsta nycklar i minnet tills bakände-tjänst avslutas</string> - <string name="pref_update_title">Uppdateringskontroll</string> - <string name="pref_update_summary">Intervall för att söka efter ConnectBot-uppdateringar</string> - <string name="pref_conn_persist_title">Kvarstående anslutningar</string> - <string name="pref_conn_persist_summary">Tvinga anslutningar att fortsätta i bakgrunden</string> - <string name="pref_keymode_title">Genvägar för katalog</string> - <string name="pref_keymode_summary">Välj hur Alt används för \'/\' och Shift för Tab</string> - <string name="pref_camera_title">Genväg för kamera</string> - <string name="pref_camera_summary">Välj genväg för kamera-knappen</string> - <string name="pref_keepalive_title">Håll skärmen aktiv</string> - <string name="pref_keepalive_summary">Håll skärmen aktiv medan konsolen används</string> - <string name="pref_wifilock_title">Håll trådlöst nätverk aktivt</string> - <string name="pref_wifilock_summary">Hindra att trådlöst nätverk slås av under en aktiv session</string> - <string name="pref_bumpyarrows_title">Aktiva piltangenter</string> - <string name="pref_bumpyarrows_summary">Vibrera när piltangenter sänds från pekdon; bra för långsamma anslutningar</string> - <string name="pref_bell_category">Terminal-ljud</string> - <string name="pref_bell_title">Aktivt</string> - <string name="pref_bell_volume_title">Ljudvolym</string> - <string name="pref_bell_vibrate_title">Vibrera</string> - <string name="pref_bell_notification_title">Bakgrundsmeddelanden</string> - <string name="pref_bell_notification_summary">Skicka meddelande när en terminal som körs i bakgrunden skickar ljudsignal.</string> - <string name="list_keymode_right">Använd högerknapparna</string> - <string name="list_keymode_left">Använd vänsterknapparna</string> - <string name="list_keymode_none">Avaktivera</string> - <string name="list_pubkeyids_none">Använd inte knapparna</string> - <string name="list_pubkeyids_any">Använd valfri olåst nyckel</string> - <string name="hostpref_nickname_title">Smeknamn</string> - <string name="hostpref_color_title">Färgkategori</string> - <string name="hostpref_fontsize_title">Teckenstorlek</string> - <string name="hostpref_pubkeyid_title">Använd publik nyckelverifiering</string> - <string name="hostpref_authagent_title">Använd SSH-verifieringsagent</string> - <string name="hostpref_postlogin_title">Automatisering efter inloggning</string> - <string name="hostpref_postlogin_summary">Kommandon att köras på fjärrservern när verifierad</string> - <string name="hostpref_compression_title">Kompression</string> - <string name="hostpref_compression_summary">Detta kan hjälpa på långsammare nätverk</string> - <string name="hostpref_wantsession_title">Starta shell-session</string> - <string name="hostpref_wantsession_summary">Inaktivera denna inställning för att bara använda vidarebefodring av portar</string> - <string name="hostpref_stayconnected_title">Fortsätt vara ansluten</string> - <string name="hostpref_stayconnected_summary">Försök återansluta till värden om frånkopplad</string> - <string name="hostpref_delkey_title">DEL-tangent</string> - <string name="hostpref_delkey_summary">Tangentkoden som sänds när DEL-tangenten trycks ner</string> - <string name="hostpref_encoding_title">Teckenkodning</string> - <string name="hostpref_encoding_summary">Teckenkodning för värddatorn</string> - <string name="hostpref_connection_category">Anslutningsinställningar</string> - <string name="hostpref_username_title">Användarnamn</string> - <string name="hostpref_hostname_title">Värd</string> - <string name="hostpref_port_title">Port</string> - <string name="bind_never">Aldrig ansluten</string> - <string name="bind_minutes">%1$s minuter sedan</string> - <string name="bind_hours">%1$s timmar sendan</string> - <string name="bind_days">%1$s dagar sedan</string> - <string name="console_copy_done">Kopierade %1$d bytes till urklippshanteraren.</string> - <string name="console_copy_start">Tryck och drag\neller använd bollen\nför att markera en yta för kopiering</string> - <string name="console_menu_close">Stäng</string> - <string name="console_menu_copy">Kopiera</string> - <string name="console_menu_paste">Klistra in</string> - <string name="console_menu_portforwards">Vidarebefodring av port</string> - <string name="console_menu_resize">Fast storlek</string> - <string name="console_menu_urlscan">URL-sökning</string> - <string name="button_yes">Acceptera</string> - <string name="button_no">Neka</string> - <string name="portforward_local">Lokal</string> - <string name="portforward_remote">Fjärr</string> - <string name="portforward_dynamic">Dynamisk (SOCKS)</string> - <string name="portforward_pos">Skapa vidarebefodring av port</string> - <string name="portforward_done">Vidarebefodring av port skapad.</string> - <string name="portforward_problem">Lyckades inte att skapa en vidarebefodring av port, är den under 1024 eller används den kanske?</string> - <string name="portforward_menu_add">Lägg till vidarebefodring av port.</string> - <string name="hint_userhost">användarnamn\@värdnamn</string> - <string name="list_format_error">Använd formatet %1$s</string> - <string name="format_username">användarnamn</string> - <string name="format_hostname">värdnamn</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Hantera publika nycklar</string> - <string name="list_menu_sortcolor">Sortera efter färg</string> - <string name="list_menu_sortname">Sortera efter namn</string> - <string name="list_menu_settings">Inställningar</string> - <string name="list_host_disconnect">Koppla ner</string> - <string name="list_host_edit">Inställningar för värd</string> - <string name="list_host_portforwards">Ändra vidarebefodringar av portar</string> - <string name="list_host_delete">Ta bort värd</string> - <string name="list_host_empty">Använd snabbanslutningen\nnedan för att ansluta till en värd.</string> - <string name="list_rotation_default">Förvalt värde</string> - <string name="list_rotation_land">Tvinga horisontellt läge</string> - <string name="list_rotation_port">Tvinga vertikalt läge</string> - <string name="list_rotation_auto">Automatiskt</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A sen Space</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Ingen</string> - <string name="list_delkey_backspace">Baksteg</string> - <string name="list_delkey_del">Ta bort</string> - <string name="delete_message">Är du säker att du vill ta bort \'%1$s\'?</string> - <string name="delete_pos">Ja, ta bort</string> - <string name="delete_neg">Avbryt</string> - <string name="wizard_agree">Godkänn</string> - <string name="wizard_next">Nästa</string> - <string name="wizard_back">Tillbaka</string> - <string name="terminal_no_hosts_connected">Inga värdar anslutna</string> - <string name="terminal_connecting">Ansluter till %1$s:%2$d via %3$s</string> - <string name="terminal_sucess">Verifierad värd \'%1$s\' nyckel: %2$s</string> - <string name="terminal_failed">Verifikation av värd-nyckeln misslyckades.</string> - <string name="terminal_using_s2c_algorithm">Server-till-klient algoritm: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Klient-till-server algoritm: %1$s %2$s</string> - <string name="terminal_using_algorithm">Använder algoritm: %1$s %2$s</string> - <string name="terminal_auth">Försöker att autentisera</string> - <string name="terminal_auth_pass">Försöker med \'password\' autentisering</string> - <string name="terminal_auth_pass_fail">Autentiseringsmetoden \'password\' misslyckades</string> - <string name="terminal_auth_pubkey_any">Försöker \'publik nyckel\' verifiering med en nyckel från det lokala minnet</string> - <string name="terminal_auth_pubkey_invalid">Vald publik nyckel är ogiltig, försök välj ny nyckel i värd redigerare</string> - <string name="terminal_auth_pubkey_specific">Försöker \'publik nyckel\' verifiera med en specifik publik nyckel</string> - <string name="terminal_auth_pubkey_fail">Verifierings metod \'publik nyckel\' med nyckel \'%1$s\' misslyckades</string> - <string name="terminal_auth_ki">Försöker med \'keyboard-interactive\' autentisering</string> - <string name="terminal_auth_ki_fail">Autentiseringsmetoden \'keyboard-interactive\' misslyckades</string> - <string name="terminal_auth_fail">[Din värd stödjer inte \'password\' eller \'keyboard-interactive\' autentiseringsmetoderna]</string> - <string name="terminal_no_session">Session kommer inte att startas på grund av värd önskemål.</string> - <string name="terminal_enable_portfoward">Aktivera vidarebefodring av port: %1$s</string> - <string name="local_shell_unavailable">Misslyckande! Lokal shell är otillgänglig på denna telefon</string> - <string name="notification_text">%1$s vill ha din uppmärksamhet.</string> - <string name="no">Nej</string> - <string name="with_confirmation">Med bekräftelse</string> - <string name="yes">Ja</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> - <string name="menu_colors_reset">Återställ</string> - <string name="app_is_running">ConnectBot är igång</string> - <string name="color_red">röd</string> - <string name="color_green">grön</string> - <string name="color_blue">blå</string> - <string name="color_gray">grå</string> -</resources>
--- a/res/values-tr/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,214 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Basit, güçlü, açık kaynak kodlu SSH client</string> - <string name="service_desc">SSH bağlantılarını ve yüklenmiş açık-anahtarları muhafaza eder</string> - <string name="title_hosts_list">Hostlar</string> - <string name="title_pubkey_list">Açık-anahtarlar</string> - <string name="title_port_forwards_list">Port yönlendirme</string> - <string name="title_host_editor">Host\'u Düzenle</string> - <string name="title_help">Yardım</string> - <string name="title_colors">Renkler</string> - <string name="resolve_connect">Bağlan</string> - <string name="resolve_entropy">Rastgele girdi topla</string> - <string name="menu_insert">Host ekle</string> - <string name="menu_delete">Host\'u sil</string> - <string name="menu_preferences">Seçenekler</string> - <string name="help_intro">Özel bir konu hakkinda daha fazla bilgi için lütfen aşağıdaki ilgili konuyu seçiniz.</string> - <string name="help_about">ConnectBot Hakkında</string> - <string name="help_keyboard">Klavye</string> - <string name="pubkey_generate">Oluştur</string> - <string name="pubkey_import">Harici dosyadan aktar</string> - <string name="pubkey_delete">Anahtarı Sil</string> - <string name="pubkey_gather_entropy">Entropi Toplanıyor</string> - <string name="pubkey_touch_prompt">Rastgele girdi toplamak için bu kutuya dokun: %1$d%% oluşturuldu</string> - <string name="pubkey_touch_hint">Anahtar oluşturmada gerekli rastgele girdi kaydedebilmemiz için parmağınızı aşağıdaki kutu üzerinde rastgele haraket ettiriniz.</string> - <string name="pubkey_generating">"Anahtar çifti oluşturuluyor…"</string> - <string name="pubkey_copy_private">Özel-anahtarı kopyala</string> - <string name="pubkey_copy_public">Umumi-anahtarı kopyala</string> - <string name="pubkey_list_empty">Anahtar-çiftini oluşturmak için\nveya dişardan eklemek için \"Menü\"ye dokunun.</string> - <string name="pubkey_unknown_format">Tanınmayan dosya formatı</string> - <string name="pubkey_change_password">Şifreyi değiştir</string> - <string name="pubkey_list_pick">/sdcard dan aktar</string> - <string name="pubkey_import_parse_problem">Dışardan eklenen özel-anahtarı okurken sorun oluştu</string> - <string name="pubkey_unlock">Anahtarın şifresini giriniz</string> - <string name="pubkey_failed_add">Anahtar \'%1$s\' için hatalı şifre verdiniz. Kimlik doğrulama başarısız oldu.</string> - <string name="pubkey_memory_load">Belleğe yükle</string> - <string name="pubkey_memory_unload">Bellekten kaldır</string> - <string name="pubkey_load_on_start">Başlangıçta anahtarı yükle</string> - <string name="pubkey_confirm_use">Kullanım öncesi doğrulama</string> - <string name="portforward_list_empty">Port yönlendirmesi oluşturmak için\n\"Menü\"ye dokunun</string> - <string name="portforward_edit">Port yönlendirmeyi düzenle</string> - <string name="portforward_delete">Port yönlendirmeyi sil</string> - <string name="prompt_nickname">Rumuz:</string> - <string name="prompt_nickname_hint_pubkey">Umumi-anahtar rumuzu</string> - <string name="prompt_source_port">Kaynak kapı:</string> - <string name="prompt_destination">Hedef (Anasistem:Kapı):</string> - <string name="prompt_old_password">Eski şifre:</string> - <string name="prompt_password">Şifre:</string> - <string name="prompt_again">(tekrar)</string> - <string name="prompt_type">Tip:</string> - <string name="prompt_password_can_be_blank">Not: parola boş bırakılabilir</string> - <string name="prompt_bits">İkiller:</string> - <string name="prompt_pubkey_password">Anahtar \'%1$s\' için parola</string> - <string name="prompt_allow_agent_to_use_key">Uzak anasistemin \'%1$s\' anahtarını\nkullanmasına izin ver?</string> - <string name="host_verification_failure_warning_header">UYARI: UZAK ANASİSTEM KİMLİĞİ DEĞİŞMİŞ!</string> - <string name="host_verification_failure_warning">BİRİLERİNİN KÖTÜ BİRŞEYLER YAPIYOR OLMASI OLASI!\nBirileri şu anda sizi dinliyor olabilir (aradaki adam saldırısı)!\nSadece anasistem anahtarı da değişmiş olabilir.</string> - <string name="prompt_host_disconnected">Anasistem bağlantısı kesildi.\nOturumu kapat?</string> - <string name="prompt_continue_connecting">Bağlanmaya devam etmek\nistediğinize emin misiniz?</string> - <string name="host_authenticity_warning">Anasistem \'%1$s\' in gerçekliği doğrulanamadı.</string> - <string name="host_fingerprint">Anasistem %1$s anahtar parmakizi %2$s</string> - <string name="alert_passwords_do_not_match_msg">Parolalar uyuşmuyor!</string> - <string name="alert_wrong_password_msg">Yanlış parola!</string> - <string name="alert_key_corrupted_msg">Kişisel anahtar bozuk görünüyor</string> - <string name="alert_sdcard_absent">SD kart takılmamış!</string> - <string name="button_add">Ekle</string> - <string name="button_change">Değiştir</string> - <string name="button_generate">Anahtar Üret</string> - <string name="button_resize">Yeniden boyutlandır</string> - <string name="alert_disconnect_msg">Bağlantı Kesildi</string> - <string name="pref_emulation_category">Uçbirim öykünümü</string> - <string name="pref_emulation_title">Öykünüm kipi</string> - <string name="pref_emulation_summary">PTY bağlantıları için kullanılan uçbirim öykünüm kipi</string> - <string name="pref_scrollback_title">Geri kaydırma boyu</string> - <string name="pref_scrollback_summary">Her bir konsol için bellekte tutulacak geri kaydırma arabellek boyu</string> - <string name="pref_ui_category">Kullanıcı arayüzü</string> - <string name="pref_rotation_title">Dönme kipi</string> - <string name="pref_rotation_summary">Klavye saklandığında/açıldığında dönüş nasıl değişir</string> - <string name="pref_fullscreen_title">Tüm ekran</string> - <string name="pref_fullscreen_summary">Konsolda iken durum çubuğunu gizle</string> - <string name="pref_memkeys_title">Anahtarları bellekte tut</string> - <string name="pref_memkeys_summary">Kilidi açılmış anahtarları arkadaki hizmetler sonlanana kadar bellekte tut</string> - <string name="pref_update_title">Güncellemelere bak</string> - <string name="pref_update_summary">ConnectBot güncellemelerine bakmak için en fazla sıklığı ayarla</string> - <string name="pref_conn_persist_title">Bağlantıları sürekli tut</string> - <string name="pref_conn_persist_summary">Arkaplanda iken bağlantıları bağlı tutmaya zorla</string> - <string name="pref_keymode_title">Dizin kısayolları</string> - <string name="pref_keymode_summary">\'/\' için Alt ve Tab için Shift kullanımının nasıl olacağını seç</string> - <string name="pref_camera_title">Kamera kısayolu</string> - <string name="pref_camera_summary">Kamera düğmesine basıldığında hangi kısayolun tetikleneceğini seç</string> - <string name="pref_keepalive_title">Ekranı açık tut</string> - <string name="pref_keepalive_summary">Bir konsolda çalışırken ekranın kapanmasını engelle</string> - <string name="pref_wifilock_title">Wi-Fi etkin tut</string> - <string name="pref_wifilock_summary">Bir oturum etkinken Wi-Fi kapanmasını engelle</string> - <string name="pref_bumpyarrows_title">dalgalı oklar</string> - <string name="pref_bumpyarrows_summary">Okları izotop ile kullanırken titret; düşük bağlantılar için kullanışlıdır</string> - <string name="pref_bell_category">Terminal zili</string> - <string name="pref_bell_title">Sesli zil</string> - <string name="pref_bell_volume_title">Zil ses düzeyi</string> - <string name="pref_bell_vibrate_title">Titreşim</string> - <string name="pref_bell_notification_title">Arkaplan uyarıları</string> - <string name="pref_bell_notification_summary">Arka planda çalışan terminal zil sesinde uyarı gönder</string> - <string name="list_keymode_right">Sağ taraftaki tuşları kullan</string> - <string name="list_keymode_left">Sol taraftaki tuşları kullan</string> - <string name="list_keymode_none">Devre Dışı Bırak</string> - <string name="list_pubkeyids_none">Tuşları kullanma</string> - <string name="list_pubkeyids_any">Herhangi bir tuşu kullan</string> - <string name="hostpref_nickname_title">Rumuz</string> - <string name="hostpref_color_title">Renk kategorisi</string> - <string name="hostpref_fontsize_title">Yazıtipi boyutu (pt)</string> - <string name="hostpref_pubkeyid_title">Umumi-anahtar doğrulaması yap</string> - <string name="hostpref_authagent_title">SSH auth agent teyidi kullan</string> - <string name="hostpref_postlogin_title">post-login otomasyonu</string> - <string name="hostpref_postlogin_summary">Uzak sunucuya bağlanıldığında çalıştırılacak komutlar</string> - <string name="hostpref_compression_title">Sıkıştırma</string> - <string name="hostpref_compression_summary">Yavaş ağlarda yardımcı olabilir</string> - <string name="hostpref_wantsession_title">Shell oturumu başlat</string> - <string name="hostpref_wantsession_summary">Sadece port yönlendirmeyi kullanmak için bu seçeneği boş bırakın</string> - <string name="hostpref_stayconnected_title">Bağlı kal</string> - <string name="hostpref_stayconnected_summary">Bağlantı koparsa tekrar bağlanmayı dene</string> - <string name="hostpref_delkey_title">DEL tuşu</string> - <string name="hostpref_delkey_summary">DEL yani sil tuşuna basıldığında gönderilecek key kodu</string> - <string name="hostpref_encoding_title">Dil Kodlaması</string> - <string name="hostpref_encoding_summary">Sunucu karakter kodlaması</string> - <string name="hostpref_connection_category">Bağlantı ayarları</string> - <string name="hostpref_username_title">Kullanıcı Adı</string> - <string name="hostpref_hostname_title">Sunucu</string> - <string name="hostpref_port_title">Port</string> - <string name="bind_never">Daha önce bağlanılmadı</string> - <string name="bind_minutes">%1$s dakika önce</string> - <string name="bind_hours">%1$s saat önce</string> - <string name="bind_days">%1$s gün önce</string> - <string name="console_copy_done">%1$d byte panoya kopyalandı</string> - <string name="console_copy_start">Kopyalanacak alanı seçmek için dokun ve sürükle ya da pad kullan</string> - <string name="console_menu_close">Kapat</string> - <string name="console_menu_copy">Kopyala</string> - <string name="console_menu_paste">Yapıştır</string> - <string name="console_menu_portforwards">Port Yönlendirmeleri</string> - <string name="console_menu_resize">Ebat zorunlu</string> - <string name="console_menu_urlscan">URL Tara</string> - <string name="button_yes">Evet</string> - <string name="button_no">Hayır</string> - <string name="portforward_local">Yerel</string> - <string name="portforward_remote">Uzak</string> - <string name="portforward_dynamic">Dinamik (SOCKS)</string> - <string name="portforward_pos">Port yönlendirmesi oluştur</string> - <string name="portforward_done">Port yönlendirmesi başarıyla oluşturuldu</string> - <string name="portforward_problem">Port yönlendirmesi oluşturmada hata oldu, port 1024 altı yada meşgul bir port kullanmakdan kaynaklanabilir</string> - <string name="portforward_menu_add">Port yönlendirmesi ekle</string> - <string name="hint_userhost">kullanici\@sunucuadi</string> - <string name="list_format_error">%1$s formatında kullanın</string> - <string name="format_username">kullanıcı adı</string> - <string name="format_hostname">sunucu adı</string> - <string name="format_port">port</string> - <string name="list_menu_pubkeys">Umumi-anahtarlar Yönetimi</string> - <string name="list_menu_sortcolor">Rengine göre sırala</string> - <string name="list_menu_sortname">İsime göre sırala</string> - <string name="list_menu_settings">Ayarlar</string> - <string name="list_host_disconnect">Bağlantıyı kes</string> - <string name="list_host_edit">Sunucu düzenle</string> - <string name="list_host_portforwards">Port yönlendirmeleri düzenle</string> - <string name="list_host_delete">Sunucuyu sil</string> - <string name="list_host_empty">Sunucuya bağlanmak için\naşağıdaki hızlı bağlan kutucuğunu kullan</string> - <string name="list_rotation_default">Varsayılan</string> - <string name="list_rotation_land">Yatay zorunlu</string> - <string name="list_rotation_port">Dikey zorunlu</string> - <string name="list_rotation_auto">Otomatik</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A ardından Boşluk</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">Hiçbiri</string> - <string name="list_delkey_backspace">Sil</string> - <string name="list_delkey_del">Sil</string> - <string name="delete_message">\'%1$s\' silinecek onaylıyor musunuz?</string> - <string name="delete_pos">Evet, sil</string> - <string name="delete_neg">İptal Et</string> - <string name="wizard_agree">Kabul et</string> - <string name="wizard_next">İleri</string> - <string name="wizard_back">Geri dön</string> - <string name="terminal_no_hosts_connected">Hiçbir sunucuya bağlanılmadı</string> - <string name="terminal_connecting">%3$s ile %1$s:%2$d bağlanıyor</string> - <string name="terminal_sucess">Host doğrulaması \'%1$s\' anahtar: %2$s</string> - <string name="terminal_failed">Sunucu anahtarı doğrulaması başarısız oldu</string> - <string name="terminal_using_s2c_algorithm">Server-to-client s2c algoritması: %1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">Client-to-server c2s algoritması: %1$s %2$s</string> - <string name="terminal_using_algorithm">Kullanılan algoritma: %1$s %2$s</string> - <string name="terminal_auth">Kimlik doğrulaması yapılıyor</string> - <string name="terminal_auth_pass">\'Şifre\' doğrulaması yapılıyor</string> - <string name="terminal_auth_pass_fail">Kimlik doğrulama \'şifre\' başarısız</string> - <string name="terminal_auth_pubkey_any">Bellekteki herhangi bir umumi-anahtar ile \'umumi-anahtar\' doğrulaması yapılıyor</string> - <string name="terminal_auth_pubkey_invalid">Seçilen umumi-anahtar geçersiz, host düzenleyicideki anahtarı tekrar seçerek deneyiniz</string> - <string name="terminal_auth_pubkey_specific">yerel umumi-anahtar specific public key ile \'publickey\' doğrulaması yapılıyor</string> - <string name="terminal_auth_pubkey_fail">Anahtar \'%1$s\' ile \'publickey\' doğrulama işlemi başarısız</string> - <string name="terminal_auth_ki">\'Klavyeden karşılıklı\' kimlik doğrulaması deneniyor</string> - <string name="terminal_auth_ki_fail">\'Klavyeden karşılıklı\' kimlik doğrulaması işlemi başarısız</string> - <string name="terminal_auth_fail">[Hostunuz \'şifre\' veya \'klavyeden karşılıklı\' kimlik doğrulamasını desteklemiyor.]</string> - <string name="terminal_no_session">Sunucu tercihleri sebebiyle oturum başlatılamıyor</string> - <string name="terminal_enable_portfoward">Port yönlendirmesini etkinleştir: %1$s</string> - <string name="local_shell_unavailable">Başarısız! Yerel shell bu telefonda kullanılamıyor.</string> - <string name="notification_text">%1$s sizi uyarıyor</string> - <string name="no">Hayır</string> - <string name="with_confirmation">teyitli</string> - <string name="yes">Evet</string> - <string name="exceptions_submit_message">ConnectBot son çalıştırıldığında sorunla karşılaştı. Hata raporunu ConnectBot geliştiricilerine iletmek ister misiniz?</string> - <string name="menu_colors_reset">Sıfırla</string> - <string name="app_is_running">ConnectBot çalışıyor</string> - <string name="color_red">kırmızı</string> - <string name="color_green">yeşil</string> - <string name="color_blue">mavi</string> - <string name="color_gray">gri</string> - <string name="colors_fg">ÖR:</string> - <string name="color_bg">AR:</string> - <string name="image_description_connected">Bağlandı.</string> - <string name="image_description_show_keyboard">Klavye göster.</string> -</resources>
--- a/res/values-uk/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">Простий та потужний SSH клієнт з відкритим кодом</string> - <string name="title_hosts_list">Вузли</string> - <string name="title_pubkey_list">Відкриті ключі</string> - <string name="title_port_forwards_list">Переадресація портів</string> - <string name="title_host_editor">Змінити вузол</string> - <string name="title_help">Допомога</string> - <string name="title_colors">Кольори</string> - <string name="resolve_connect">Підключитись</string> - <string name="menu_insert">Додати вузол</string> - <string name="menu_delete">Вилучити вузол</string> - <string name="menu_preferences">Налаштування</string> - <string name="help_intro">Для додаткової інформації виберіть топік</string> - <string name="help_about">Про ConnectBot</string> - <string name="help_keyboard">Клавіатура</string> - <string name="pubkey_generate">Генерувати</string> - <string name="pubkey_import">Імпортувати</string> - <string name="pubkey_delete">Вилучити ключ</string> - <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> - <string name="pubkey_change_password">Змінити пароль</string> - <string name="pubkey_list_pick">Завантажити з SD карти</string> - <string name="pubkey_unlock">Розблокувати ключ</string> - <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> -</resources>
--- a/res/values-v11/styles.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> - <style name="NoTitle" parent="android:Theme.Holo"> - <item name="android:windowContentOverlay">@null</item> - <item name="android:windowActionBarOverlay">true</item> - <item name="android:actionBarStyle">@style/SolidActionBar</item> - </style> - - <style name="SolidActionBar" parent="android:Widget.Holo.ActionBar"> - <item name="android:background">#222222</item> - </style> -</resources>
--- a/res/values-v14/styles.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> - <style name="NoTitle" parent="android:Theme.DeviceDefault"> - <item name="android:windowContentOverlay">@null</item> - <item name="android:windowActionBarOverlay">true</item> - <item name="android:actionBarStyle">@style/SolidActionBar</item> - </style> - - <style name="SolidActionBar" parent="android:Widget.Holo.ActionBar"> - <item name="android:background">#222222</item> - </style> -</resources>
--- a/res/values-vi/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="title_hosts_list">Máy chủ</string> - <string name="title_help">Trợ giúp</string> - <string name="title_colors">Màu sắc</string> - <string name="resolve_connect">Kết nối</string> - <string name="pubkey_list_empty">Tap Menu to create\nor import key pairs.</string> - <string name="portforward_list_empty">Tap Menu to create\nport forwards.</string> - <string name="list_format_error">Use the format %1$s</string> - <string name="exceptions_submit_message">It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?</string> -</resources>
--- a/res/values-zh-rCN/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">简洁、强大、开源的SSH客户端</string> - <string name="service_desc">维护SSH连接及已装载的公钥</string> - <string name="title_hosts_list">主机</string> - <string name="title_pubkey_list">公钥</string> - <string name="title_port_forwards_list">端口转发</string> - <string name="title_host_editor">编辑主机</string> - <string name="title_help">帮助</string> - <string name="title_colors">颜色</string> - <string name="resolve_connect">连接</string> - <string name="resolve_entropy">收集杂乱数</string> - <string name="menu_insert">添加主机</string> - <string name="menu_delete">删除主机</string> - <string name="menu_preferences">设置</string> - <string name="help_intro">请在下面主题中选择一个以查看更多内容</string> - <string name="help_about">关于ConnectBot</string> - <string name="help_keyboard">键盘</string> - <string name="pubkey_generate">产生</string> - <string name="pubkey_import">导入</string> - <string name="pubkey_delete">删除密钥</string> - <string name="pubkey_gather_entropy">正在收集用户熵</string> - <string name="pubkey_touch_prompt">触摸方框来收集随机数:%1$d%完成</string> - <string name="pubkey_touch_hint">请在方框内随机移动手指来生成随机密钥</string> - <string name="pubkey_generating">正在产生密钥配对</string> - <string name="pubkey_copy_private">复制私钥</string> - <string name="pubkey_copy_public">复制公钥</string> - <string name="pubkey_list_empty">点击\"菜单\"来创建或者导入密钥对</string> - <string name="pubkey_unknown_format">未知格式</string> - <string name="pubkey_change_password">更改密码</string> - <string name="pubkey_list_pick">从/sdcard导入</string> - <string name="pubkey_import_parse_problem">导入私钥的时候出现问题</string> - <string name="pubkey_unlock">解锁密钥</string> - <string name="pubkey_failed_add">验证失败,\'%1$s\'密钥密码错误</string> - <string name="pubkey_memory_load">载入到内存</string> - <string name="pubkey_memory_unload">从内存中移除</string> - <string name="pubkey_load_on_start">启动时自动载入公钥</string> - <string name="pubkey_confirm_use">使用前确认</string> - <string name="portforward_list_empty">点击「菜单」来创建端口转发</string> - <string name="portforward_edit">编辑转发端口</string> - <string name="portforward_delete">删除端口转发</string> - <string name="prompt_nickname">昵称:</string> - <string name="prompt_nickname_hint_pubkey">我的工作密钥</string> - <string name="prompt_source_port">源端口:</string> - <string name="prompt_destination">目标端口:</string> - <string name="prompt_old_password">旧密码:</string> - <string name="prompt_password">新密码:</string> - <string name="prompt_again">确认新密码</string> - <string name="prompt_type">转发类型</string> - <string name="prompt_password_can_be_blank">注意:密码可以为空</string> - <string name="prompt_bits">位数:</string> - <string name="prompt_pubkey_password">密钥「%1$s」的密码</string> - <string name="prompt_allow_agent_to_use_key">允许远程主机使用\'%1$s\'密钥?</string> - <string name="host_verification_failure_warning_header">警告:远程主机身份标识已经改变</string> - <string name="host_verification_failure_warning">可能某人正在做非善意的事情\n可能有人正在偷听你的会话(中间人攻击)\n但也许仅仅是主密匙(host key)已被更改,你确信如此?</string> - <string name="prompt_host_disconnected">主机已经断开。\n是否关闭本次对话?</string> - <string name="prompt_continue_connecting">是否要继续连接?</string> - <string name="host_authenticity_warning">主机「%1$s」的验证无法建立</string> - <string name="host_fingerprint">主机 %1$s 密钥指纹是 %2$s</string> - <string name="alert_passwords_do_not_match_msg">密码不匹配!</string> - <string name="alert_wrong_password_msg">密码错误</string> - <string name="alert_key_corrupted_msg">私钥似乎已破坏</string> - <string name="alert_sdcard_absent">没有插入SD卡!</string> - <string name="button_add">添加</string> - <string name="button_change">修改</string> - <string name="button_generate">生成密钥</string> - <string name="button_resize">改变窗口大小</string> - <string name="alert_disconnect_msg">连接中断</string> - <string name="pref_emulation_category">模拟终端</string> - <string name="pref_emulation_title">仿真模式</string> - <string name="pref_emulation_summary">设置使用PTY连接时的终端模式</string> - <string name="pref_scrollback_title">回滚长度</string> - <string name="pref_scrollback_summary">在内存中为每个控制台保留的回滚缓存长度</string> - <string name="pref_ui_category">用户界面</string> - <string name="pref_rotation_title">循环模式</string> - <string name="pref_rotation_summary">当键盘打开或关闭时屏幕如何旋转(水平或竖直)</string> - <string name="pref_fullscreen_title">全屏</string> - <string name="pref_fullscreen_summary">处于控制台时隐藏状态栏</string> - <string name="pref_memkeys_title">在内存中记录密钥</string> - <string name="pref_memkeys_summary">保留解锁的密匙于内存中直到后台服务停止</string> - <string name="pref_update_title">检查更新</string> - <string name="pref_update_summary">设置检查ConnectBot更新的最大频率</string> - <string name="pref_conn_persist_title">保持联机</string> - <string name="pref_conn_persist_summary">切换到后台时强制保持连接</string> - <string name="pref_keymode_title">目录快捷方式</string> - <string name="pref_keymode_summary">选择如何使用 Alt 代表 /,Shift 代表 Tab</string> - <string name="pref_camera_title">摄像快捷键</string> - <string name="pref_camera_summary">选择照相键按下时触发的快捷功能</string> - <string name="pref_keepalive_title">保持屏幕唤醒</string> - <string name="pref_keepalive_summary">终端运行时禁止屏幕休眠</string> - <string name="pref_wifilock_title">保持WI-FI激活</string> - <string name="pref_wifilock_summary">会话运行时禁止Wi-Fi关闭</string> - <string name="pref_bumpyarrows_title">触摸反馈</string> - <string name="pref_bumpyarrows_summary">轨迹球发出模拟方向键时振动; (对滞后连接特别有用)</string> - <string name="pref_bell_category">终端响铃</string> - <string name="pref_bell_title">响铃</string> - <string name="pref_bell_volume_title">铃声音量</string> - <string name="pref_bell_vibrate_title">响铃时振动</string> - <string name="pref_bell_notification_title">背景通知</string> - <string name="pref_bell_notification_summary">当终端在后台响铃时发出通知</string> - <string name="list_keymode_right">使用右边键盘</string> - <string name="list_keymode_left">使用左边键盘</string> - <string name="list_keymode_none">禁用</string> - <string name="list_pubkeyids_none">不使用密匙</string> - <string name="list_pubkeyids_any">使用解锁密匙</string> - <string name="hostpref_nickname_title">昵称</string> - <string name="hostpref_color_title">颜色类型</string> - <string name="hostpref_fontsize_title">字型大小 (pt)</string> - <string name="hostpref_pubkeyid_title">使用公钥验证</string> - <string name="hostpref_authagent_title">使用 SSH 认证</string> - <string name="hostpref_postlogin_title">登录后自动运行</string> - <string name="hostpref_postlogin_summary">登录后在远程服务器上自动运行命令</string> - <string name="hostpref_compression_title">压缩</string> - <string name="hostpref_compression_summary">此选项对低速网络会有帮助</string> - <string name="hostpref_wantsession_title">开始Shell会话</string> - <string name="hostpref_wantsession_summary">仅仅对端口转发禁用偏好设置</string> - <string name="hostpref_stayconnected_title">保持连接</string> - <string name="hostpref_stayconnected_summary">断线重连</string> - <string name="hostpref_delkey_title">DEL键</string> - <string name="hostpref_delkey_summary">按下DEL键时发送给服务器的键值</string> - <string name="hostpref_encoding_title">编码</string> - <string name="hostpref_encoding_summary">主机的字符编码</string> - <string name="hostpref_connection_category">连接设置</string> - <string name="hostpref_username_title">用户名</string> - <string name="hostpref_hostname_title">主机</string> - <string name="hostpref_port_title">端口</string> - <string name="bind_never">尚未连接</string> - <string name="bind_minutes">已连接 %1$s 分钟</string> - <string name="bind_hours">已连接 %1$s 小时</string> - <string name="bind_days">已连接 %1$s 天</string> - <string name="console_copy_done">已复制%1$d位</string> - <string name="console_copy_start">点击拖动\n或使用触摸板\n来选择要复制的区域</string> - <string name="console_menu_close">关闭</string> - <string name="console_menu_copy">复制</string> - <string name="console_menu_paste">粘贴</string> - <string name="console_menu_portforwards">端口转发</string> - <string name="console_menu_resize">指定大小</string> - <string name="console_menu_urlscan">URL 地址扫描</string> - <string name="button_yes">确认</string> - <string name="button_no">取消</string> - <string name="portforward_local">本地</string> - <string name="portforward_remote">远端</string> - <string name="portforward_dynamic">动态套接字(SOCKS)</string> - <string name="portforward_pos">创建端口转发</string> - <string name="portforward_done">创建端口转发成功</string> - <string name="portforward_problem">创建端口转发失败,检查你选择的端口是否小于1024或该端口已被占用</string> - <string name="portforward_menu_add">添加端口转发</string> - <string name="hint_userhost">用户名\@主机名</string> - <string name="list_format_error">使用%1$s格式</string> - <string name="format_username">用户名</string> - <string name="format_hostname">主机名</string> - <string name="format_port">端口</string> - <string name="list_menu_pubkeys">管理公钥</string> - <string name="list_menu_sortcolor">按颜色排序</string> - <string name="list_menu_sortname">按名称排序</string> - <string name="list_menu_settings">设置</string> - <string name="list_host_disconnect">断开连接</string> - <string name="list_host_edit">编辑主机</string> - <string name="list_host_portforwards">编辑端口转发</string> - <string name="list_host_delete">删除主机</string> - <string name="list_host_empty">使用下面的快速连接框连接主机</string> - <string name="list_rotation_default">默认</string> - <string name="list_rotation_land">强制横屏显示</string> - <string name="list_rotation_port">强制竖屏显示</string> - <string name="list_rotation_auto">自动</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A 然后 Space</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc 键</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">无</string> - <string name="list_delkey_backspace">退格键</string> - <string name="list_delkey_del">删除</string> - <string name="delete_message">确定要删除\'%1$s\'吗?</string> - <string name="delete_pos">是,删除</string> - <string name="delete_neg">取消</string> - <string name="wizard_agree">同意</string> - <string name="wizard_next">下一页</string> - <string name="wizard_back">返回</string> - <string name="terminal_no_hosts_connected">当前没有连接主机</string> - <string name="terminal_connecting">正在通过%3$s连接到 %1$s:%2$d</string> - <string name="terminal_sucess">验证主机 %1$s 键值: %2$s</string> - <string name="terminal_failed">主机验证失败</string> - <string name="terminal_using_s2c_algorithm">服务器到客户端算法:%1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">客户端到服务器算法:%1$s %2$s</string> - <string name="terminal_using_algorithm">使用算法:%1$s %2$s</string> - <string name="terminal_auth">尝试验证</string> - <string name="terminal_auth_pass">尝试进行用户口令认证</string> - <string name="terminal_auth_pass_fail">密码验证失败</string> - <string name="terminal_auth_pubkey_any">尝试使用保存在内存中的公匙进行用户认证</string> - <string name="terminal_auth_pubkey_invalid">所选公钥失效,请在主机中重新选择</string> - <string name="terminal_auth_pubkey_specific">正在以公钥认证方式认证所指定的公钥</string> - <string name="terminal_auth_pubkey_fail">公钥%1$s认证失败</string> - <string name="terminal_auth_ki">尝试键盘交互式认证</string> - <string name="terminal_auth_ki_fail">键盘交互式认证失败</string> - <string name="terminal_auth_fail">[该主机不支持用户口令认证或键盘交互式认证]</string> - <string name="terminal_no_session">由于主机设定不起动该会话</string> - <string name="terminal_enable_portfoward">启用端口转发:%1$s</string> - <string name="local_shell_unavailable">失败! 本地Shell在该手机上不可用</string> - <string name="notification_text">%1$s 需要你的注意</string> - <string name="no">不</string> - <string name="with_confirmation">需要确认</string> - <string name="yes">确定</string> - <string name="exceptions_submit_message">ConnectBot上次运行时出现异常, 是否提交报告至ConnectBot开发者?</string> - <string name="menu_colors_reset">重置</string> - <string name="app_is_running">ConnectBot 正在运行</string> - <string name="color_red">红色</string> - <string name="color_green">绿色</string> - <string name="color_blue">蓝色</string> - <string name="color_gray">灰色</string> - <string name="colors_fg">前景色:</string> - <string name="color_bg">背景色:</string> - <string name="image_description_connected">已连接。</string> - <string name="image_description_key_is_locked">密钥已锁。</string> - <string name="image_description_toggle_control_character">切换控制字符。</string> - <string name="image_description_send_escape_character">发送转义字符。</string> - <string name="image_description_show_keyboard">显示键盘。</string> -</resources>
--- a/res/values-zh-rHK/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources/>
--- a/res/values-zh-rTW/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,216 +0,0 @@ -<?xml version='1.0' encoding='utf-8'?> -<resources> - <string name="app_desc">簡單、強大、開放原始碼的SSH用戶端</string> - <string name="service_desc">管理SSH連線及載入公鑰</string> - <string name="title_hosts_list">主機列表</string> - <string name="title_pubkey_list">公鑰</string> - <string name="title_port_forwards_list">連接埠轉址</string> - <string name="title_host_editor">編輯主機資訊</string> - <string name="title_help">說明</string> - <string name="title_colors">顏色</string> - <string name="resolve_connect">連線</string> - <string name="resolve_entropy">收集用戶熵</string> - <string name="menu_insert">新增主機</string> - <string name="menu_delete">刪除主機</string> - <string name="menu_preferences">設定</string> - <string name="help_intro">請在下面主題中選擇一個以查看更多內容。</string> - <string name="help_about">關於ConnectBot</string> - <string name="help_keyboard">鍵盤</string> - <string name="pubkey_generate">產生</string> - <string name="pubkey_import">匯入</string> - <string name="pubkey_delete">刪除金鑰</string> - <string name="pubkey_gather_entropy">正在收集用戶熵</string> - <string name="pubkey_touch_prompt">觸摸方框來收集隨機數:%1$d%完成</string> - <string name="pubkey_touch_hint">由於金鑰產生的時候需要隨機資訊,請在下面的方框中隨意移動您的手指。</string> - <string name="pubkey_generating">正在產生金鑰對</string> - <string name="pubkey_copy_private">複製私鑰</string> - <string name="pubkey_copy_public">複製公鑰</string> - <string name="pubkey_list_empty">按「選單」鍵來建立\n或匯入金鑰對。</string> - <string name="pubkey_unknown_format">未知格式</string> - <string name="pubkey_change_password">更改密碼</string> - <string name="pubkey_list_pick">從/sdcard選擇</string> - <string name="pubkey_import_parse_problem">匯入私鑰的時候發生問題</string> - <string name="pubkey_unlock">未鎖定金鑰</string> - <string name="pubkey_failed_add">驗證失敗,錯誤的的金鑰密碼「%1$s」</string> - <string name="pubkey_memory_load">讀取到記憶體中</string> - <string name="pubkey_memory_unload">從記憶體中移除</string> - <string name="pubkey_load_on_start">在啟動的時候載入金鑰</string> - <string name="pubkey_confirm_use">使用前確認</string> - <string name="portforward_list_empty">按「選單」鍵來建立連接埠轉址</string> - <string name="portforward_edit">編輯連接埠轉址</string> - <string name="portforward_delete">刪除連接埠轉址</string> - <string name="prompt_nickname">暱稱:</string> - <string name="prompt_nickname_hint_pubkey">我的工作金鑰</string> - <string name="prompt_source_port">來源連接埠:</string> - <string name="prompt_destination">目的連接埠:</string> - <string name="prompt_old_password">舊密碼:</string> - <string name="prompt_password">密碼:</string> - <string name="prompt_again">(再輸入一遍密碼)</string> - <string name="prompt_type">轉址類型:</string> - <string name="prompt_password_can_be_blank">注意:密碼可以為空</string> - <string name="prompt_bits">位數:</string> - <string name="prompt_pubkey_password">公鑰「%1$s」的密碼</string> - <string name="prompt_allow_agent_to_use_key">允許遠端主機來\n使用金鑰 \'%1$s\'?</string> - <string name="host_verification_failure_warning_header">警告:遠端主機的鑑別已經變更!</string> - <string name="host_verification_failure_warning">可能某人正在做非善意的事情!\n可能有人正在側錄您的連線(中間攻擊法)\n但也許僅僅是主機金鑰已被變更,您確信如此?</string> - <string name="prompt_host_disconnected">主機已經中斷。\n是否關閉本次連線階段?</string> - <string name="prompt_continue_connecting">是否要繼續連線?</string> - <string name="host_authenticity_warning">主機「%1$s」的驗證無法建立</string> - <string name="host_fingerprint">主機 %1$s 金鑰指紋是 %2$s</string> - <string name="alert_passwords_do_not_match_msg">密碼不符!</string> - <string name="alert_wrong_password_msg">錯誤的密碼!</string> - <string name="alert_key_corrupted_msg">私鑰已經損壞!</string> - <string name="alert_sdcard_absent">沒有插入SD卡!</string> - <string name="button_add">新增</string> - <string name="button_change">變更</string> - <string name="button_generate">產生金鑰</string> - <string name="button_resize">調整大小</string> - <string name="alert_disconnect_msg">連線中斷</string> - <string name="pref_emulation_category">終端模擬器</string> - <string name="pref_emulation_title">終端機類型</string> - <string name="pref_emulation_summary">設置使用PTY連接時的終端模式</string> - <string name="pref_scrollback_title">回溯記憶體大小</string> - <string name="pref_scrollback_summary">在記憶體中為每個控制台保留的回溯緩衝大小</string> - <string name="pref_ui_category">使用者介面</string> - <string name="pref_rotation_title">螢幕旋轉模式</string> - <string name="pref_rotation_summary">當鍵盤視窗出現或隱藏時要如何改變螢幕顯示</string> - <string name="pref_fullscreen_title">全螢幕</string> - <string name="pref_fullscreen_summary">當在控制台時隱藏狀態列</string> - <string name="pref_memkeys_title">將金鑰儲存在記憶體</string> - <string name="pref_memkeys_summary">保持記憶體中的金鑰是解鎖狀態,直到背景服務結束</string> - <string name="pref_update_title">檢查更新</string> - <string name="pref_update_summary">將ConnectBot的檢查更新頻率設為最大</string> - <string name="pref_conn_persist_title">保持連線</string> - <string name="pref_conn_persist_summary">在背景執行時仍保持連線狀態</string> - <string name="pref_keymode_title">快捷鍵</string> - <string name="pref_keymode_summary">選擇如何使用Alt來叫出\'/\'和用Shift呼叫Tab</string> - <string name="pref_camera_title">照相快捷鍵</string> - <string name="pref_camera_summary">選擇當照相按鈕按下時將要觸發的快捷鍵</string> - <string name="pref_keepalive_title">保持螢幕亮度</string> - <string name="pref_keepalive_summary">當在執行控制台時不關閉螢幕</string> - <string name="pref_wifilock_title">保持Wi-Fi連線</string> - <string name="pref_wifilock_summary">連線階段未結束前,避免Wi-Fi關閉</string> - <string name="pref_bumpyarrows_title">觸覺方向鍵</string> - <string name="pref_bumpyarrows_summary">當用軌跡球發出模擬方向鍵時振動; 對延遲連線特別有用</string> - <string name="pref_bell_category">終端鈴聲</string> - <string name="pref_bell_title">響鈴</string> - <string name="pref_bell_volume_title">鈴聲音量</string> - <string name="pref_bell_vibrate_title">振動同時響鈴</string> - <string name="pref_bell_notification_title">背景通知</string> - <string name="pref_bell_notification_summary">當背景終端響鈴時發出通知。</string> - <string name="list_keymode_right">使用右側按鍵</string> - <string name="list_keymode_left">使用左側按鍵</string> - <string name="list_keymode_none">停用</string> - <string name="list_pubkeyids_none">不使用公鑰</string> - <string name="list_pubkeyids_any">使用解鎖金鑰</string> - <string name="hostpref_nickname_title">暱稱</string> - <string name="hostpref_color_title">顏色類型</string> - <string name="hostpref_fontsize_title">字型大小 (pt)</string> - <string name="hostpref_pubkeyid_title">使用公鑰驗證</string> - <string name="hostpref_authagent_title">使用 SSH 認證</string> - <string name="hostpref_postlogin_title">登入後自動執行</string> - <string name="hostpref_postlogin_summary">每次驗證後在遠端伺服器上執行的命令</string> - <string name="hostpref_compression_title">壓縮</string> - <string name="hostpref_compression_summary">此選項對低速網路會有幫助</string> - <string name="hostpref_wantsession_title">開始Shell連線階段</string> - <string name="hostpref_wantsession_summary">僅僅連接埠轉址停用偏好設定</string> - <string name="hostpref_stayconnected_title">保持連線</string> - <string name="hostpref_stayconnected_summary">斷線後與主機重新連線</string> - <string name="hostpref_delkey_title">DEL鍵</string> - <string name="hostpref_delkey_summary">當DEL按下時觸發的按鍵</string> - <string name="hostpref_encoding_title">編碼</string> - <string name="hostpref_encoding_summary">主機的字元編碼</string> - <string name="hostpref_connection_category">連線設定</string> - <string name="hostpref_username_title">使用者名稱</string> - <string name="hostpref_hostname_title">主機</string> - <string name="hostpref_port_title">連接埠</string> - <string name="bind_never">從未連線</string> - <string name="bind_minutes">已連接 %1$s 分鐘</string> - <string name="bind_hours">已連接 %1$s 小時</string> - <string name="bind_days">已連接 %1$s 天</string> - <string name="console_copy_done">複製 %1$d 位元組到剪貼簿</string> - <string name="console_copy_start">滑動手指\n或使用軌跡球\n選擇要複製的區域</string> - <string name="console_menu_close">關閉</string> - <string name="console_menu_copy">複製</string> - <string name="console_menu_paste">貼上</string> - <string name="console_menu_portforwards">連接埠轉址</string> - <string name="console_menu_resize">字體大小</string> - <string name="console_menu_urlscan">URL掃描</string> - <string name="button_yes">是</string> - <string name="button_no">否</string> - <string name="portforward_local">本機</string> - <string name="portforward_remote">遠端</string> - <string name="portforward_dynamic">動態(SOCKS)</string> - <string name="portforward_pos">建立連接埠轉址</string> - <string name="portforward_done">成功建立連接埠轉址</string> - <string name="portforward_problem">新增連接埠時發生問題,可能您使用1024以下的埠或是埠被佔用?</string> - <string name="portforward_menu_add">新增連接埠轉址</string> - <string name="hint_userhost">使用者名稱\@主機名稱</string> - <string name="list_format_error">使用%1$s格式</string> - <string name="format_username">使用者名稱</string> - <string name="format_hostname">主機名稱</string> - <string name="format_port">連接埠</string> - <string name="list_menu_pubkeys">管理金鑰</string> - <string name="list_menu_sortcolor">按顏色排序</string> - <string name="list_menu_sortname">按名字排序</string> - <string name="list_menu_settings">設定</string> - <string name="list_host_disconnect">中斷連線</string> - <string name="list_host_edit">編輯主機</string> - <string name="list_host_portforwards">編輯連接埠轉址</string> - <string name="list_host_delete">刪除主機</string> - <string name="list_host_empty">使用下面的快速連接框連接主機</string> - <string name="list_rotation_default">預設值</string> - <string name="list_rotation_land">強制橫屏顯示</string> - <string name="list_rotation_port">強制竪屏顯示</string> - <string name="list_rotation_auto">自動</string> - <string name="list_hwbutton_ctrlaspace">Ctrl+A 然後 Space</string> - <string name="list_hwbutton_ctrla">Ctrl+A</string> - <string name="list_hwbutton_esc">Esc</string> - <string name="list_hwbutton_esc_a">Esc+A</string> - <string name="list_hwbutton_none">無</string> - <string name="list_delkey_backspace">退格</string> - <string name="list_delkey_del">刪除</string> - <string name="delete_message">您確定要刪除 鑰 \'%1$s\'</string> - <string name="delete_pos">是,刪除</string> - <string name="delete_neg">取消</string> - <string name="wizard_agree">同意</string> - <string name="wizard_next">下一步</string> - <string name="wizard_back">返回</string> - <string name="terminal_no_hosts_connected">目前沒有已連接主機</string> - <string name="terminal_connecting">連接到 %1$s:%2$d,通過 %3$s</string> - <string name="terminal_sucess">驗證主機 \'%1$s\' 金鑰: %2$s</string> - <string name="terminal_failed">主機驗證失敗</string> - <string name="terminal_using_s2c_algorithm">伺服器到用戶端算法:%1$s %2$s</string> - <string name="terminal_using_c2s_algorithm">用戶端到伺服器算法:%1$s %2$s</string> - <string name="terminal_using_algorithm">使用演算法:%1$s %2$s</string> - <string name="terminal_auth">嘗試驗證</string> - <string name="terminal_auth_pass">嘗試 \'password\' 認證</string> - <string name="terminal_auth_pass_fail">認證方法 \'password\' 失敗</string> - <string name="terminal_auth_pubkey_any">嘗試 \'publickey\' 認證暨記憶體中任何公鑰</string> - <string name="terminal_auth_pubkey_invalid">所選擇的公鑰無法使用,請在主機編輯中嘗試重新選擇</string> - <string name="terminal_auth_pubkey_specific">嘗試 \'publickey\' 認證暨指定公鑰</string> - <string name="terminal_auth_pubkey_fail">認證方法 \'password\' 暨金鑰 \'%1$s\' 失敗</string> - <string name="terminal_auth_ki">嘗試 \'keyboard-interactive\' 認證</string> - <string name="terminal_auth_ki_fail">認證方法 \'keyboard-interactive\' 失敗</string> - <string name="terminal_auth_fail">[您的主機不支援 \'password\' 或 \'keyboard-interactive\' 驗證機制。]</string> - <string name="terminal_no_session">因為主機的相關設置,不會啓動會話。</string> - <string name="terminal_enable_portfoward">啓用連接埠轉址:%1$s</string> - <string name="local_shell_unavailable">失敗!此手機本機Shell不可用。</string> - <string name="notification_text">%1$s 需要您的注意。</string> - <string name="no">否</string> - <string name="with_confirmation">已確認過</string> - <string name="yes">是</string> - <string name="exceptions_submit_message">ConnectBot在上次執行時出現異常。請回報給ConnectBot開發者?</string> - <string name="menu_colors_reset">重設</string> - <string name="color_red">紅</string> - <string name="color_green">綠</string> - <string name="color_blue">藍</string> - <string name="color_gray">灰</string> - <string name="colors_fg">前景:</string> - <string name="color_bg">背景:</string> - <string name="image_description_connected">已連線。</string> - <string name="image_description_key_is_locked">金鑰已鎖定。</string> - <string name="image_description_toggle_control_character">切換控制字元</string> - <string name="image_description_send_escape_character">送出escape字元。</string> - <string name="image_description_show_keyboard">顯示鍵盤。</string> -</resources>
--- a/res/values/arrays.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string-array name="list_emulation_modes" translatable="false"> - <item>xterm-color</item> - <item>xterm-256color</item> - <item>xterm</item> - <item>vt100</item> - <item>ansi</item> - <item>screen</item> - </string-array> - - <string-array name="list_5250_encryption_modes" translatable="false"> - <item>NONE</item> - <item>SSLv2</item> - <item>SSLv3</item> - <item>TLS</item> - </string-array> - - <string-array name="list_rotation" translatable="false"> - <item>@string/list_rotation_default</item> - <item>@string/list_rotation_land</item> - <item>@string/list_rotation_port</item> - <item>@string/list_rotation_auto</item> - </string-array> - - <string-array name="list_rotation_values" translatable="false"> - <item>Default</item> - <item>Force landscape</item> - <item>Force portrait</item> - <item>Automatic</item> - </string-array> - - <string-array name="list_hwbutton" translatable="false"> - <item>@string/list_hwbutton_ctrl</item> - <item>@string/list_hwbutton_esc</item> - <item>@string/list_hwbutton_tab</item> - <item>@string/list_hwbutton_screen_capture</item> - <item>@string/list_hwbutton_ctrlaspace</item> - <item>@string/list_hwbutton_ctrla</item> - <item>@string/list_hwbutton_esc_a</item> - <item>@string/list_hwbutton_monitor</item> - <item>@string/list_hwbutton_soft_function_keys</item> - <item>@string/list_hwbutton_increase_fontsize</item> - <item>@string/list_hwbutton_decrease_fontsize</item> - <item>@string/list_hwbutton_none</item> - </string-array> - - <!-- must match PreferenceConstants --> - <string-array name="list_hwbutton_values" translatable="false"> - <item>CTRL</item> - <item>Esc</item> - <item>Tab</item> - <item>Screen Capture</item> - <item>Ctrl+A then Space</item> - <item>Ctrl+A</item> - <item>Esc+A</item> - <item>Monitor Key</item> - <item>Soft Function Keypad</item> - <item>Increase Font Size</item> - <item>Decrease Font Size</item> - <item>None</item> - </string-array> - - <string-array name="list_colors" translatable="false"> - <item>@string/color_red</item> - <item>@string/color_green</item> - <item>@string/color_blue</item> - <item>@string/color_gray</item> - </string-array> - - <string-array name="list_color_values" translatable="false"> - <item>red</item> - <item>green</item> - <item>blue</item> - <item>gray</item> - </string-array> - - <string-array name="list_keymode" translatable="false"> - <item>@string/list_keymode_right</item> - <item>@string/list_keymode_left</item> - <item>@string/list_keymode_none</item> - </string-array> - - <string-array name="list_keymode_values" translatable="false"> - <item>Use right-side keys</item> - <item>Use left-side keys</item> - <item>none</item> - </string-array> - - <string-array name="list_pubkeyids" translatable="false"> - <item>@string/list_pubkeyids_none</item> - <item>@string/list_pubkeyids_any</item> - </string-array> - - <string-array name="list_pubkeyids_value" translatable="false"> - <item>-2</item> - <item>-1</item> - </string-array> - - <string-array name="list_authagent" translatable="false"> - <item>@string/no</item> - <item>@string/with_confirmation</item> - <item>@string/yes</item> - </string-array> - - <string-array name="list_authagent_values" translatable="false"> - <item>no</item> - <item>confirm</item> - <item>yes</item> - </string-array> - - <string-array name="list_portforward_types" translatable="false"> - <item>@string/portforward_local</item> - <item>@string/portforward_remote</item> - <item>@string/portforward_dynamic</item> - </string-array> - - <string-array name="list_wizard_topics" translatable="false"> - <item>About</item> - <item>Hints</item> - <item>PhysicalKeyboard</item> - <item>5250Keys</item> - <item>ScreenGestures</item> - <item>VirtualKeyboard</item> - </string-array> - - <string-array name="list_delkey" translatable="false"> - <item>@string/list_delkey_del</item> - <item>@string/list_delkey_backspace</item> - </string-array> - - <string-array name="list_delkey_values" translatable="false"> - <item>del</item> - <item>backspace</item> - </string-array> - - <string-array name="file_dialog" translatable="false"> - <item>@string/pref_file_dialog_builtin</item> - <item>OI File Manager</item> - <item>AndExplorer</item> - </string-array> - - <string-array name="file_dialog_values" translatable="false"> - <item>built-in</item> - <item>OI</item> - <item>AE</item> - </string-array> - - <string-array name="list_custom_keymap" translatable="false"> - <item>@string/pref_custom_keymap_disabled</item> - <item>@string/pref_custom_keymap_full</item> - <item>ASUS Transformer Pad Series Mobile Dock</item> - <item>Samsung Captivate Glide (SGH-i927)</item> - <item>Samsung Captivate Glide (SGH-i927) ICS</item> - <item>Sony Ericsson Xperia (mini) pro</item> - </string-array> - - <string-array name="list_custom_keymap_values" translatable="false"> - <item>none</item> - <item>full</item> - <item>asus_tf</item> - <item>sgh_i927</item> - <item>sgh_i927_ics</item> - <item>se_xppro</item> - </string-array> -</resources>
--- a/res/values/notrans.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<resources> - <string name="app_name" translatable="false">510 ConnectBot</string> - <string name="copyright_info" translatable="false">Copyright © 2014 by 510 Software Group. Release under the GPLv3 or later.</string> - <string name="copyright_location" translatable="false">You can view the full text of the license at https://www.gnu.org/licenses/gpl.txt</string> -</resources>
--- a/res/values/strings.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,705 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_desc">"Simple, powerful, open-source SSH client."</string> - <string name="service_desc">"Maintains SSH connections and loaded pubkeys"</string> - <string name="auth_agent_service_desc">"Acts as an ssh-agent for other Android Apps on the device"</string> - - <string name="ssh_agent_permission_label">use SSH keys stored in your SSH Agent</string> - <string name="ssh_agent_permission_desc">Allows the application to authenticate SSH transactions using your private keys stored in ConnectBot. - VERY DANGEROUS if used by a malicious application.</string> - - <!-- Window title for the Host List --> - <string name="title_hosts_list">"Hosts"</string> - <!-- Window title for the Pubkeys List --> - <string name="title_pubkey_list">"Pubkeys"</string> - <!-- Window title for the Port Forwards List --> - <string name="title_port_forwards_list">"Port forwards"</string> - <!-- Window title when editing host details --> - <string name="title_host_editor">"Edit Host"</string> - <!-- Window title for Help index --> - <string name="title_help">"Help"</string> - <!-- Window title for color list editing screen --> - <string name="title_colors">"Colors"</string> - - <string name="resolve_connect">"Connect"</string> - <!-- Menu selection where user must move finger randomly over an area to gather entropy (collect random bits) --> - <string name="resolve_entropy">"Gather Entropy"</string> - - <string name="menu_insert">"Add Host"</string> - <string name="menu_delete">"Delete Host"</string> - <string name="menu_preferences">"Preferences"</string> - - <string name="help_intro">"Please select a topic below for more information on a particular subject."</string> - <string name="help_about">"About ConnectBot"</string> - <string name="help_keyboard">"Keyboard"</string> - - <string name="pubkey_generate">"Generate"</string> - <string name="pubkey_import">"Import"</string> - <string name="pubkey_delete">"Delete key"</string> - <!-- Dialog title when user must move finger randomly over an area to gather entropy (collect random bits) --> - <string name="pubkey_gather_entropy">"Gathering Entropy"</string> - <string name="pubkey_touch_prompt">"Touch this box to gather randomness: %1$d%% done"</string> - <string name="pubkey_touch_hint">"In order to assure randomness during the key generation, move your finger randomly over the box below."</string> - <string name="pubkey_generating">"Generating key pair…"</string> - <string name="pubkey_copy_private">"Copy private key"</string> - <string name="pubkey_copy_public">"Copy public key"</string> - <!-- Note that the '\n' just splits lines, so it's actually "create or import" --> - <string name="pubkey_list_empty">"Tap \"Menu\" to create"\n"or import key pairs."</string> - <string name="pubkey_unknown_format">"Unknown format"</string> - <string name="pubkey_change_password">"Change password"</string> - <string name="pubkey_list_pick">"Pick from /sdcard"</string> - <string name="pubkey_import_parse_problem">"Problem parsing imported private key"</string> - <string name="pubkey_unlock">"Unlock key"</string> - <string name="pubkey_failed_add">"Bad password for key '%1$s'. Authentication failed."</string> - <string name="pubkey_memory_load">"Load into memory"</string> - <string name="pubkey_memory_unload">"Unload from memory"</string> - <string name="pubkey_load_on_start">"Load key on start"</string> - <!-- Pubkey preference asking user whether the key use should be confirmed via prompt before it can be used for authentication --> - <string name="pubkey_confirm_use">"Confirm before use"</string> - - <!-- Note that the '\n' splits lines, so it's actually "create port forwards" --> - <string name="portforward_list_empty">"Tap \"Menu\" to create"\n"port forwards."</string> - <string name="portforward_edit">"Edit port forward"</string> - <string name="portforward_delete">"Delete port forward"</string> - - <string name="prompt_nickname">"Nickname:"</string> - <!-- An example string that could be used as a nickname for a pubkey. --> - <string name="prompt_nickname_hint_pubkey">"My work key"</string> - <!-- The source TCP port for port forwards. --> - <string name="prompt_source_port">"Source port:"</string> - <!-- The "host:port" combination used for port forward destinations. --> - <string name="prompt_destination">"Destination:"</string> - <string name="prompt_old_password">"Old password:"</string> - <string name="prompt_password">"Password:"</string> - <!-- Added after a "Password:" prompt to indicate user needs to confirm entry. --> - <string name="prompt_again">"(again)"</string> - <!-- Label for the user to select port forward type. --> - <string name="prompt_type">"Type:"</string> - <string name="prompt_password_can_be_blank">"Note: password can be blank"</string> - <!-- Prompt for the size of the private key in bits. --> - <string name="prompt_bits">"Bits:"</string> - - <!-- Prompt for the password to unlock a certain pubkey. --> - <string name="prompt_pubkey_password">"Password for key '%1$s'"</string> - - <!-- Prompt for whether to allow SSH Authentication Agent to use the specified key. Note that the '\n' means split the line so it's actually "host to use key" --> - <string name="prompt_allow_agent_to_use_key">"Allow remote host to"\n"use key '%1$s'?"</string> - - <!-- The header of the warning a user gets when the host key has changed. Note that this can be a very serious attack, so we try to be as "loud" to the user as possible. --> - <string name="host_verification_failure_warning_header">"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!"</string> - <!-- The body of the warning a user gets when the host key has changed. Note that this can be a very serious attack, so we try to be as "loud" to the user as possible. --> - <string name="host_verification_failure_warning">"IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"\n"Someone could be eavesdropping on you right now (man-in-the-middle attack)!"\n"It is also possible that the host key has just been changed."</string> - - <!-- Prompt user gets when the remote host has disconnected unexpectedly. --> - <string name="prompt_host_disconnected">"Host has disconnected."\n"Close session?"</string> - <!-- Prompt user must answer yes or no to when the remote host fails verification of encryption fingerprint --> - <string name="prompt_continue_connecting">"Are you sure you want"\n"to continue connecting?"</string> - - <!-- Sent to user when the remote public encryption key fingerprint doesn't match the local database --> - <string name="host_authenticity_warning">"The authenticity of host '%1$s' can't be established."</string> - <!-- First field is encryption algorithm. Second is the actual fingerprint in hex digits --> - <string name="host_fingerprint">"Host %1$s key fingerprint is %2$s"</string> - - <!-- tn5250 strings --> - <string name="host_cert_version">"Version: "</string> - <string name="host_cert_serial">"Serial Number: "</string> - <string name="host_cert_algorithm">"Signature Algorithm: "</string> - <string name="host_cert_issuer">"Issuer: "</string> - <string name="host_cert_from">"Valid From: "</string> - <string name="host_cert_to">"Valid To: "</string> - <string name="host_cert_dn">"Subject DN: "</string> - <string name="host_cert_publickey">"Public Key: "</string> - <string name="host_certificate">"The certificate is %1$s"</string> - <string name="prompt_accept_certificate">"Unknown Certificate - Do you accept it?"</string> - <string name="prompt_save_certificate">"Do you want to save this certificate?"</string> - <string name="prompt_sys_request">"Enter sys-request string"</string> - - <string name="alert_passwords_do_not_match_msg">"Passwords do not match!"</string> - <string name="alert_wrong_password_msg">"Wrong password!"</string> - <string name="alert_key_corrupted_msg">"Private key appears corrupt!"</string> - <string name="alert_sdcard_absent">"SD card is not inserted!"</string> - - <!-- Add a new item (e.g., host or pubkey) to the list. --> - <string name="button_add">"Add"</string> - <!-- Change an existing item's (e.g., host or pubkey) details. --> - <string name="button_change">"Change"</string> - <!-- Button that begins the generation of a public key pair. --> - <string name="button_generate">"Generate Key"</string> - <!-- Button that resizes the screen to the user-specified dimensions. --> - <string name="button_resize">"Resize"</string> - <!-- Button that resets to default size --> - <string name="button_resize_reset">"Default size"</string> - - <string name="alert_disconnect_msg">"Connection Lost"</string> - - - <!-- The category title for terminal emulation preferences. --> - <string name="pref_emulation_category">"Terminal emulation"</string> - - <!-- Name for the emulation terminal type preference. --> - <string name="pref_emulation_title">"Emulation mode"</string> - <!-- Description of the emulation terminal type preference. --> - <string name="pref_emulation_summary">"Terminal emulation mode to use for PTY connections"</string> - - <!-- Name for the scrollback size preference --> - <string name="pref_scrollback_title">"Scrollback size"</string> - <!-- Description of the scrollback size preference --> - <string name="pref_scrollback_summary">"Size of scrollback buffer to keep in memory for each console"</string> - - <!-- The category title for user interface preferences --> - <string name="pref_ui_category">"User interface"</string> - - <!-- Name for the rotation mode preference --> - <string name="pref_rotation_title">"Rotation mode"</string> - <!-- Summary for the rotation mode preference --> - <string name="pref_rotation_summary">"How to change rotation when keyboard popped in/out"</string> - - <!-- Name for the full screen preference --> - <string name="pref_fullscreen_title">"Full screen"</string> - <!-- Summary for the full screen preference --> - <string name="pref_fullscreen_summary">"Start terminal in full screen mode"</string> - - <!-- Name for the shifted numbers are f-keys preference --> - <string name="pref_shiftfkeys_title">"Shift+num are F-keys"</string> - <!-- Summary for the shifted numbers are f-keys preference --> - <string name="pref_shiftfkeys_summary">"On hardware keyboards, number keys send F1-F10 with shift"</string> - - <!-- Name for the ctrl'ed numbers are f-keys preference --> - <string name="pref_ctrlfkeys_title">"Ctrl+num are F-keys"</string> - <!-- Summary for the ctrl'ed numbers are f-keys preference --> - <string name="pref_ctrlfkeys_summary">"On software keyboards, number keys send F1-F10 with ctrl"</string> - - <!-- Name for the memorize keys preference --> - <string name="pref_memkeys_title">"Remember keys in memory"</string> - <!-- Summary for the memorize keys preference --> - <string name="pref_memkeys_summary">"Keep unlocked keys in memory until backend service is terminated"</string> - - <!-- Name for the update check preference --> - <string name="pref_update_title">"Update check"</string> - <!-- Summary for the update check preference --> - <string name="pref_update_summary">"Set the maximum frequency to check for ConnectBot updates"</string> - - <!-- Name for the preference that forces the service to stay running in the background.--> - <string name="pref_conn_persist_title">"Persist connections"</string> - <!-- Summary for the preference that forces the service to stay running in the background. --> - <string name="pref_conn_persist_summary">"Force connections to stay connected while in background"</string> - - <!-- Name for the keyboard shortcuts preference --> - <string name="pref_keymode_title">"Directory shortcuts"</string> - <!-- Summary for the keyboard shortcuts preference --> - <string name="pref_keymode_summary">"Select how to use Alt for '/' and Shift for Tab"</string> - - <!-- Name for the camera shortcut usage preference --> - <string name="pref_camera_title">"Camera button"</string> - <string name="pref_camera_summary">"Action triggered by pressing the camera button"</string> - - <!-- Name for the volup shortcut usage preference --> - <string name="pref_volup_title">"Volume up button"</string> - <string name="pref_volup_summary">"Action triggered by pressing the volume up button"</string> - - <!-- Name for the volup shortcut usage preference --> - <string name="pref_voldn_title">"Volume down button"</string> - <string name="pref_voldn_summary">"Action triggered by pressing the volume down button"</string> - - <!-- Name for the search shortcut usage preference --> - <string name="pref_search_title">"Search button"</string> - <string name="pref_search_summary">"Action triggered by pressing the search button"</string> - - <!-- Name for the ptt shortcut usage preference --> - <string name="pref_ptt_title">"PTT (L2) button"</string> - <string name="pref_ptt_summary">"Action triggered by pressing the ptt button"</string> - - <!-- Name for the keep screen on preference --> - <string name="pref_keepalive_title">"Keep screen awake"</string> - <!-- Summary for the camera shortcut usage preference --> - <string name="pref_keepalive_summary">"Prevent the screen from turning off when working in a console"</string> - - <!-- Name for the Wi-Fi lock preference --> - <string name="pref_wifilock_title">"Keep Wi-Fi active"</string> - <!-- Summary for the Wi-Fi lock preference --> - <string name="pref_wifilock_summary">"Prevent Wi-Fi from turning off when a session is active"</string> - - <!-- Name for the haptic feedback (bumpy arrow) preference --> - <string name="pref_bumpyarrows_title">"Bumpy arrows"</string> - <!-- Summary for the haptic feedback (bumpy arrow) preference --> - <string name="pref_bumpyarrows_summary">"Vibrate when sending arrow keys from trackball; useful for laggy connections"</string> - - <!-- Category title for the Terminal Bell preferences --> - <string name="pref_bell_category">"Terminal bell"</string> - - <!-- Checkbox preference title for the audible terminal bell feature --> - <string name="pref_bell_title">"Audible bell"</string> - - <!-- Title for the slider preference to set the volume --> - <string name="pref_bell_volume_title">"Bell volume"</string> - - <!-- Checkbox preference title for the vibrate on terminal bell feature --> - <string name="pref_bell_vibrate_title">"Vibrate on bell"</string> - - <!-- Checkbox preference title for the receive notifications on terminal bell feature --> - <string name="pref_bell_notification_title">"Background notifications"</string> - <!-- Brief summary of the feature that is enabled when the checkbox preference for the receive notifications on terminal bell feature is checked --> - <string name="pref_bell_notification_summary">"Send notification when a terminal running in the background sounds a bell."</string> - - <!-- Preference selection to indicate use of right side of keyboard for special shortcuts. --> - <string name="list_keymode_right">"Use right-side keys"</string> - <!-- Preference selection to indicate use of left side of keyboard for special shortcuts. --> - <string name="list_keymode_left">"Use left-side keys"</string> - <!-- Preference selection to indicate never to use special shortcut keys. --> - <string name="list_keymode_none">"Disable"</string> - - <!-- Preference to not use pubkeys to authenticate to this host. --> - <string name="list_pubkeyids_none">"Do not use keys"</string> - <!-- Preference to use any pubkey to authenticate to this host. --> - <string name="list_pubkeyids_any">"Use any unlocked key"</string> - - <!-- Host nickname field preference title --> - <string name="hostpref_nickname_title">"Nickname"</string> - - <!-- Host color category preference title --> - <string name="hostpref_color_title">"Color category"</string> - - <!-- Host's default font size when opening the terminal in points (pt) --> - <string name="hostpref_fontsize_title">"Font size (pt)"</string> - - <!-- Host's use fixed size --> - <string name="hostpref_fixed_size_title">"Fixed screen size"</string> - <string name="hostpref_fixed_size_summary">"Compute font size from screen size"</string> - <string name="hostpref_fixed_width_title">"Screen width (columns)"</string> - <string name="hostpref_fixed_height_title">"Screen height (rows)"</string> - - <!-- Host pubkey usage preference title --> - <string name="hostpref_pubkeyid_title">"Use pubkey authentication"</string> - - <!-- Preference title for the SSH Authentication Agent Forwarding for a host connection --> - <string name="hostpref_authagent_title">"Use SSH auth agent"</string> - - <!-- Host post-login automation preference title --> - <string name="hostpref_postlogin_title">"Post-login automation"</string> - <!-- Host post-login automation preference summary --> - <string name="hostpref_postlogin_summary">"Commands to run on remote server once authenticated"</string> - - <!-- Host compression preference title --> - <string name="hostpref_compression_title">"Compression"</string> - <!-- Summary for compression preference --> - <string name="hostpref_compression_summary">"This may help with slower networks"</string> - - <!-- HTTP Proxy preference title --> - <string name="hostpref_httpproxy_title">"Use HTTP Proxy"</string> - <!-- Summary for compression preference --> - <string name="hostpref_httpproxy_summary">"The host:port of an HTTP proxy"</string> - - <!-- Setting for whether we want a session to start up when we connect to a host --> - <string name="hostpref_wantsession_title">"Start shell session"</string> - <!-- Summary for field asking whether a shell session should be started up upon connection or not --> - <string name="hostpref_wantsession_summary">"Disable this preference to only use port forwards"</string> - - <!-- Setting for whether the host should be reconnected to automatically upon disconnect --> - <string name="hostpref_stayconnected_title">"Stay connected"</string> - <!-- Summary for preference asking whether the host should be reconnected to when it disconnects --> - <string name="hostpref_stayconnected_summary">"Try to reconnect to host if disconnected"</string> - - <!-- Setting for what key code is sent to the server when DEL key is pressed. --> - <string name="hostpref_delkey_title">"DEL Key"</string> - <!-- Summary for field asking what key code is sent to the server when DEL key is pressed. --> - <string name="hostpref_delkey_summary">"The key code sent when DEL key is pressed"</string> - - <!-- Host character encoding preference title --> - <string name="hostpref_encoding_title">"Encoding"</string> - <!-- Host character encoding preference summary --> - <string name="hostpref_encoding_summary">"Character encoding for the host"</string> - - <!-- Host preference category title for connection settings --> - <string name="hostpref_connection_category">"Connection settings"</string> - - <!-- Username field title for host editor preference --> - <string name="hostpref_username_title">"Username"</string> - - <!-- Hostname field title for host editor preference --> - <string name="hostpref_hostname_title">"Host"</string> - - <!-- Port field title for host editor preference --> - <string name="hostpref_port_title">"Port"</string> - - <!-- Monitor field title for host editor preference --> - <string name="hostpref_monitor_title">"Monitor Init String"</string> - <string name="hostpref_monitor_summary">"String to pass to the monitor process"</string> - - <!-- Override global emulation (terminal type) host editor preference --> - <string name="hostpref_emulation_title">"Emulation mode"</string> - <string name="hostpref_emulation_summary">"Override global emulation mode / answerback string"</string> - - <!-- 5250 --> - <string name="hostpref_5250_settings">"5250 Settings"</string> - <string name="hostpref_5250_encryption_title">"Host 5250 Encryption"</string> - <string name="hostpref_5250_library_title">"LIBRARY"</string> - <string name="hostpref_5250_menu_title">"MENU"</string> - <string name="hostpref_5250_program_title">"PROGRAM"</string> - - <!-- Host preference category title for x11 forwarding --> - <string name="hostpref_x11_forwarding">"X11 forwarding"</string> - - <!-- Enable x11 forwarding checkbox title for host editor preference --> - <string name="hostpref_wantx11forward_title">"Enable X11 forwarding"</string> - - <!-- Enable x11 forwarding checkbox summary for host editor preference --> - <string name="hostpref_wantx11forward_summary">"Forward X11 sessions to host and port specified below"</string> - - <!-- Hostname field title for x11 forwarding in host editor preference --> - <string name="hostpref_x11host_title">"X11 forwarding host"</string> - - <!-- Port field title for x11 forwarding in host editor preference --> - <string name="hostpref_x11port_title">"X11 forwarding port"</string> - - <!-- Displayed to indicate a host has never been connected to. --> - <string name="bind_never">"Never connected"</string> - <!-- The time that has elapsed since a host was connected to when it has been less than an hour. --> - <string name="bind_minutes">"%1$s minutes ago"</string> - <!-- The time that has elapsed since a host was connected to when it has been less than a day. --> - <string name="bind_hours">"%1$s hours ago"</string> - <!-- The time that has elapsed since a host was connected to when it has been a day or more. --> - <string name="bind_days">"%1$s days ago"</string> - - <!-- Message given when user copies from the terminal. --> - <string name="console_copy_done">"Copied %1$d bytes to clipboard"</string> - <!-- Instructions for how to copy from the terminal. The '\n' entries are to split lines to improve readability and prevent wrapping off the screen. --> - <string name="console_copy_start">"Touch and drag"\n"or use directional pad"\n"to select area to copy"</string> - - <!-- Button to close the disconnected terminal window. --> - <string name="console_menu_close">"Close"</string> - <!-- Button to begin copying from the terminal to the clipboard. --> - <string name="console_menu_copy">"Copy"</string> - <!-- Button to paste from the clipboard to the terminal. --> - <string name="console_menu_paste">"Paste"</string> - <!-- Button that brings user to the Port Forwards List. --> - <string name="console_menu_portforwards">"Port Forwards"</string> - <!-- Button that brings user to the terminal resizing dialog where they can force a size. --> - <string name="console_menu_resize">"Force Size"</string> - <!-- Button that brings up the list of URLs on the current screen --> - <string name="console_menu_urlscan">"URL Scan"</string> - <!-- Button that initiates screen capture --> - <string name="console_menu_screencapture">"Screen Capture"</string> - <!-- Button that lets user pick the file to download --> - <string name="console_menu_download">"Download File"</string> - <!-- Button that lets user pick the file to upload --> - <string name="console_menu_upload">"Upload File"</string> - - <!-- Button label to answer "Yes" to a yes/no prompt --> - <string name="button_yes">"Yes"</string> - <!-- Button label to answer "No" to a yes/no prompt --> - <string name="button_no">"No"</string> - - <!-- Selection for a "local" port forward. E.g., connections to a port listening locally is forwarded to the remote end's listening port. --> - <string name="portforward_local">"Local"</string> - <!-- Selection for a "remote" port forward. E.g., connections to a port listening remotely is forwarded to the local end's listening port. --> - <string name="portforward_remote">"Remote"</string> - <!-- Selection for a "dynamic" port forward. E.g., connections to a port listening locally is forwarded based on the SOCKS protocol to an arbitrary remote host and port. --> - <string name="portforward_dynamic">"Dynamic (SOCKS)"</string> - <!-- Button that commits the port forward to be made from the Port Forward Creation dialog. --> - <string name="portforward_pos">"Create port forward"</string> - - <string name="portforward_done">"Successfully created port forward"</string> - <string name="portforward_problem">"Problem creating port forward, maybe you're using ports under 1024 or port is already used?"</string> - - <string name="portforward_menu_add">"Add port forward"</string> - - <!-- The string to present in the quick-connect box to hint the user to the format for connecting to hosts. --> - <string name="hint_userhost">"user@hostname"</string> - - <!-- Hint given to user when the format they're using is incorrect in the quick-connect box. --> - <string name="list_format_error">"Use the format \"%1$s\""</string> - - <!-- Part of the formatting hints that will be used like: username@hostname:port --> - <string name="format_username">"user"</string> - <!-- Part of the formatting hints that will be used like: username@hostname:port --> - <string name="format_hostname">"host"</string> - <!-- Part of the formatting hints that will be used like: username@hostname:port --> - <string name="format_port">"port"</string> - - <string name="list_menu_pubkeys">"Manage Pubkeys"</string> - <!-- Selection choice to sort hosts by color. --> - <string name="list_menu_sortcolor">"Sort by color"</string> - <!-- Selection choice to sort hosts by nickname. --> - <string name="list_menu_sortname">"Sort by name"</string> - <string name="list_menu_settings">"Settings"</string> - - <string name="list_host_disconnect">"Disconnect"</string> - <string name="list_host_edit">"Edit host"</string> - <string name="list_host_portforwards">"Edit port forwards"</string> - <string name="list_host_delete">"Delete host"</string> - <!-- Note that the '\n' splits the lines so it's actually "quick-connect box below to connect" --> - <string name="list_host_empty">"Use the quick-connect box"\n"below to connect to a host."</string> - - <!-- Default screen rotation preference selection --> - <string name="list_rotation_default">"Default"</string> - <string name="list_rotation_land">"Force landscape"</string> - <string name="list_rotation_port">"Force portrait"</string> - <!-- Selection to indicate the rotation should be selected automatically based on the tilt sensor. --> - <string name="list_rotation_auto">"Automatic"</string> - - <!-- Selection to indicate pressing a hardware button should send Ctrl. --> - <string name="list_hwbutton_ctrl">"CTRL"</string> - <!-- Selection to indicate pressing a hardware button should send Esc. --> - <string name="list_hwbutton_esc">"Esc"</string> - <!-- Selection to indicate pressing a hardware button should send a Tab. --> - <string name="list_hwbutton_tab">"Tab"</string> - <!-- Selection to indicate pressing a hardware button should do a screen capture. --> - <string name="list_hwbutton_screen_capture">"Screen Capture"</string> - <!-- Selection to indicate pressing a hardware button should send "Ctrl then Space". --> - <string name="list_hwbutton_ctrlaspace">"Ctrl+A then Space"</string> - <!-- Selection to indicate pressing a hardware button should send "Ctrl+A". --> - <string name="list_hwbutton_ctrla">"Ctrl+A"</string> - <!-- Selection to indicate pressing a hardware button should send "Esc+A". --> - <string name="list_hwbutton_esc_a">"Esc+A"</string> - <!-- Selection to indicate pressing a hardware button should notify the monitor. --> - <string name="list_hwbutton_monitor">"Monitor Key"</string> - <!-- Selection to indicate pressing a hardware button should bring up the soft function key pad. --> - <string name="list_hwbutton_soft_function_keys">"Soft Function Keypad"</string> - <!-- Selection to indicate pressing a hardware button should increase font size. --> - <string name="list_hwbutton_increase_fontsize">"Increase Font Size"</string> - <!-- Selection to indicate pressing a hardware button should decrease font size. --> - <string name="list_hwbutton_decrease_fontsize">"Decrease Font Size"</string> - <!-- Selection to indicate pressing a hardware button should send nothing at all. --> - <string name="list_hwbutton_none">"None"</string> - - <!-- Name for the backspace character --> - <string name="list_delkey_backspace">"Backspace"</string> - <!-- Name for the ASCII DEL character --> - <string name="list_delkey_del">"Delete"</string> - - <string name="delete_message">"Are you sure you want to delete '%1$s'?"</string> - <string name="delete_pos">"Yes, delete"</string> - <string name="delete_neg">"Cancel"</string> - - <!-- Button to agree to license terms. --> - <string name="wizard_agree">"Agree"</string> - <!-- Button to go to the next page in the first time start-up wizard. --> - <string name="wizard_next">"Next"</string> - <!-- Button to go to the previous page in the first time start-up wizard. --> - <string name="wizard_back">"Back"</string> - - <string name="terminal_no_hosts_connected">"No hosts currently connected"</string> - - <!-- Displayed in terminal when attempting to connect to a host. The first two - variables are host:port and the third is the protocol (e.g., SSH) --> - <string name="terminal_connecting">"Connecting to %1$s:%2$d via %3$s"</string> - - <!-- Displays the host key to the user in the terminal --> - <string name="terminal_sucess">"Verified host '%1$s' key: %2$s"</string> - <string name="terminal_failed">"Host key verification failed."</string> - - <!-- Displayed on the terminal describing the cryptographic algorithm names --> - <string name="terminal_using_s2c_algorithm">"Server-to-client algorithm: %1$s %2$s"</string> - <!-- Displayed on the terminal describing the cryptographic algorithm names --> - <string name="terminal_using_c2s_algorithm">"Client-to-server algorithm: %1$s %2$s"</string> - <!-- Displayed on the terminal describing the cryptographic algorithm names --> - <string name="terminal_using_algorithm">"Using algorithm: %1$s %2$s"</string> - - <string name="terminal_auth">"Trying to authenticate"</string> - - <string name="terminal_auth_pass">"Attempting 'password' authentication"</string> - <string name="terminal_auth_pass_fail">"Authentication method 'password' failed"</string> - - <string name="terminal_auth_pubkey_any">"Attempting 'publickey' authentication with any in-memory public keys"</string> - <string name="terminal_auth_pubkey_invalid">"Selected public key is invalid, try reselecting key in host editor"</string> - <string name="terminal_auth_pubkey_specific">"Attempting 'publickey' authentication with a specific public key"</string> - <string name="terminal_auth_pubkey_fail">"Authentication method 'publickey' with key '%1$s' failed"</string> - - <string name="terminal_auth_ki">"Attempting 'keyboard-interactive' authentication"</string> - <string name="terminal_auth_ki_fail">"Authentication method 'keyboard-interactive' failed"</string> - - <string name="terminal_auth_fail">"[Your host doesn't support 'password' or 'keyboard-interactive' authentication.]"</string> - - <string name="terminal_no_session">"Session will not be started due to host preference."</string> - <string name="terminal_enable_portfoward">"Enable port forward: %1$s"</string> - - <string name="local_shell_unavailable">"Failure! Local shell is unavailable on this device."</string> - - <!-- Text sent to the user to alert them that a Terminal Bell is received in a background session --> - <string name="notification_text">"%1$s wants your attention."</string> - - <!-- Preference selection for SSH Authentication Agent to never use pubkeys --> - <string name="no">"No"</string> - <!-- Preference selection for SSH Authentication Agent to be able to use pubkeys "with confirmation" only --> - <string name="with_confirmation">"With confirmation"</string> - <!-- Preference selection for SSH Authentication Agent to be able to use pubkeys --> - <string name="yes">"Yes"</string> - - <!-- String displayed to user when they're asked to submit exceptions to the ConnectBot developers --> - <string name="exceptions_submit_message">"It appears ConnectBot had a problem last time it ran. Submit error report to ConnectBot developers?"</string> - - <!-- Menu selection to reset colors to their defaults. --> - <string name="menu_colors_reset">"Reset"</string> - - <!-- Displayed in the notification bar that connections are active --> - <string name="app_is_running">"510 ConnectBot is running"</string> - - <string name="color_red">"red"</string> - <string name="color_green">"green"</string> - <string name="color_blue">"blue"</string> - <string name="color_gray">"gray"</string> - - <!-- Very short label indicating the thing next to it is "foreground color." --> - <string name="colors_fg">"FG":</string> - - <!-- Very short label indicating the thing next to it is "background color." --> - <string name="color_bg">"BG:"</string> - - <!-- Describes the image of the "connected to host" icon for accessibility purposes. --> - <string name="image_description_connected">"Connected."</string> - - <!-- Describes the icon of the "locked pubkey" icon for accessibility purposes. --> - <string name="image_description_key_is_locked">"Key is locked."</string> - - <!-- Describes the icon of the "send control character" button in the terminal view for - accessibility purposes. --> - <string name="image_description_toggle_control_character">Toggle control character.</string> - - <!-- Describes the icon of the "send escape character" button in the terminal view for - accessibility purposes. --> - <string name="image_description_send_escape_character">Send escape character.</string> - - <!-- Describes the icon of the "show keyboard" button in the terminal view for accessibility - purposes. --> - <string name="image_description_show_keyboard">Show keyboard.</string> - - <!-- Describes the icon of the "line input" button in the terminal view for accessibility - purposes --> - <string name="image_description_line_input">Single line input</string> - - <!-- Describes the icon of the "sym" button in the terminal view for accessibility - purposes --> - <string name="image_description_sym">Character picker window</string> - - <string name="button_close">Close</string> - - <!-- Keyboard customization --> - <string name="pref_custom_keymap_title">Custom Keymap</string> - <string name="pref_custom_keymap_summary">Remapping of certain keys on supported devices</string> - <string name="pref_custom_keymap_full">Full hardware keyboard</string> - <string name="pref_custom_keymap_disabled">disabled</string> - - <string name="resize_error_title">Error resizing screen</string> - <string name="resize_error_width_height">Width and height must be higher than 0</string> - <string name="dia_resize_x">x</string> - - <!-- Screen capture --> - <string name="pref_screen_capture_category">Screen Capture</string> - <string name="pref_screen_capture_folder">Screen capture path</string> - <string name="pref_screen_capture_folder_summary">Folder to save screen capture files</string> - <string name="pref_screen_capture_popup">Screen capture report</string> - <string name="pref_screen_capture_popup_summary">Display a pop-up window on successful screen capture</string> - <string name="screen_capture">Screen Capture</string> - <string name="screenshot_success_title">Screenshot successful</string> - <string name="screenshot_saved_as">Screenshot saved as</string> - <string name="screenshot_error_title">Error creating screenshot</string> - <string name="screenshot_not_saved_as">Could not save screenshot as</string> - - <!-- Character picker (Sym) dialog --> - <string name="pref_picker_string">Sym window contents</string> - <string name="pref_picker_string_summary">String of characters for the character picker dialog</string> - <string name="pref_picker_keep_open">Leave Sym window open</string> - <string name="pref_picker_keep_open_summary">Only the cancel button closes the picker dialog</string> - - <!-- File Dialog --> - <string name="pref_file_transfer_category">File Transfer</string> - <string name="pref_file_dialog_title">File selection</string> - <string name="pref_file_dialog_summary">Dialog for choosing files and directories</string> - <string name="pref_file_dialog_builtin">built-in</string> - <string name="error_starting_app">Error starting %1$s</string> - <string name="file_chooser_select_file">Select file %1$s</string> - <string name="select_for_download">for download</string> - <string name="select_for_upload">for upload</string> - <string name="select_for_key_import">for key import</string> - - <!-- com.lamerman.FileExplorer --> - <string name="location">Location</string> - <string name="cant_read_folder">Error reading folder.</string> - <string name="nnew">New</string> - <string name="select">Select</string> - <string name="file_name">File name:</string> - <string name="cancel">Cancel</string> - <string name="new_file">New file</string> - <string name="save">Save</string> - <string name="no_data">No Data</string> - <color name="gray">#ffff0000</color> - - <!-- File Transfer --> - <string name="pref_download_folder">Download folder</string> - <string name="pref_download_folder_summary">Path to save downloaded files</string> - <string name="pref_remote_upload_folder">Remote upload folder</string> - <string name="pref_remote_upload_folder_summary">Remote path to save uploaded files</string> - <string name="pref_upload_dest_prompt">Upload target prompt</string> - <string name="pref_upload_dest_prompt_summary">Prompt for remote destination of file uploads</string> - <string name="pref_background_file_transfer">Background file transfer</string> - <string name="pref_background_file_transfer_summary">Perform file downloads and uploads in background</string> - <string name="transfer_downloading">"Downloading file…"</string> - <string name="transfer_downloading_file">Downloading file: %1$s</string> - <string name="transfer_download_complete">Download complete</string> - <string name="transfer_download_failed">Error downloading file(s):%1$s</string> - <string name="transfer_select_remote_download_title">Download file(s)</string> - <string name="transfer_select_remote_download_desc">Enter paths of the remote files to download (one per line)</string> - <string name="transfer_select_remote_upload_dest_title">Upload destination</string> - <string name="transfer_select_remote_upload_dest_desc">Enter remote file name for:</string> - <string name="transfer_button_download">Download</string> - <string name="transfer_button_upload">Upload</string> - <string name="transfer_uploading">"Uploading file…"</string> - <string name="transfer_uploading_file">Uploading file: %1$s</string> - <string name="transfer_upload_complete">Upload complete</string> - <string name="transfer_upload_failed">Error uploading file(s):%1$s</string> - - <!-- Key export --> - <string name="pubkey_export_private">"Export private key"</string> - <string name="pubkey_export_public">"Export public key"</string> - <string name="pubkey_public_save_as">Save public key</string> - <string name="pubkey_public_save_as_desc">File name (full path) to save the public key</string> - <string name="pubkey_private_save_as">Save private key</string> - <string name="pubkey_private_save_as_desc">File name (full path) to save the private key</string> - <string name="pubkey_public_export_success">Public key saved as %1$s</string> - <string name="pubkey_public_export_problem">Error exporting public key</string> - <string name="pubkey_private_export_success">Private key saved as %1$s</string> - <string name="pubkey_private_export_problem">Error exporting private key</string> - - <!-- Debug --> - <string name="pref_debug_category">Debug settings</string> - <string name="pref_debug_keycodes">Print keycodes</string> - <string name="pref_debug_keycodes_summary">Print codes of keys pressed in terminal window</string> - <string name="keycode_pressed">Code of pressed key</string> - - <!-- Long Press Menu --> - <string name="pref_extended_longpress">Extended longpress menu</string> - <string name="pref_extended_longpress_summary">Show input dialogs in tap-and-hold menu</string> - <string name="longpress_select_action">Select Action</string> - <string name="longpress_enable_full_screen_mode">Enable full screen mode</string> - <string name="longpress_disable_full_screen_mode">Disable full screen mode</string> - <string name="longpress_change_font_size">Change font size</string> - <string name="longpress_arrows_dialog">Arrow keys</string> - <string name="longpress_fkeys_dialog">Function keys</string> - <string name="longpress_ctrl_dialog">CTRL+?</string> - <string name="longpress_sym_dialog">Character picker</string> - - <!-- Ctrl picker dialog --> - <string name="pref_ctrl_string">Ctrl window contents</string> - <string name="pref_ctrl_string_summary">String of characters for the CTRL+? combination</string> - - <string name="fullscreen">Fullscreen</string> -</resources>
--- a/res/values/styles.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> -<resources> - <style name="NoTitle" parent="android:Theme"> - <item name="android:windowNoTitle">true</item> - <item name="android:windowContentOverlay">@null</item> - </style> -</resources>
--- a/res/xml/host_prefs.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,214 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> - - <EditTextPreference - android:key="nickname" - android:title="@string/hostpref_nickname_title" - android:singleLine="true" - /> - - <ListPreference - android:key="color" - android:title="@string/hostpref_color_title" - android:entries="@array/list_colors" - android:entryValues="@array/list_color_values" - /> - - <EditTextPreference - android:key="fontsize" - android:title="@string/hostpref_fontsize_title" - android:inputType="number" - android:singleLine="true" - /> - - <CheckBoxPreference - android:key="fixed_size" - android:title="@string/hostpref_fixed_size_title" - android:summary="@string/hostpref_fixed_size_summary" - /> - - <EditTextPreference - android:key="fixed_width" - android:title="@string/hostpref_fixed_width_title" - android:defaultValue="80" - android:numeric="integer" - /> - - <EditTextPreference - android:key="fixed_height" - android:title="@string/hostpref_fixed_height_title" - android:defaultValue="25" - android:numeric="integer" - /> - - <ListPreference - android:key="pubkeyid" - android:title="@string/hostpref_pubkeyid_title" - android:entries="@array/list_pubkeyids" - android:entryValues="@array/list_pubkeyids_value" - /> - - <ListPreference - android:key="useauthagent" - android:title="@string/hostpref_authagent_title" - android:entries="@array/list_authagent" - android:entryValues="@array/list_authagent_values" - /> - - <EditTextPreference - android:key="postlogin" - android:title="@string/hostpref_postlogin_title" - android:summary="@string/hostpref_postlogin_summary" - /> - - <CheckBoxPreference - android:key="compression" - android:title="@string/hostpref_compression_title" - android:summary="@string/hostpref_compression_summary" - /> - - <EditTextPreference - android:key="httpproxy" - android:title="@string/hostpref_httpproxy_title" - android:summary="@string/hostpref_httpproxy_summary" - android:inputType="textUri" - /> - - <CheckBoxPreference - android:key="wantsession" - android:title="@string/hostpref_wantsession_title" - android:summary="@string/hostpref_wantsession_summary" - /> - - <CheckBoxPreference - android:key="stayconnected" - android:title="@string/hostpref_stayconnected_title" - android:summary="@string/hostpref_stayconnected_summary" - /> - - <ListPreference - android:key="delkey" - android:title="@string/hostpref_delkey_title" - android:summary="@string/hostpref_delkey_summary" - android:entries="@array/list_delkey" - android:entryValues="@array/list_delkey_values" - /> - - <ListPreference - android:key="encoding" - android:title="@string/hostpref_encoding_title" - android:summary="@string/hostpref_encoding_summary" - /> - - <PreferenceCategory - android:title="@string/hostpref_connection_category"> - - <EditTextPreference - android:key="username" - android:title="@string/hostpref_username_title" - android:singleLine="true" - /> - - <EditTextPreference - android:key="hostname" - android:title="@string/hostpref_hostname_title" - android:singleLine="true" - /> - - <EditTextPreference - android:key="port" - android:title="@string/hostpref_port_title" - android:numeric="integer" - /> - - <EditTextPreference - android:key="monitor" - android:title="@string/hostpref_monitor_title" - android:summary="@string/hostpref_monitor_summary" - android:singleLine="true" - /> - - <EditTextPreference - android:key="emulation" - android:title="@string/hostpref_emulation_title" - android:summary="@string/hostpref_emulation_summary" - android:singleLine="true" - /> - </PreferenceCategory> - - - <PreferenceCategory - android:key="5250" - android:title="@string/hostpref_5250_settings"> - - <ListPreference - android:key="encryption5250" - android:title="@string/hostpref_5250_encryption_title" - android:entries="@array/list_5250_encryption_modes" - android:entryValues="@array/list_5250_encryption_modes" - /> - - <EditTextPreference - android:key="library5250" - android:title="@string/hostpref_5250_library_title" - android:singleLine="true" - /> - - <EditTextPreference - android:key="menu5250" - android:title="@string/hostpref_5250_menu_title" - android:singleLine="true" - /> - - <EditTextPreference - android:key="program5250" - android:title="@string/hostpref_5250_program_title" - android:singleLine="true" - /> - </PreferenceCategory> - - - <PreferenceCategory - android:key="x11" - android:title="@string/hostpref_x11_forwarding"> - - <CheckBoxPreference - android:key="wantx11forward" - android:title="@string/hostpref_wantx11forward_title" - android:summary="@string/hostpref_wantx11forward_summary" - /> - - <EditTextPreference - android:key="x11host" - android:title="@string/hostpref_x11host_title" - android:singleLine="true" - /> - - <EditTextPreference - android:key="x11port" - android:title="@string/hostpref_x11port_title" - android:numeric="integer" - /> - - </PreferenceCategory> - -</PreferenceScreen>
--- a/res/xml/preferences.xml Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,302 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ ---> - -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> - - <CheckBoxPreference - android:key="memkeys" - android:title="@string/pref_memkeys_title" - android:summary="@string/pref_memkeys_summary" - android:defaultValue="true" - /> - - <CheckBoxPreference - android:key="connPersist" - android:title="@string/pref_conn_persist_title" - android:summary="@string/pref_conn_persist_summary" - android:defaultValue="true" - /> - - <PreferenceCategory - android:title="@string/pref_emulation_category"> - - <ListPreference - android:key="emulation" - android:title="@string/pref_emulation_title" - android:summary="@string/pref_emulation_summary" - android:entries="@array/list_emulation_modes" - android:entryValues="@array/list_emulation_modes" - android:defaultValue="xterm-256color" - /> - - <EditTextPreference - android:key="scrollback" - android:title="@string/pref_scrollback_title" - android:summary="@string/pref_scrollback_summary" - android:defaultValue="140" - android:numeric="integer" - /> - - </PreferenceCategory> - - <PreferenceCategory - android:key="category_ui" - android:title="@string/pref_ui_category"> - - <ListPreference - android:key="rotation" - android:title="@string/pref_rotation_title" - android:summary="@string/pref_rotation_summary" - android:entries="@array/list_rotation" - android:entryValues="@array/list_rotation_values" - android:defaultValue="Default" - /> - - <CheckBoxPreference - android:key="shiftfkeys" - android:title="@string/pref_shiftfkeys_title" - android:summary="@string/pref_shiftfkeys_summary" - android:defaultValue="false" - /> - - <CheckBoxPreference - android:key="ctrlfkeys" - android:title="@string/pref_ctrlfkeys_title" - android:summary="@string/pref_ctrlfkeys_summary" - android:defaultValue="false" - /> - - <ListPreference - android:key="keymode" - android:title="@string/pref_keymode_title" - android:summary="@string/pref_keymode_summary" - android:entries="@array/list_keymode" - android:entryValues="@array/list_keymode_values" - android:defaultValue="Use right-side keys" - /> - - <ListPreference - android:key="camera" - android:title="@string/pref_camera_title" - android:summary="@string/pref_camera_summary" - android:entries="@array/list_hwbutton" - android:entryValues="@array/list_hwbutton_values" - android:defaultValue="Screen Capture" - /> - - <ListPreference - android:key="volup" - android:title="@string/pref_volup_title" - android:summary="@string/pref_volup_summary" - android:entries="@array/list_hwbutton" - android:entryValues="@array/list_hwbutton_values" - android:defaultValue="Soft Function Keypad" - /> - - <ListPreference - android:key="voldn" - android:title="@string/pref_voldn_title" - android:summary="@string/pref_voldn_summary" - android:entries="@array/list_hwbutton" - android:entryValues="@array/list_hwbutton_values" - android:defaultValue="Tab" - /> - - <ListPreference - android:key="search" - android:title="@string/pref_search_title" - android:summary="@string/pref_search_summary" - android:entries="@array/list_hwbutton" - android:entryValues="@array/list_hwbutton_values" - android:defaultValue="Esc" - /> - - <ListPreference - android:key="ptt" - android:title="@string/pref_ptt_title" - android:summary="@string/pref_ptt_summary" - android:entries="@array/list_hwbutton" - android:entryValues="@array/list_hwbutton_values" - android:defaultValue="Monitor Key" - /> - - <CheckBoxPreference - android:key="keepalive" - android:title="@string/pref_keepalive_title" - android:summary="@string/pref_keepalive_summary" - android:defaultValue="true" - /> - - <CheckBoxPreference - android:key="wifilock" - android:title="@string/pref_wifilock_title" - android:summary="@string/pref_wifilock_summary" - android:defaultValue="true" - /> - - <CheckBoxPreference - android:key="bumpyarrows" - android:title="@string/pref_bumpyarrows_title" - android:summary="@string/pref_bumpyarrows_summary" - android:defaultValue="true" - /> - - <CheckBoxPreference - android:key="extended_longpress" - android:title="@string/pref_extended_longpress" - android:summary="@string/pref_extended_longpress_summary" - android:defaultValue="false" - /> - - <EditTextPreference - android:key="ctrl_string" - android:title="@string/pref_ctrl_string" - android:summary="@string/pref_ctrl_string_summary" - android:defaultValue="ABCDEKLOQRWSTUXZ" - android:singleLine="true" - /> - - <EditTextPreference - android:key="picker_string" - android:title="@string/pref_picker_string" - android:summary="@string/pref_picker_string_summary" - android:defaultValue="~\\^()[]{}<>|/:_;,.!@#$%&*?\"'-+=" - android:singleLine="true" - /> - - <CheckBoxPreference - android:key="picker_keep_open" - android:title="@string/pref_picker_keep_open" - android:summary="@string/pref_picker_keep_open_summary" - android:defaultValue="false" - /> - - <ListPreference - android:key="list_custom_keymap" - android:title="@string/pref_custom_keymap_title" - android:summary="@string/pref_custom_keymap_summary" - android:entries="@array/list_custom_keymap" - android:entryValues="@array/list_custom_keymap_values" - android:defaultValue="none" - /> - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/pref_bell_category"> - - <CheckBoxPreference - android:key="bell" - android:title="@string/pref_bell_title" - android:defaultValue="true" - /> - - <com.five_ten_sg.connectbot.util.VolumePreference - android:key="bellVolume" - android:title="@string/pref_bell_volume_title" - /> - - <CheckBoxPreference - android:key="bellVibrate" - android:title="@string/pref_bell_vibrate_title" - android:defaultValue="true" - /> - - <CheckBoxPreference - android:key="bellNotification" - android:title="@string/pref_bell_notification_title" - android:summary="@string/pref_bell_notification_summary" - android:defaultValue="false" - /> - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/pref_screen_capture_category"> - - <EditTextPreference - android:key="screen_capture_folder" - android:title="@string/pref_screen_capture_folder" - android:summary="@string/pref_screen_capture_folder_summary" - android:inputType="text" - android:singleLine="true" - /> - - <CheckBoxPreference - android:key="screen_capture_popup" - android:title="@string/pref_screen_capture_popup" - android:summary="@string/pref_screen_capture_popup_summary" - android:defaultValue="true" - /> - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/pref_file_transfer_category"> - - <ListPreference - android:key="file_dialog" - android:title="@string/pref_file_dialog_title" - android:summary="@string/pref_file_dialog_summary" - android:entries="@array/file_dialog" - android:entryValues="@array/file_dialog_values" - android:defaultValue="built-in" - /> - - <EditTextPreference - android:key="download_folder" - android:title="@string/pref_download_folder" - android:summary="@string/pref_download_folder_summary" - android:inputType="text" - android:singleLine="true" - /> - - <EditTextPreference - android:key="remote_upload_folder" - android:title="@string/pref_remote_upload_folder" - android:summary="@string/pref_remote_upload_folder_summary" - android:inputType="text" - android:singleLine="true" - android:defaultValue="" - /> - - <CheckBoxPreference - android:key="upload_dest_prompt" - android:title="@string/pref_upload_dest_prompt" - android:summary="@string/pref_upload_dest_prompt_summary" - android:defaultValue="true" - /> - - <CheckBoxPreference - android:key="background_file_transfer" - android:title="@string/pref_background_file_transfer" - android:summary="@string/pref_background_file_transfer_summary" - android:defaultValue="true" - /> - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/pref_debug_category"> - - <CheckBoxPreference - android:key="debug_keycodes" - android:title="@string/pref_debug_keycodes" - android:summary="@string/pref_debug_keycodes_summary" - android:defaultValue="false" - /> - </PreferenceCategory> -</PreferenceScreen>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/settings.gradle Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,1 @@ +include ':app'
--- a/src/ch/ethz/ssh2/AbstractSFTPClient.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,690 +0,0 @@ -package ch.ethz.ssh2; - -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.SocketException; -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; -import java.util.HashMap; -import java.util.Map; - -import ch.ethz.ssh2.channel.Channel; -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.packets.TypesWriter; -import ch.ethz.ssh2.sftp.AttribFlags; -import ch.ethz.ssh2.sftp.ErrorCodes; -import ch.ethz.ssh2.sftp.Packet; -import ch.ethz.ssh2.util.StringEncoder; - -/** - * @version $Id: AbstractSFTPClient.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public abstract class AbstractSFTPClient implements SFTPClient { - - private static final Logger log = Logger.getLogger(SFTPv3Client.class); - - private Session sess; - - private InputStream is; - private OutputStream os; - - private int next_request_id = 1000; - - private String charset; - - /** - * Parallel read requests maximum size. - */ - private static final int DEFAULT_MAX_PARALLELISM = 64; - - /** - * Parallel read requests. - */ - private int parallelism = DEFAULT_MAX_PARALLELISM; - - public void setRequestParallelism(int parallelism) { - this.parallelism = Math.min(parallelism, DEFAULT_MAX_PARALLELISM); - } - - /** - * Mapping request ID to request. - */ - private Map<Integer, OutstandingReadRequest> pendingReadQueue - = new HashMap<Integer, OutstandingReadRequest>(); - - /** - * Mapping request ID to request. - */ - private Map<Integer, OutstandingStatusRequest> pendingStatusQueue - = new HashMap<Integer, OutstandingStatusRequest>(); - - private PacketListener listener; - - protected AbstractSFTPClient(final Connection conn, final int version, final PacketListener listener) throws IOException { - this.listener = listener; - log.debug("Opening session and starting SFTP subsystem."); - sess = conn.openSession(); - sess.startSubSystem("sftp"); - is = sess.getStdout(); - os = new BufferedOutputStream(sess.getStdin(), 2048); - init(version); - } - - private void init(final int client_version) throws IOException { - // Send SSH_FXP_INIT with client version - TypesWriter tw = new TypesWriter(); - tw.writeUINT32(client_version); - sendMessage(Packet.SSH_FXP_INIT, 0, tw.getBytes()); - /* Receive SSH_FXP_VERSION */ - log.debug("Waiting for SSH_FXP_VERSION..."); - TypesReader tr = new TypesReader(receiveMessage(34000)); /* Should be enough for any reasonable server */ - int t = tr.readByte(); - listener.read(Packet.forName(t)); - - if (t != Packet.SSH_FXP_VERSION) { - log.warning(String.format("The server did not send a SSH_FXP_VERSION but %d", t)); - throw new PacketTypeException(t); - } - - final int protocol_version = tr.readUINT32(); - log.debug("SSH_FXP_VERSION: protocol_version = " + protocol_version); - - if (protocol_version != client_version) { - throw new IOException(String.format("Server protocol version %d does not match %d", - protocol_version, client_version)); - } - - // Both parties should from then on adhere to particular version of the protocol - - // Read and save extensions (if any) for later use - while (tr.remain() != 0) { - String name = tr.readString(); - listener.read(name); - byte[] value = tr.readByteString(); - log.debug(String.format("SSH_FXP_VERSION: extension: %s = '%s'", name, StringEncoder.GetString(value))); - } - } - - /** - * Queries the channel state - * - * @return True if the underlying session is in open state - */ - public boolean isConnected() { - return sess.getState() == Channel.STATE_OPEN; - } - - /** - * Close this SFTP session. NEVER forget to call this method to free up - * resources - even if you got an exception from one of the other methods. - * Sometimes these other methods may throw an exception, saying that the - * underlying channel is closed (this can happen, e.g., if the other server - * sent a close message.) However, as long as you have not called the - * <code>close()</code> method, you are likely wasting resources. - */ - public void close() { - sess.close(); - } - - /** - * Set the charset used to convert between Java Unicode Strings and byte encodings - * used by the server for paths and file names. - * - * @param charset the name of the charset to be used or <code>null</code> to use UTF-8. - * @throws java.io.IOException - * @see #getCharset() - */ - public void setCharset(String charset) throws IOException { - if (charset == null) { - this.charset = null; - return; - } - - try { - Charset.forName(charset); - } - catch (UnsupportedCharsetException e) { - throw new IOException("This charset is not supported", e); - } - - this.charset = charset; - } - - /** - * The currently used charset for filename encoding/decoding. - * - * @return The name of the charset (<code>null</code> if UTF-8 is used). - * @see #setCharset(String) - */ - public String getCharset() { - return charset; - } - - public abstract SFTPFileHandle openFile(String fileName, int flags, SFTPFileAttributes attr) throws IOException; - - public void mkdir(String dirName, int posixPermissions) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(dirName, this.getCharset()); - tw.writeUINT32(AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS); - tw.writeUINT32(posixPermissions); - sendMessage(Packet.SSH_FXP_MKDIR, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - public void rm(String fileName) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(fileName, this.getCharset()); - sendMessage(Packet.SSH_FXP_REMOVE, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - public void rmdir(String dirName) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(dirName, this.getCharset()); - sendMessage(Packet.SSH_FXP_RMDIR, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - public void mv(String oldPath, String newPath) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(oldPath, this.getCharset()); - tw.writeString(newPath, this.getCharset()); - sendMessage(Packet.SSH_FXP_RENAME, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - public String readLink(String path) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(path, charset); - sendMessage(Packet.SSH_FXP_READLINK, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_NAME) { - int count = tr.readUINT32(); - - if (count != 1) { - throw new PacketTypeException(t); - } - - return tr.readString(charset); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - public void setstat(String path, SFTPFileAttributes attr) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(path, charset); - tw.writeBytes(attr.toBytes()); - sendMessage(Packet.SSH_FXP_SETSTAT, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - public void fsetstat(SFTPFileHandle handle, SFTPFileAttributes attr) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(handle.getHandle(), 0, handle.getHandle().length); - tw.writeBytes(attr.toBytes()); - sendMessage(Packet.SSH_FXP_FSETSTAT, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - public void createSymlink(String src, String target) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(src, charset); - tw.writeString(target, charset); - sendMessage(Packet.SSH_FXP_SYMLINK, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - public void createHardlink(String src, String target) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString("hardlink@openssh.com", charset); - tw.writeString(target, charset); - tw.writeString(src, charset); - sendMessage(Packet.SSH_FXP_EXTENDED, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - public String canonicalPath(String path) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(path, charset); - sendMessage(Packet.SSH_FXP_REALPATH, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_NAME) { - int count = tr.readUINT32(); - - if (count != 1) { - throw new PacketFormatException("The server sent an invalid SSH_FXP_NAME packet."); - } - - final String name = tr.readString(charset); - listener.read(name); - return name; - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - private void sendMessage(int type, int requestId, byte[] msg, int off, int len) throws IOException { - if (log.isDebugEnabled()) { - log.debug(String.format("Send message of type %d with request id %d", type, requestId)); - } - - listener.write(Packet.forName(type)); - int msglen = len + 1; - - if (type != Packet.SSH_FXP_INIT) { - msglen += 4; - } - - os.write(msglen >> 24); - os.write(msglen >> 16); - os.write(msglen >> 8); - os.write(msglen); - os.write(type); - - if (type != Packet.SSH_FXP_INIT) { - os.write(requestId >> 24); - os.write(requestId >> 16); - os.write(requestId >> 8); - os.write(requestId); - } - - os.write(msg, off, len); - os.flush(); - } - - protected void sendMessage(int type, int requestId, byte[] msg) throws IOException { - sendMessage(type, requestId, msg, 0, msg.length); - } - - private void readBytes(byte[] buff, int pos, int len) throws IOException { - while (len > 0) { - int count = is.read(buff, pos, len); - - if (count < 0) { - throw new SocketException("Unexpected end of stream."); - } - - len -= count; - pos += count; - } - } - - /** - * Read a message and guarantee that the <b>contents</b> is not larger than - * <code>maxlen</code> bytes. - * <p/> - * Note: receiveMessage(34000) actually means that the message may be up to 34004 - * bytes (the length attribute preceding the contents is 4 bytes). - * - * @param maxlen - * @return the message contents - * @throws IOException - */ - protected byte[] receiveMessage(int maxlen) throws IOException { - byte[] msglen = new byte[4]; - readBytes(msglen, 0, 4); - int len = (((msglen[0] & 0xff) << 24) | ((msglen[1] & 0xff) << 16) | ((msglen[2] & 0xff) << 8) | (msglen[3] & 0xff)); - - if ((len > maxlen) || (len <= 0)) { - throw new PacketFormatException(String.format("Illegal SFTP packet length %d", len)); - } - - byte[] msg = new byte[len]; - readBytes(msg, 0, len); - return msg; - } - - protected int generateNextRequestID() { - synchronized (this) { - return next_request_id++; - } - } - - protected void closeHandle(byte[] handle) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(handle, 0, handle.length); - sendMessage(Packet.SSH_FXP_CLOSE, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - private void readStatus() throws IOException { - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - // Search the pending queue - OutstandingStatusRequest status = pendingStatusQueue.remove(tr.readUINT32()); - - if (null == status) { - throw new RequestMismatchException(); - } - - // Evaluate the answer - if (t == Packet.SSH_FXP_STATUS) { - // In any case, stop sending more packets - int code = tr.readUINT32(); - - if (log.isDebugEnabled()) { - String[] desc = ErrorCodes.getDescription(code); - log.debug("Got SSH_FXP_STATUS (" + status.req_id + ") (" + ((desc != null) ? desc[0] : "UNKNOWN") + ")"); - } - - if (code == ErrorCodes.SSH_FX_OK) { - return; - } - - String msg = tr.readString(); - listener.read(msg); - throw new SFTPException(msg, code); - } - - throw new PacketTypeException(t); - } - - private void readPendingReadStatus() throws IOException { - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - // Search the pending queue - OutstandingReadRequest status = pendingReadQueue.remove(tr.readUINT32()); - - if (null == status) { - throw new RequestMismatchException(); - } - - // Evaluate the answer - if (t == Packet.SSH_FXP_STATUS) { - // In any case, stop sending more packets - int code = tr.readUINT32(); - - if (log.isDebugEnabled()) { - String[] desc = ErrorCodes.getDescription(code); - log.debug("Got SSH_FXP_STATUS (" + status.req_id + ") (" + ((desc != null) ? desc[0] : "UNKNOWN") + ")"); - } - - if (code == ErrorCodes.SSH_FX_OK) { - return; - } - - if (code == ErrorCodes.SSH_FX_EOF) { - return; - } - - String msg = tr.readString(); - listener.read(msg); - throw new SFTPException(msg, code); - } - - throw new PacketTypeException(t); - } - - protected void expectStatusOKMessage(int id) throws IOException { - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != id) { - throw new RequestMismatchException(); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - - if (errorCode == ErrorCodes.SSH_FX_OK) { - return; - } - - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - public void closeFile(SFTPFileHandle handle) throws IOException { - while (!pendingReadQueue.isEmpty()) { - this.readPendingReadStatus(); - } - - while (!pendingStatusQueue.isEmpty()) { - this.readStatus(); - } - - closeHandle(handle.getHandle()); - } - - public int read(SFTPFileHandle handle, long fileOffset, byte[] dst, int dstoff, int len) throws IOException { - boolean errorOccured = false; - int remaining = len * parallelism; - //int clientOffset = dstoff; - long serverOffset = fileOffset; - - for (OutstandingReadRequest r : pendingReadQueue.values()) { - // Server offset should take pending requests into account. - serverOffset += r.len; - } - - while (true) { - // Stop if there was an error and no outstanding request - if ((pendingReadQueue.size() == 0) && errorOccured) { - break; - } - - // Send as many requests as we are allowed to - while (pendingReadQueue.size() < parallelism) { - if (errorOccured) { - break; - } - - // Send the next read request - OutstandingReadRequest req = new OutstandingReadRequest(); - req.req_id = generateNextRequestID(); - req.serverOffset = serverOffset; - req.len = (remaining > len) ? len : remaining; - req.buffer = dst; - req.dstOffset = dstoff; - serverOffset += req.len; - //clientOffset += req.len; - remaining -= req.len; - sendReadRequest(req.req_id, handle, req.serverOffset, req.len); - pendingReadQueue.put(req.req_id, req); - } - - if (pendingReadQueue.size() == 0) { - break; - } - - // Receive a single answer - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - // Search the pending queue - OutstandingReadRequest req = pendingReadQueue.remove(tr.readUINT32()); - - if (null == req) { - throw new RequestMismatchException(); - } - - // Evaluate the answer - if (t == Packet.SSH_FXP_STATUS) { - /* In any case, stop sending more packets */ - int code = tr.readUINT32(); - String msg = tr.readString(); - listener.read(msg); - - if (log.isDebugEnabled()) { - String[] desc = ErrorCodes.getDescription(code); - log.debug("Got SSH_FXP_STATUS (" + req.req_id + ") (" + ((desc != null) ? desc[0] : "UNKNOWN") + ")"); - } - - // Flag to read all pending requests but don't send any more. - errorOccured = true; - - if (pendingReadQueue.isEmpty()) { - if (ErrorCodes.SSH_FX_EOF == code) { - return -1; - } - - throw new SFTPException(msg, code); - } - } - else if (t == Packet.SSH_FXP_DATA) { - // OK, collect data - int readLen = tr.readUINT32(); - - if ((readLen < 0) || (readLen > req.len)) { - throw new PacketFormatException("The server sent an invalid length field in a SSH_FXP_DATA packet."); - } - - if (log.isDebugEnabled()) { - log.debug("Got SSH_FXP_DATA (" + req.req_id + ") " + req.serverOffset + "/" + readLen - + " (requested: " + req.len + ")"); - } - - // Read bytes into buffer - tr.readBytes(req.buffer, req.dstOffset, readLen); - - if (readLen < req.len) { - /* Send this request packet again to request the remaing data in this slot. */ - req.req_id = generateNextRequestID(); - req.serverOffset += readLen; - req.len -= readLen; - log.debug("Requesting again: " + req.serverOffset + "/" + req.len); - sendReadRequest(req.req_id, handle, req.serverOffset, req.len); - pendingReadQueue.put(req.req_id, req); - } - - return readLen; - } - else { - throw new PacketTypeException(t); - } - } - - // Should never reach here. - throw new SFTPException("No EOF reached", -1); - } - - private void sendReadRequest(int id, SFTPFileHandle handle, long offset, int len) throws IOException { - TypesWriter tw = new TypesWriter(); - tw.writeString(handle.getHandle(), 0, handle.getHandle().length); - tw.writeUINT64(offset); - tw.writeUINT32(len); - sendMessage(Packet.SSH_FXP_READ, id, tw.getBytes()); - } - - public void write(SFTPFileHandle handle, long fileOffset, byte[] src, int srcoff, int len) throws IOException { - while (len > 0) { - int writeRequestLen = len; - - if (writeRequestLen > 32768) { - writeRequestLen = 32768; - } - - // Send the next write request - OutstandingStatusRequest req = new OutstandingStatusRequest(); - req.req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(handle.getHandle(), 0, handle.getHandle().length); - tw.writeUINT64(fileOffset); - tw.writeString(src, srcoff, writeRequestLen); - sendMessage(Packet.SSH_FXP_WRITE, req.req_id, tw.getBytes()); - pendingStatusQueue.put(req.req_id, req); - - // Only read next status if parallelism reached - while (pendingStatusQueue.size() >= parallelism) { - this.readStatus(); - } - - fileOffset += writeRequestLen; - srcoff += writeRequestLen; - len -= writeRequestLen; - } - } - - - /** - * A read is divided into multiple requests sent sequentially before - * reading any status from the server - */ - private static class OutstandingReadRequest { - int req_id; - /** - * Read offset to request on server starting at the file offset for the first request. - */ - long serverOffset; - /** - * Length of requested data - */ - int len; - /** - * Offset in destination buffer - */ - int dstOffset; - /** - * Temporary buffer - */ - byte[] buffer; - } - - /** - * A read is divided into multiple requests sent sequentially before - * reading any status from the server - */ - private static final class OutstandingStatusRequest { - int req_id; - } - -}
--- a/src/ch/ethz/ssh2/AuthAgentCallback.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -package ch.ethz.ssh2; - -import java.security.KeyPair; -import java.util.Map; - -/** - * AuthAgentCallback. - * - * @author Kenny Root - * @version $Id$ - */ -public interface AuthAgentCallback { - - /** - * @return array of blobs containing the OpenSSH-format encoded public keys - */ - Map<String, byte[]> retrieveIdentities(); - - /** - * @param pair A <code>RSAPrivateKey</code> or <code>DSAPrivateKey</code> or <code>ECPrivateKey</code> - * containing a DSA or RSA or EC private key of - * the user in standard java key format. - * @param comment comment associated with this key - * @param confirmUse whether to prompt before using this key - * @param lifetime lifetime in seconds for key to be remembered - * @return success or failure - */ - boolean addIdentity(KeyPair pair, String comment, boolean confirmUse, int lifetime); - - /** - * @param publicKey byte blob containing the OpenSSH-format encoded public key - * @return success or failure - */ - boolean removeIdentity(byte[] publicKey); - - /** - * @return success or failure - */ - boolean removeAllIdentities(); - - /** - * @param publicKey byte blob containing the OpenSSH-format encoded public key - * @return A <code>RSAPrivateKey</code> or <code>DSAPrivateKey</code> - * containing a DSA or RSA or EC private key of - * the user in standard java key format. - */ - KeyPair getKeyPair(byte[] publicKey); - - /** - * @return - */ - boolean isAgentLocked(); - - /** - * @param lockPassphrase - */ - boolean setAgentLock(String lockPassphrase); - - /** - * @param unlockPassphrase - * @return - */ - boolean requestAgentUnlock(String unlockPassphrase); -}
--- a/src/ch/ethz/ssh2/AuthenticationResult.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ - -package ch.ethz.ssh2; - -public enum AuthenticationResult { - - /** - * - */ - SUCCESS, - /** - * The authentication request to which this is a response was successful, however, more - * authentication requests are needed (multi-method authentication sequence). - * - * @see ServerAuthenticationCallback#getRemainingAuthMethods(ServerConnection) - */ - PARTIAL_SUCCESS, - /** - * The server rejected the authentication request. - */ - FAILURE -}
--- a/src/ch/ethz/ssh2/ChannelCondition.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * Contains constants that can be used to specify what conditions to wait for on - * a SSH-2 channel (e.g., represented by a {@link Session}). - * - * @see Session#waitForCondition(int, long) - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public abstract interface ChannelCondition { - /** - * A timeout has occurred, none of your requested conditions is fulfilled. - * However, other conditions may be true - therefore, NEVER use the "==" - * operator to test for this (or any other) condition. Always use - * something like <code>((cond & ChannelCondition.CLOSED) != 0)</code>. - */ - public static final int TIMEOUT = 1; - - /** - * The underlying SSH-2 channel, however not necessarily the whole connection, - * has been closed. This implies <code>EOF</code>. Note that there may still - * be unread stdout or stderr data in the local window, i.e, <code>STDOUT_DATA</code> - * or/and <code>STDERR_DATA</code> may be set at the same time. - */ - public static final int CLOSED = 2; - - /** - * There is stdout data available that is ready to be consumed. - */ - public static final int STDOUT_DATA = 4; - - /** - * There is stderr data available that is ready to be consumed. - */ - public static final int STDERR_DATA = 8; - - /** - * EOF on has been reached, no more _new_ stdout or stderr data will arrive - * from the remote server. However, there may be unread stdout or stderr - * data, i.e, <code>STDOUT_DATA</code> or/and <code>STDERR_DATA</code> - * may be set at the same time. - */ - public static final int EOF = 16; - - /** - * The exit status of the remote process is available. - * Some servers never send the exist status, or occasionally "forget" to do so. - */ - public static final int EXIT_STATUS = 32; - - /** - * The exit signal of the remote process is available. - */ - public static final int EXIT_SIGNAL = 64; - -}
--- a/src/ch/ethz/ssh2/Connection.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1452 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2; - -import java.io.CharArrayWriter; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketTimeoutException; -import java.security.KeyPair; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import ch.ethz.ssh2.auth.AgentProxy; -import ch.ethz.ssh2.auth.AuthenticationManager; -import ch.ethz.ssh2.channel.ChannelManager; -import ch.ethz.ssh2.compression.CompressionFactory; -import ch.ethz.ssh2.crypto.CryptoWishList; -import ch.ethz.ssh2.crypto.SecureRandomFix; -import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; -import ch.ethz.ssh2.crypto.digest.MAC; -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.PacketIgnore; -import ch.ethz.ssh2.transport.ClientTransportManager; -import ch.ethz.ssh2.transport.HTTPProxyClientTransportManager; -import ch.ethz.ssh2.transport.KexManager; -import ch.ethz.ssh2.util.TimeoutService.TimeoutToken; -import ch.ethz.ssh2.util.TimeoutService; - -/** - * A <code>Connection</code> is used to establish an encrypted TCP/IP - * connection to a SSH-2 server. - * <p/> - * Typically, one - * <ol> - * <li>creates a {@link #Connection(String) Connection} object.</li> - * <li>calls the {@link #connect() connect()} method.</li> - * <li>calls some of the authentication methods (e.g., {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}).</li> - * <li>calls one or several times the {@link #openSession() openSession()} method.</li> - * <li>finally, one must close the connection and release resources with the {@link #close() close()} method.</li> - * </ol> - * - * @author Christian Plattner - * @version $Id: Connection.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ - -public class Connection { - protected static final Logger log = Logger.getLogger(Connection.class); - - /** - * The identifier presented to the SSH-2 server. This is the same - * as the "softwareversion" defined in RFC 4253. - * <p/> - * <b>NOTE: As per the RFC, the "softwareversion" string MUST consist of printable - * US-ASCII characters, with the exception of whitespace characters and the minus sign (-).</b> - */ - private String softwareversion - = String.format("Ganymed_%s", Version.getSpecification()); - - /* Will be used to generate all random data needed for the current connection. - * Note: SecureRandom.nextBytes() is thread safe. - */ - - private SecureRandomFix generator; - - /** - * Unless you know what you are doing, you will never need this. - * - * @return The list of supported cipher algorithms by this implementation. - */ - - public static synchronized String[] getAvailableCiphers() { - return BlockCipherFactory.getDefaultCipherList(); - } - - /** - * Unless you know what you are doing, you will never need this. - * - * @return The list of supported MAC algorthims by this implementation. - */ - - public static synchronized String[] getAvailableMACs() { - return MAC.getMacList(); - } - - /** - * Unless you know what you are doing, you will never need this. - * - * @return The list of supported server host key algorthims by this implementation. - */ - - public static synchronized String[] getAvailableServerHostKeyAlgorithms() { - return KexManager.getDefaultServerHostkeyAlgorithmList(); - } - - private AuthenticationManager am; - - private boolean authenticated; - private ChannelManager cm; - - private CryptoWishList cryptoWishList - = new CryptoWishList(); - - private DHGexParameters dhgexpara - = new DHGexParameters(); - - private final String hostname; - - private final int port; - - private ClientTransportManager tm; - - private boolean tcpNoDelay = false; - - private HTTPProxyData proxy; - - private List<ConnectionMonitor> connectionMonitors - = new ArrayList<ConnectionMonitor>(); - - /** - * Prepares a fresh <code>Connection</code> object which can then be used - * to establish a connection to the specified SSH-2 server. - * <p/> - * Same as {@link #Connection(String, int) Connection(hostname, 22)}. - * - * @param hostname the hostname of the SSH-2 server. - */ - public Connection(String hostname) { - this(hostname, 22); - } - - /** - * Prepares a fresh <code>Connection</code> object which can then be used - * to establish a connection to the specified SSH-2 server. - * - * @param hostname the host where we later want to connect to. - * @param port port on the server, normally 22. - */ - public Connection(String hostname, int port) { - this.hostname = hostname; - this.port = port; - } - - /** - * Prepares a fresh <code>Connection</code> object which can then be used - * to establish a connection to the specified SSH-2 server. - * - * @param hostname the host where we later want to connect to. - * @param port port on the server, normally 22. - * @param softwareversion Allows you to set a custom "softwareversion" string as defined in RFC 4253. - * <b>NOTE: As per the RFC, the "softwareversion" string MUST consist of printable - * US-ASCII characters, with the exception of whitespace characters and the minus sign (-).</b> - */ - public Connection(String hostname, int port, String softwareversion) { - this.hostname = hostname; - this.port = port; - this.softwareversion = softwareversion; - } - - public Connection(String hostname, int port, final HTTPProxyData proxy) { - this.hostname = hostname; - this.port = port; - this.proxy = proxy; - } - - public Connection(String hostname, int port, String softwareversion, final HTTPProxyData proxy) { - this.hostname = hostname; - this.port = port; - this.softwareversion = softwareversion; - this.proxy = proxy; - } - - /** - * After a successful connect, one has to authenticate oneself. This method - * is based on DSA (it uses DSA to sign a challenge sent by the server). - * <p/> - * If the authentication phase is complete, <code>true</code> will be - * returned. If the server does not accept the request (or if further - * authentication steps are needed), <code>false</code> is returned and - * one can retry either by using this or any other authentication method - * (use the <code>getRemainingAuthMethods</code> method to get a list of - * the remaining possible methods). - * - * @param user A <code>String</code> holding the username. - * @param pem A <code>String</code> containing the DSA private key of the - * user in OpenSSH key format (PEM, you can't miss the - * "-----BEGIN DSA PRIVATE KEY-----" tag). The string may contain - * linefeeds. - * @param password If the PEM string is 3DES encrypted ("DES-EDE3-CBC"), then you - * must specify the password. Otherwise, this argument will be - * ignored and can be set to <code>null</code>. - * @return whether the connection is now authenticated. - * @throws IOException - * @deprecated You should use one of the {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()} - * methods, this method is just a wrapper for it and will - * disappear in future builds. - */ - @Deprecated - - public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException { - if (tm == null) { - throw new IllegalStateException("Connection is not established!"); - } - - if (authenticated) { - throw new IllegalStateException("Connection is already authenticated!"); - } - - if (am == null) { - am = new AuthenticationManager(tm); - } - - if (cm == null) { - cm = new ChannelManager(tm); - } - - if (user == null) { - throw new IllegalArgumentException("user argument is null"); - } - - if (pem == null) { - throw new IllegalArgumentException("pem argument is null"); - } - - authenticated = am.authenticatePublicKey(user, pem.toCharArray(), password, getOrCreateSecureRND()); - return authenticated; - } - - /** - * A wrapper that calls {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback) - * authenticateWithKeyboardInteractivewith} a <code>null</code> submethod list. - * - * @param user A <code>String</code> holding the username. - * @param cb An <code>InteractiveCallback</code> which will be used to - * determine the responses to the questions asked by the server. - * @return whether the connection is now authenticated. - * @throws IOException - */ - - public synchronized boolean authenticateWithKeyboardInteractive(String user, InteractiveCallback cb) - throws IOException { - return authenticateWithKeyboardInteractive(user, null, cb); - } - - /** - * After a successful connect, one has to authenticate oneself. This method - * is based on "keyboard-interactive", specified in - * draft-ietf-secsh-auth-kbdinteract-XX. Basically, you have to define a - * callback object which will be feeded with challenges generated by the - * server. Answers are then sent back to the server. It is possible that the - * callback will be called several times during the invocation of this - * method (e.g., if the server replies to the callback's answer(s) with - * another challenge...) - * <p/> - * If the authentication phase is complete, <code>true</code> will be - * returned. If the server does not accept the request (or if further - * authentication steps are needed), <code>false</code> is returned and - * one can retry either by using this or any other authentication method - * (use the <code>getRemainingAuthMethods</code> method to get a list of - * the remaining possible methods). - * <p/> - * Note: some SSH servers advertise "keyboard-interactive", however, any - * interactive request will be denied (without having sent any challenge to - * the client). - * - * @param user A <code>String</code> holding the username. - * @param submethods An array of submethod names, see - * draft-ietf-secsh-auth-kbdinteract-XX. May be <code>null</code> - * to indicate an empty list. - * @param cb An <code>InteractiveCallback</code> which will be used to - * determine the responses to the questions asked by the server. - * @return whether the connection is now authenticated. - * @throws IOException - */ - - public synchronized boolean authenticateWithKeyboardInteractive(String user, String[] submethods, - InteractiveCallback cb) throws IOException { - if (cb == null) { - throw new IllegalArgumentException("Callback may not ne NULL!"); - } - - if (tm == null) { - throw new IllegalStateException("Connection is not established!"); - } - - if (authenticated) { - throw new IllegalStateException("Connection is already authenticated!"); - } - - if (am == null) { - am = new AuthenticationManager(tm); - } - - if (cm == null) { - cm = new ChannelManager(tm); - } - - if (user == null) { - throw new IllegalArgumentException("user argument is null"); - } - - authenticated = am.authenticateInteractive(user, submethods, cb); - return authenticated; - } - - public synchronized boolean authenticateWithAgent(String user, AgentProxy proxy) throws IOException { - if (tm == null) { - throw new IllegalStateException("Connection is not established!"); - } - - if (authenticated) { - throw new IllegalStateException("Connection is already authenticated!"); - } - - if (am == null) { - am = new AuthenticationManager(tm); - } - - if (cm == null) { - cm = new ChannelManager(tm); - } - - if (user == null) { - throw new IllegalArgumentException("user argument is null"); - } - - authenticated = am.authenticatePublicKey(user, proxy); - return authenticated; - } - - /** - * After a successful connect, one has to authenticate oneself. This method - * sends username and password to the server. - * <p/> - * If the authentication phase is complete, <code>true</code> will be - * returned. If the server does not accept the request (or if further - * authentication steps are needed), <code>false</code> is returned and - * one can retry either by using this or any other authentication method - * (use the <code>getRemainingAuthMethods</code> method to get a list of - * the remaining possible methods). - * <p/> - * Note: if this method fails, then please double-check that it is actually - * offered by the server (use {@link #getRemainingAuthMethods(String) getRemainingAuthMethods()}. - * <p/> - * Often, password authentication is disabled, but users are not aware of it. - * Many servers only offer "publickey" and "keyboard-interactive". However, - * even though "keyboard-interactive" *feels* like password authentication - * (e.g., when using the putty or openssh clients) it is *not* the same mechanism. - * - * @param user - * @param password - * @return if the connection is now authenticated. - * @throws IOException - */ - - public synchronized boolean authenticateWithPassword(String user, String password) throws IOException { - if (tm == null) { - throw new IllegalStateException("Connection is not established!"); - } - - if (authenticated) { - throw new IllegalStateException("Connection is already authenticated!"); - } - - if (am == null) { - am = new AuthenticationManager(tm); - } - - if (cm == null) { - cm = new ChannelManager(tm); - } - - if (user == null) { - throw new IllegalArgumentException("user argument is null"); - } - - if (password == null) { - throw new IllegalArgumentException("password argument is null"); - } - - authenticated = am.authenticatePassword(user, password); - return authenticated; - } - - /** - * After a successful connect, one has to authenticate oneself. - * This method can be used to explicitly use the special "none" - * authentication method (where only a username has to be specified). - * <p/> - * Note 1: The "none" method may always be tried by clients, however as by - * the specs, the server will not explicitly announce it. In other words, - * the "none" token will never show up in the list returned by - * {@link #getRemainingAuthMethods(String)}. - * <p/> - * Note 2: no matter which one of the authenticateWithXXX() methods - * you call, the library will always issue exactly one initial "none" - * authentication request to retrieve the initially allowed list of - * authentication methods by the server. Please read RFC 4252 for the - * details. - * <p/> - * If the authentication phase is complete, <code>true</code> will be - * returned. If further authentication steps are needed, <code>false</code> - * is returned and one can retry by any other authentication method - * (use the <code>getRemainingAuthMethods</code> method to get a list of - * the remaining possible methods). - * - * @param user - * @return if the connection is now authenticated. - * @throws IOException - */ - - public synchronized boolean authenticateWithNone(String user) throws IOException { - if (tm == null) { - throw new IllegalStateException("Connection is not established!"); - } - - if (authenticated) { - throw new IllegalStateException("Connection is already authenticated!"); - } - - if (am == null) { - am = new AuthenticationManager(tm); - } - - if (cm == null) { - cm = new ChannelManager(tm); - } - - if (user == null) { - throw new IllegalArgumentException("user argument is null"); - } - - /* Trigger the sending of the PacketUserauthRequestNone packet */ - /* (if not already done) */ - authenticated = am.authenticateNone(user); - return authenticated; - } - - /** - * After a successful connect, one has to authenticate oneself. - * The authentication method "publickey" works by signing a challenge - * sent by the server. The signature is either DSA or RSA based - it - * just depends on the type of private key you specify, either a DSA - * or RSA private key in PEM format. And yes, this is may seem to be a - * little confusing, the method is called "publickey" in the SSH-2 protocol - * specification, however since we need to generate a signature, you - * actually have to supply a private key =). - * <p/> - * The private key contained in the PEM file may also be encrypted ("Proc-Type: 4,ENCRYPTED"). - * The library supports DES-CBC and DES-EDE3-CBC encryption, as well - * as the more exotic PEM encrpytions AES-128-CBC, AES-192-CBC and AES-256-CBC. - * <p/> - * If the authentication phase is complete, <code>true</code> will be - * returned. If the server does not accept the request (or if further - * authentication steps are needed), <code>false</code> is returned and - * one can retry either by using this or any other authentication method - * (use the <code>getRemainingAuthMethods</code> method to get a list of - * the remaining possible methods). - * <p/> - * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..." - * it is not in the expected format. You have to convert it to the OpenSSH - * key format by using the "puttygen" tool (can be downloaded from the Putty - * website). Simply load your key and then use the "Conversions/Export OpenSSH key" - * functionality to get a proper PEM file. - * - * @param user A <code>String</code> holding the username. - * @param pemPrivateKey A <code>char[]</code> containing a DSA or RSA private key of the - * user in OpenSSH key format (PEM, you can't miss the - * "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----" - * tag). The char array may contain linebreaks/linefeeds. - * @param password If the PEM structure is encrypted ("Proc-Type: 4,ENCRYPTED") then - * you must specify a password. Otherwise, this argument will be ignored - * and can be set to <code>null</code>. - * @return whether the connection is now authenticated. - * @throws IOException - */ - - public synchronized boolean authenticateWithPublicKey(String user, char[] pemPrivateKey, String password) - throws IOException { - if (tm == null) { - throw new IllegalStateException("Connection is not established!"); - } - - if (authenticated) { - throw new IllegalStateException("Connection is already authenticated!"); - } - - if (am == null) { - am = new AuthenticationManager(tm); - } - - if (cm == null) { - cm = new ChannelManager(tm); - } - - if (user == null) { - throw new IllegalArgumentException("user argument is null"); - } - - if (pemPrivateKey == null) { - throw new IllegalArgumentException("pemPrivateKey argument is null"); - } - - authenticated = am.authenticatePublicKey(user, pemPrivateKey, password, getOrCreateSecureRND()); - return authenticated; - } - - /** - * After a successful connect, one has to authenticate oneself. The - * authentication method "publickey" works by signing a challenge sent by - * the server. The signature is either DSA or RSA based - it just depends on - * the type of private key you specify, either a DSA or RSA private key in - * PEM format. And yes, this is may seem to be a little confusing, the - * method is called "publickey" in the SSH-2 protocol specification, however - * since we need to generate a signature, you actually have to supply a - * private key =). - * <p> - * If the authentication phase is complete, <code>true</code> will be - * returned. If the server does not accept the request (or if further - * authentication steps are needed), <code>false</code> is returned and - * one can retry either by using this or any other authentication method - * (use the <code>getRemainingAuthMethods</code> method to get a list of - * the remaining possible methods). - * - * @param user - * A <code>String</code> holding the username. - * @param pair - * A <code>RSAPrivateKey</code> or <code>DSAPrivateKey</code> - * containing a DSA or RSA private key of - * the user in Trilead object format. - * - * @return whether the connection is now authenticated. - * @throws IOException - */ - - public synchronized boolean authenticateWithPublicKey(String user, KeyPair pair) - throws IOException { - if (tm == null) - throw new IllegalStateException("Connection is not established!"); - - if (authenticated) - throw new IllegalStateException("Connection is already authenticated!"); - - if (am == null) - am = new AuthenticationManager(tm); - - if (cm == null) - cm = new ChannelManager(tm); - - if (user == null) - throw new IllegalArgumentException("user argument is null"); - - if (pair == null) - throw new IllegalArgumentException("Key pair argument is null"); - - authenticated = am.authenticatePublicKey(user, pair, getOrCreateSecureRND()); - return authenticated; - } - - /** - * A convenience wrapper function which reads in a private key (PEM format, either DSA or RSA) - * and then calls <code>authenticateWithPublicKey(String, char[], String)</code>. - * <p/> - * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..." - * it is not in the expected format. You have to convert it to the OpenSSH - * key format by using the "puttygen" tool (can be downloaded from the Putty - * website). Simply load your key and then use the "Conversions/Export OpenSSH key" - * functionality to get a proper PEM file. - * - * @param user A <code>String</code> holding the username. - * @param pemFile A <code>File</code> object pointing to a file containing a DSA or RSA - * private key of the user in OpenSSH key format (PEM, you can't miss the - * "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----" - * tag). - * @param password If the PEM file is encrypted then you must specify the password. - * Otherwise, this argument will be ignored and can be set to <code>null</code>. - * @return whether the connection is now authenticated. - * @throws IOException - */ - - public synchronized boolean authenticateWithPublicKey(String user, File pemFile, String password) - throws IOException { - if (pemFile == null) { - throw new IllegalArgumentException("pemFile argument is null"); - } - - char[] buff = new char[256]; - CharArrayWriter cw = new CharArrayWriter(); - FileReader fr = new FileReader(pemFile); - - while (true) { - int len = fr.read(buff); - - if (len < 0) { - break; - } - - cw.write(buff, 0, len); - } - - fr.close(); - return authenticateWithPublicKey(user, cw.toCharArray(), password); - } - - /** - * Add a {@link ConnectionMonitor} to this connection. Can be invoked at any time, - * but it is best to add connection monitors before invoking - * <code>connect()</code> to avoid glitches (e.g., you add a connection monitor after - * a successful connect(), but the connection has died in the mean time. Then, - * your connection monitor won't be notified.) - * <p/> - * You can add as many monitors as you like. If a monitor has already been added, then - * this method does nothing. - * - * @param cmon An object implementing the {@link ConnectionMonitor} interface. - * @see ConnectionMonitor - */ - - public synchronized void addConnectionMonitor(ConnectionMonitor cmon) { - if (!connectionMonitors.contains(cmon)) { - connectionMonitors.add(cmon); - - if (tm != null) { - tm.setConnectionMonitors(connectionMonitors); - } - } - } - - /** - * Remove a {@link ConnectionMonitor} from this connection. - * - * @param cmon - * @return whether the monitor could be removed - */ - - public synchronized boolean removeConnectionMonitor(ConnectionMonitor cmon) { - boolean existed = connectionMonitors.remove(cmon); - - if (tm != null) { - tm.setConnectionMonitors(connectionMonitors); - } - - return existed; - } - - /** - * Controls whether compression is used on the link or not. - * <p> - * Note: This can only be called before connect() - * @param enabled whether to enable compression - * @throws IOException - */ - - public synchronized void setCompression(boolean enabled) throws IOException { - if (tm != null) - throw new IOException("Connection to " + hostname + " is already in connected state!"); - - if (enabled) enableCompression(); - else disableCompression(); - } - - /** - * Close the connection to the SSH-2 server. All assigned sessions will be - * closed, too. Can be called at any time. Don't forget to call this once - * you don't need a connection anymore - otherwise the receiver thread may - * run forever. - */ - - // cannot be synchronized, since Connection.connect() is synchronized, and - // if the key exchange fails, another thread will try to close(). - - public void close() { - log.debug("Connection.close()"); - Throwable t = new Throwable("Closed due to user request."); - close(t, false); - } - - public void close(Throwable t, boolean hard) { - log.debug(String.format("Connection.close(%s hard=%b)", t.getMessage(), hard)); - if (cm != null) { - cm.closeAllChannels(); - } - - if (tm != null) { - tm.close(t, hard == false); - tm = null; - } - - am = null; - cm = null; - authenticated = false; - } - - /** - * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(null, 0, 0)}. - * - * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. - * @throws IOException - */ - - public synchronized ConnectionInfo connect() throws IOException { - return connect(null, 0, 0); - } - - /** - * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(verifier, 0, 0)}. - * - * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. - * @throws IOException - */ - - public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier) throws IOException { - return connect(verifier, 0, 0); - } - - /** - * Connect to the SSH-2 server and, as soon as the server has presented its - * host key, use the {@link ServerHostKeyVerifier#verifyServerHostKey(String, - * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} - * method of the <code>verifier</code> to ask for permission to proceed. - * If <code>verifier</code> is <code>null</code>, then any host key will be - * accepted - this is NOT recommended, since it makes man-in-the-middle attackes - * VERY easy (somebody could put a proxy SSH server between you and the real server). - * <p/> - * Note: The verifier will be called before doing any crypto calculations - * (i.e., diffie-hellman). Therefore, if you don't like the presented host key then - * no CPU cycles are wasted (and the evil server has less information about us). - * <p/> - * However, it is still possible that the server presented a fake host key: the server - * cheated (typically a sign for a man-in-the-middle attack) and is not able to generate - * a signature that matches its host key. Don't worry, the library will detect such - * a scenario later when checking the signature (the signature cannot be checked before - * having completed the diffie-hellman exchange). - * <p/> - * Note 2: The {@link ServerHostKeyVerifier#verifyServerHostKey(String, - * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} method - * will *NOT* be called from the current thread, the call is being made from a - * background thread (there is a background dispatcher thread for every - * established connection). - * <p/> - * Note 3: This method will block as long as the key exchange of the underlying connection - * has not been completed (and you have not specified any timeouts). - * <p/> - * Note 4: If you want to re-use a connection object that was successfully connected, - * then you must call the {@link #close()} method before invoking <code>connect()</code> again. - * - * @param verifier An object that implements the - * {@link ServerHostKeyVerifier} interface. Pass <code>null</code> - * to accept any server host key - NOT recommended. - * @param connectTimeout Connect the underlying TCP socket to the server with the given timeout - * value (non-negative, in milliseconds). Zero means no timeout. - * @param kexTimeout Timeout for complete connection establishment (non-negative, - * in milliseconds). Zero means no timeout. The timeout counts from the - * moment you invoke the connect() method and is cancelled as soon as the - * first key-exchange round has finished. It is possible that - * the timeout event will be fired during the invocation of the - * <code>verifier</code> callback, but it will only have an effect after - * the <code>verifier</code> returns. - * @return A {@link ConnectionInfo} object containing the details of - * the established connection. - * @throws IOException If any problem occurs, e.g., the server's host key is not - * accepted by the <code>verifier</code> or there is problem during - * the initial crypto setup (e.g., the signature sent by the server is wrong). - * <p/> - * In case of a timeout (either connectTimeout or kexTimeout) - * a SocketTimeoutException is thrown. - * <p/> - * An exception may also be thrown if the connection was already successfully - * connected (no matter if the connection broke in the mean time) and you invoke - * <code>connect()</code> again without having called {@link #close()} first. - * <p/> - * If a HTTP proxy is being used and the proxy refuses the connection, - * then a {@link HTTPProxyException} may be thrown, which - * contains the details returned by the proxy. If the proxy is buggy and does - * not return a proper HTTP response, then a normal IOException is thrown instead. - */ - - public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout) - throws IOException { - final class TimeoutState { - boolean isCancelled = false; - boolean timeoutSocketClosed = false; - } - - if (tm != null) { - throw new IllegalStateException(String.format("Connection to %s is already in connected state", hostname)); - } - - if (connectTimeout < 0) { - throw new IllegalArgumentException("connectTimeout must be non-negative!"); - } - - if (kexTimeout < 0) { - throw new IllegalArgumentException("kexTimeout must be non-negative!"); - } - - final TimeoutState state = new TimeoutState(); - - if (null == proxy) { - tm = new ClientTransportManager(new Socket()); - } - else { - tm = new HTTPProxyClientTransportManager(new Socket(), proxy); - } - - tm.setSoTimeout(connectTimeout); - tm.setTcpNoDelay(tcpNoDelay); - tm.setConnectionMonitors(connectionMonitors); - - try { - TimeoutToken token = null; - - if (kexTimeout > 0) { - final Runnable timeoutHandler = new Runnable() { - public void run() { - synchronized (state) { - if (state.isCancelled) { - return; - } - - state.timeoutSocketClosed = true; - tm.close(new SocketTimeoutException("The connect timeout expired"), false); - } - } - }; - long timeoutHorizont = System.currentTimeMillis() + kexTimeout; - token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler); - } - - tm.connect(hostname, port, softwareversion, cryptoWishList, verifier, dhgexpara, connectTimeout, - getOrCreateSecureRND()); - /* Wait until first KEX has finished */ - ConnectionInfo ci = tm.getConnectionInfo(1); - - /* Now try to cancel the timeout, if needed */ - - if (token != null) { - TimeoutService.cancelTimeoutHandler(token); - - /* Were we too late? */ - - synchronized (state) { - if (state.timeoutSocketClosed) { - throw new IOException("This exception will be replaced by the one below =)"); - } - - /* Just in case the "cancelTimeoutHandler" invocation came just a little bit - * too late but the handler did not enter the semaphore yet - we can - * still stop it. - */ - state.isCancelled = true; - } - } - - return ci; - } - catch (SocketTimeoutException e) { - throw e; - } - catch (HTTPProxyException e) { - throw e; - } - catch (IOException e) { - // This will also invoke any registered connection monitors - close(e, false); - - synchronized (state) { - /* Show a clean exception, not something like "the socket is closed!?!" */ - if (state.timeoutSocketClosed) { - throw new SocketTimeoutException(String.format("The kexTimeout (%d ms) expired.", kexTimeout)); - } - } - - throw e; - } - } - - /** - * Creates a new {@link LocalPortForwarder}. - * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local - * port via the secure tunnel to another host (which may or may not be - * identical to the remote SSH-2 server). - * <p/> - * This method must only be called after one has passed successfully the authentication step. - * There is no limit on the number of concurrent forwardings. - * - * @param local_port the local port the LocalPortForwarder shall bind to. - * @param host_to_connect target address (IP or hostname) - * @param port_to_connect target port - * @return A {@link LocalPortForwarder} object. - * @throws IOException - */ - - public synchronized LocalPortForwarder createLocalPortForwarder(int local_port, String host_to_connect, - int port_to_connect) throws IOException { - this.checkConnection(); - return new LocalPortForwarder(cm, local_port, host_to_connect, port_to_connect); - } - - /** - * Creates a new {@link LocalPortForwarder}. - * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local - * port via the secure tunnel to another host (which may or may not be - * identical to the remote SSH-2 server). - * <p/> - * This method must only be called after one has passed successfully the authentication step. - * There is no limit on the number of concurrent forwardings. - * - * @param addr specifies the InetSocketAddress where the local socket shall be bound to. - * @param host_to_connect target address (IP or hostname) - * @param port_to_connect target port - * @return A {@link LocalPortForwarder} object. - * @throws IOException - */ - - public synchronized LocalPortForwarder createLocalPortForwarder(InetSocketAddress addr, String host_to_connect, - int port_to_connect) throws IOException { - this.checkConnection(); - return new LocalPortForwarder(cm, addr, host_to_connect, port_to_connect); - } - - /** - * Creates a new {@link LocalStreamForwarder}. - * A <code>LocalStreamForwarder</code> manages an Input/Outputstream pair - * that is being forwarded via the secure tunnel into a TCP/IP connection to another host - * (which may or may not be identical to the remote SSH-2 server). - * - * @param host_to_connect - * @param port_to_connect - * @return A {@link LocalStreamForwarder} object. - * @throws IOException - */ - - public synchronized LocalStreamForwarder createLocalStreamForwarder(String host_to_connect, int port_to_connect) - throws IOException { - this.checkConnection(); - return new LocalStreamForwarder(cm, host_to_connect, port_to_connect); - } - - /** - * Creates a new {@link DynamicPortForwarder}. A - * <code>DynamicPortForwarder</code> forwards TCP/IP connections that arrive - * at a local port via the secure tunnel to another host that is chosen via - * the SOCKS protocol. - * <p> - * This method must only be called after one has passed successfully the - * authentication step. There is no limit on the number of concurrent - * forwardings. - * - * @param local_port - * @return A {@link DynamicPortForwarder} object. - * @throws IOException - */ - - public synchronized DynamicPortForwarder createDynamicPortForwarder(int local_port) throws IOException { - if (tm == null) - throw new IllegalStateException("Cannot forward ports, you need to establish a connection first."); - - if (!authenticated) - throw new IllegalStateException("Cannot forward ports, connection is not authenticated."); - - return new DynamicPortForwarder(cm, local_port); - } - - /** - * Creates a new {@link DynamicPortForwarder}. A - * <code>DynamicPortForwarder</code> forwards TCP/IP connections that arrive - * at a local port via the secure tunnel to another host that is chosen via - * the SOCKS protocol. - * <p> - * This method must only be called after one has passed successfully the - * authentication step. There is no limit on the number of concurrent - * forwardings. - * - * @param addr - * specifies the InetSocketAddress where the local socket shall - * be bound to. - * @return A {@link DynamicPortForwarder} object. - * @throws IOException - */ - - public synchronized DynamicPortForwarder createDynamicPortForwarder(InetSocketAddress addr) throws IOException { - if (tm == null) - throw new IllegalStateException("Cannot forward ports, you need to establish a connection first."); - - if (!authenticated) - throw new IllegalStateException("Cannot forward ports, connection is not authenticated."); - - return new DynamicPortForwarder(cm, addr); - } - - /** - * Create a very basic {@link SCPClient} that can be used to copy - * files from/to the SSH-2 server. - * <p/> - * Works only after one has passed successfully the authentication step. - * There is no limit on the number of concurrent SCP clients. - * <p/> - * Note: This factory method will probably disappear in the future. - * - * @return A {@link SCPClient} object. - * @throws IOException - */ - - public synchronized SCPClient createSCPClient() throws IOException { - this.checkConnection(); - return new SCPClient(this); - } - - /** - * Force an asynchronous key re-exchange (the call does not block). The - * latest values set for MAC, Cipher and DH group exchange parameters will - * be used. If a key exchange is currently in progress, then this method has - * the only effect that the so far specified parameters will be used for the - * next (server driven) key exchange. - * <p/> - * Note: This implementation will never start a key exchange (other than the initial one) - * unless you or the SSH-2 server ask for it. - * - * @throws IOException In case of any failure behind the scenes. - */ - - public synchronized void forceKeyExchange() throws IOException { - this.checkConnection(); - tm.forceKeyExchange(cryptoWishList, dhgexpara, null, null, null); - } - - /** - * Returns the hostname that was passed to the constructor. - * - * @return the hostname - */ - - public synchronized String getHostname() { - return hostname; - } - - /** - * Returns the port that was passed to the constructor. - * - * @return the TCP port - */ - - public synchronized int getPort() { - return port; - } - - /** - * Returns a {@link ConnectionInfo} object containing the details of - * the connection. Can be called as soon as the connection has been - * established (successfully connected). - * - * @return A {@link ConnectionInfo} object. - * @throws IOException In case of any failure behind the scenes. - */ - - public synchronized ConnectionInfo getConnectionInfo() throws IOException { - this.checkConnection(); - return tm.getConnectionInfo(1); - } - - /** - * After a successful connect, one has to authenticate oneself. This method - * can be used to tell which authentication methods are supported by the - * server at a certain stage of the authentication process (for the given - * username). - * <p/> - * Note 1: the username will only be used if no authentication step was done - * so far (it will be used to ask the server for a list of possible - * authentication methods by sending the initial "none" request). Otherwise, - * this method ignores the user name and returns a cached method list - * (which is based on the information contained in the last negative server response). - * <p/> - * Note 2: the server may return method names that are not supported by this - * implementation. - * <p/> - * After a successful authentication, this method must not be called - * anymore. - * - * @param user A <code>String</code> holding the username. - * @return a (possibly emtpy) array holding authentication method names. - * @throws IOException - */ - - public synchronized String[] getRemainingAuthMethods(String user) throws IOException { - if (user == null) { - throw new IllegalArgumentException("user argument may not be NULL!"); - } - - if (tm == null) { - throw new IllegalStateException("Connection is not established!"); - } - - if (authenticated) { - throw new IllegalStateException("Connection is already authenticated!"); - } - - if (am == null) { - am = new AuthenticationManager(tm); - } - - if (cm == null) { - cm = new ChannelManager(tm); - } - - final Set<String> remainingMethods = am.getRemainingMethods(user); - return remainingMethods.toArray(new String[remainingMethods.size()]); - } - - /** - * Determines if the authentication phase is complete. Can be called at any - * time. - * - * @return <code>true</code> if no further authentication steps are - * needed. - */ - - public synchronized boolean isAuthenticationComplete() { - return authenticated; - } - - /** - * Returns true if there was at least one failed authentication request and - * the last failed authentication request was marked with "partial success" - * by the server. This is only needed in the rare case of SSH-2 server setups - * that cannot be satisfied with a single successful authentication request - * (i.e., multiple authentication steps are needed.) - * <p/> - * If you are interested in the details, then have a look at RFC4252. - * - * @return if the there was a failed authentication step and the last one - * was marked as a "partial success". - */ - - public synchronized boolean isAuthenticationPartialSuccess() { - if (am == null) { - return false; - } - - return am.getPartialSuccess(); - } - - /** - * Checks if a specified authentication method is available. This method is - * actually just a wrapper for {@link #getRemainingAuthMethods(String) - * getRemainingAuthMethods()}. - * - * @param user A <code>String</code> holding the username. - * @param method An authentication method name (e.g., "publickey", "password", - * "keyboard-interactive") as specified by the SSH-2 standard. - * @return if the specified authentication method is currently available. - * @throws IOException - */ - - public synchronized boolean isAuthMethodAvailable(String user, String method) throws IOException { - String methods[] = getRemainingAuthMethods(user); - - for (final String m : methods) { - if (m.compareTo(method) == 0) { - return true; - } - } - - return false; - } - - private SecureRandomFix getOrCreateSecureRND() { - if (generator == null) { - generator = new SecureRandomFix(); - } - - return generator; - } - - /** - * Open a new {@link Session} on this connection. Works only after one has passed - * successfully the authentication step. There is no limit on the number of - * concurrent sessions. - * - * @return A {@link Session} object. - * @throws IOException - */ - - public synchronized Session openSession() throws IOException { - this.checkConnection(); - return new Session(cm, getOrCreateSecureRND()); - } - - /** - * Send an SSH_MSG_IGNORE packet. This method will generate a random data attribute - * (length between 0 (invlusive) and 16 (exclusive) bytes, contents are random bytes). - * <p/> - * This method must only be called once the connection is established. - * - * @throws IOException - */ - - public synchronized void sendIgnorePacket() throws IOException { - SecureRandomFix rnd = getOrCreateSecureRND(); - byte[] data = new byte[rnd.nextInt(16)]; - rnd.nextBytes(data); - sendIgnorePacket(data); - } - - /** - * Send an SSH_MSG_IGNORE packet with the given data attribute. - * <p/> - * This method must only be called once the connection is established. - * - * @throws IOException - */ - - public synchronized void sendIgnorePacket(byte[] data) throws IOException { - this.checkConnection(); - PacketIgnore pi = new PacketIgnore(data); - tm.sendMessage(pi.getPayload()); - } - - /** - * Controls whether compression is used on the link or not. - */ - - public synchronized void setCompression(String[] algorithms) { - CompressionFactory.checkCompressorList(algorithms); - cryptoWishList.c2s_comp_algos = algorithms; - } - - public synchronized void enableCompression() { - cryptoWishList.c2s_comp_algos = CompressionFactory.getDefaultCompressorList(); - cryptoWishList.s2c_comp_algos = CompressionFactory.getDefaultCompressorList(); - } - - public synchronized void disableCompression() { - cryptoWishList.c2s_comp_algos = new String[] {"none"}; - cryptoWishList.s2c_comp_algos = new String[] {"none"}; - } - - /** - * Unless you know what you are doing, you will never need this. - */ - - public synchronized void setClient2ServerCiphers(final String[] ciphers) { - if ((ciphers == null) || (ciphers.length == 0)) { - throw new IllegalArgumentException(); - } - - BlockCipherFactory.checkCipherList(ciphers); - cryptoWishList.c2s_enc_algos = ciphers; - } - - /** - * Unless you know what you are doing, you will never need this. - */ - - public synchronized void setClient2ServerMACs(final String[] macs) { - MAC.checkMacList(macs); - cryptoWishList.c2s_mac_algos = macs; - } - - /** - * Sets the parameters for the diffie-hellman group exchange. Unless you - * know what you are doing, you will never need this. Default values are - * defined in the {@link DHGexParameters} class. - * - * @param dgp {@link DHGexParameters}, non null. - */ - - public synchronized void setDHGexParameters(DHGexParameters dgp) { - if (dgp == null) { - throw new IllegalArgumentException(); - } - - dhgexpara = dgp; - } - - /** - * Unless you know what you are doing, you will never need this. - */ - - public synchronized void setServer2ClientCiphers(final String[] ciphers) { - BlockCipherFactory.checkCipherList(ciphers); - cryptoWishList.s2c_enc_algos = ciphers; - } - - /** - * Unless you know what you are doing, you will never need this. - */ - - public synchronized void setServer2ClientMACs(final String[] macs) { - MAC.checkMacList(macs); - cryptoWishList.s2c_mac_algos = macs; - } - - /** - * Define the set of allowed server host key algorithms to be used for - * the following key exchange operations. - * <p/> - * Unless you know what you are doing, you will never need this. - * - * @param algos An array of allowed server host key algorithms. - * SSH-2 defines <code>ssh-dss</code> and <code>ssh-rsa</code>. - * The entries of the array must be ordered after preference, i.e., - * the entry at index 0 is the most preferred one. You must specify - * at least one entry. - */ - - public synchronized void setServerHostKeyAlgorithms(final String[] algos) { - KexManager.checkServerHostkeyAlgorithmsList(algos); - cryptoWishList.serverHostKeyAlgorithms = algos; - } - - /** - * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm) on the underlying socket. - * <p/> - * Can be called at any time. If the connection has not yet been established - * then the passed value will be stored and set after the socket has been set up. - * The default value that will be used is <code>false</code>. - * - * @param enable the argument passed to the <code>Socket.setTCPNoDelay()</code> method. - * @throws IOException - */ - - public synchronized void setTCPNoDelay(boolean enable) throws IOException { - tcpNoDelay = enable; - - if (tm != null) { - tm.setTcpNoDelay(enable); - } - } - - /** - * Used to tell the library that the connection shall be established through - * a proxy server. It only makes sense to call this method before calling - * the {@link #connect() connect()} method. - * <p> - * At the moment, only HTTP proxies are supported. - * <p> - * Note: This method can be called any number of times. The - * {@link #connect() connect()} method will use the value set in the last - * preceding invocation of this method. - * - * @see HTTPProxyData - * - * @param proxy - * Connection information about the proxy. If <code>null</code>, - * then no proxy will be used (non surprisingly, this is also the - * default). - */ - - public synchronized void setProxyData(HTTPProxyData proxy) { - this.proxy = proxy; - } - - /** - * Request a remote port forwarding. - * If successful, then forwarded connections will be redirected to the given target address. - * You can cancle a requested remote port forwarding by calling - * {@link #cancelRemotePortForwarding(int) cancelRemotePortForwarding()}. - * <p/> - * A call of this method will block until the peer either agreed or disagreed to your request- - * <p/> - * Note 1: this method typically fails if you - * <ul> - * <li>pass a port number for which the used remote user has not enough permissions (i.e., port - * < 1024)</li> - * <li>or pass a port number that is already in use on the remote server</li> - * <li>or if remote port forwarding is disabled on the server.</li> - * </ul> - * <p/> - * Note 2: (from the openssh man page): By default, the listening socket on the server will be - * bound to the loopback interface only. This may be overriden by specifying a bind address. - * Specifying a remote bind address will only succeed if the server's <b>GatewayPorts</b> option - * is enabled (see sshd_config(5)). - * - * @param bindAddress address to bind to on the server: - * <ul> - * <li>"" means that connections are to be accepted on all protocol families - * supported by the SSH implementation</li> - * <li>"0.0.0.0" means to listen on all IPv4 addresses</li> - * <li>"::" means to listen on all IPv6 addresses</li> - * <li>"localhost" means to listen on all protocol families supported by the SSH - * implementation on loopback addresses only, [RFC3330] and RFC3513]</li> - * <li>"127.0.0.1" and "::1" indicate listening on the loopback interfaces for - * IPv4 and IPv6 respectively</li> - * </ul> - * @param bindPort port number to bind on the server (must be > 0) - * @param targetAddress the target address (IP or hostname) - * @param targetPort the target port - * @throws IOException - */ - - public synchronized void requestRemotePortForwarding(String bindAddress, int bindPort, String targetAddress, - int targetPort) throws IOException { - this.checkConnection(); - - if ((bindAddress == null) || (targetAddress == null) || (bindPort <= 0) || (targetPort <= 0)) { - throw new IllegalArgumentException(); - } - - cm.requestGlobalForward(bindAddress, bindPort, targetAddress, targetPort); - } - - /** - * Cancel an earlier requested remote port forwarding. - * Currently active forwardings will not be affected (e.g., disrupted). - * Note that further connection forwarding requests may be received until - * this method has returned. - * - * @param bindPort the allocated port number on the server - * @throws IOException if the remote side refuses the cancel request or another low - * level error occurs (e.g., the underlying connection is closed) - */ - - public synchronized void cancelRemotePortForwarding(int bindPort) throws IOException { - this.checkConnection(); - cm.requestCancelGlobalForward(bindPort); - } - - /** - * Provide your own instance of SecureRandom. Can be used, e.g., if you - * want to seed the used SecureRandom generator manually. - * <p/> - * The SecureRandom instance is used during key exchanges, public key authentication, - * x11 cookie generation and the like. - * - * @param rnd a SecureRandom instance - */ - - public synchronized void setSecureRandom(SecureRandomFix rnd) { - if (rnd == null) { - throw new IllegalArgumentException(); - } - - this.generator = rnd; - } - - private void checkConnection() throws IllegalStateException { - if (tm == null) { - throw new IllegalStateException("You need to establish a connection first."); - } - - if (!authenticated) { - throw new IllegalStateException("The connection is not authenticated."); - } - } -}
--- a/src/ch/ethz/ssh2/ConnectionInfo.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * In most cases you probably do not need the information contained in here. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class ConnectionInfo { - /** - * The used key exchange (KEX) algorithm in the latest key exchange. - */ - public String keyExchangeAlgorithm; - - /** - * The currently used crypto algorithm for packets from to the client to the - * server. - */ - public String clientToServerCryptoAlgorithm; - /** - * The currently used crypto algorithm for packets from to the server to the - * client. - */ - public String serverToClientCryptoAlgorithm; - - /** - * The currently used MAC algorithm for packets from to the client to the - * server. - */ - public String clientToServerMACAlgorithm; - /** - * The currently used MAC algorithm for packets from to the server to the - * client. - */ - public String serverToClientMACAlgorithm; - - /** - * The type of the server host key (currently either "ssh-dss" or - * "ssh-rsa"). - */ - public String serverHostKeyAlgorithm; - - /** - * The server host key that was sent during the latest key exchange. - */ - public byte[] serverHostKey; - - /** - * Number of kex exchanges performed on this connection so far. - */ - public int keyExchangeCounter = 0; -}
--- a/src/ch/ethz/ssh2/ConnectionMonitor.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * A <code>ConnectionMonitor</code> is used to get notified when the - * underlying socket of a connection is closed. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public interface ConnectionMonitor { - /** - * This method is called after the connection's underlying - * socket has been closed. E.g., due to the {@link Connection#close()} request of the - * user, if the peer closed the connection, due to a fatal error during connect() - * (also if the socket cannot be established) or if a fatal error occured on - * an established connection. - * <p> - * This is an experimental feature. - * <p> - * You MUST NOT make any assumption about the thread that invokes this method. - * <p> - * <b>Please note: if the connection is not connected (e.g., there was no successful - * connect() call), then the invocation of {@link Connection#close()} will NOT trigger - * this method.</b> - * - * @see Connection#addConnectionMonitor(ConnectionMonitor) - * - * @param reason Includes an indication why the socket was closed. - */ - public void connectionLost(Throwable reason); -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/DHGexParameters.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * A <code>DHGexParameters</code> object can be used to specify parameters for - * the diffie-hellman group exchange. - * <p> - * Depending on which constructor is used, either the use of a - * <code>SSH_MSG_KEX_DH_GEX_REQUEST</code> or <code>SSH_MSG_KEX_DH_GEX_REQUEST_OLD</code> - * can be forced. - * - * @see Connection#setDHGexParameters(DHGexParameters) - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public class DHGexParameters { - private final int min_group_len; - private final int pref_group_len; - private final int max_group_len; - - private static final int MIN_ALLOWED = 1024; - private static final int MAX_ALLOWED = 8192; - - /** - * Same as calling {@link #DHGexParameters(int, int, int) DHGexParameters(1024, 1024, 4096)}. - * This is also the default used by the Connection class. - * - */ - public DHGexParameters() { - this(1024, 1024, 4096); - } - - /** - * This constructor can be used to force the sending of a - * <code>SSH_MSG_KEX_DH_GEX_REQUEST_OLD</code> request. - * Internally, the minimum and maximum group lengths will - * be set to zero. - * - * @param pref_group_len has to be >= 1024 and <= 8192 - */ - public DHGexParameters(int pref_group_len) { - if ((pref_group_len < MIN_ALLOWED) || (pref_group_len > MAX_ALLOWED)) - throw new IllegalArgumentException("pref_group_len out of range!"); - - this.pref_group_len = pref_group_len; - this.min_group_len = 0; - this.max_group_len = 0; - } - - /** - * This constructor can be used to force the sending of a - * <code>SSH_MSG_KEX_DH_GEX_REQUEST</code> request. - * <p> - * Note: older OpenSSH servers don't understand this request, in which - * case you should use the {@link #DHGexParameters(int)} constructor. - * <p> - * All values have to be >= 1024 and <= 8192. Furthermore, - * min_group_len <= pref_group_len <= max_group_len. - * - * @param min_group_len - * @param pref_group_len - * @param max_group_len - */ - public DHGexParameters(int min_group_len, int pref_group_len, int max_group_len) { - if ((min_group_len < MIN_ALLOWED) || (min_group_len > MAX_ALLOWED)) - throw new IllegalArgumentException("min_group_len out of range!"); - - if ((pref_group_len < MIN_ALLOWED) || (pref_group_len > MAX_ALLOWED)) - throw new IllegalArgumentException("pref_group_len out of range!"); - - if ((max_group_len < MIN_ALLOWED) || (max_group_len > MAX_ALLOWED)) - throw new IllegalArgumentException("max_group_len out of range!"); - - if ((pref_group_len < min_group_len) || (pref_group_len > max_group_len)) - throw new IllegalArgumentException("pref_group_len is incompatible with min and max!"); - - if (max_group_len < min_group_len) - throw new IllegalArgumentException("max_group_len must not be smaller than min_group_len!"); - - this.min_group_len = min_group_len; - this.pref_group_len = pref_group_len; - this.max_group_len = max_group_len; - } - - /** - * Get the maximum group length. - * - * @return the maximum group length, may be <code>zero</code> if - * SSH_MSG_KEX_DH_GEX_REQUEST_OLD should be requested - */ - public int getMax_group_len() { - return max_group_len; - } - - /** - * Get the minimum group length. - * - * @return minimum group length, may be <code>zero</code> if - * SSH_MSG_KEX_DH_GEX_REQUEST_OLD should be requested - */ - public int getMin_group_len() { - return min_group_len; - } - - /** - * Get the preferred group length. - * - * @return the preferred group length - */ - public int getPref_group_len() { - return pref_group_len; - } -}
--- a/src/ch/ethz/ssh2/DynamicPortForwarder.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.ethz.ssh2; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import ch.ethz.ssh2.channel.ChannelManager; -import ch.ethz.ssh2.channel.DynamicAcceptThread; - -/** - * A <code>DynamicPortForwarder</code> forwards TCP/IP connections to a local - * port via the secure tunnel to another host which is selected via the - * SOCKS protocol. Checkout {@link Connection#createDynamicPortForwarder(int)} - * on how to create one. - * - * @author Kenny Root - * @version $Id: $ - */ -public class DynamicPortForwarder { - ChannelManager cm; - - DynamicAcceptThread dat; - - DynamicPortForwarder(ChannelManager cm, int local_port) - throws IOException { - this.cm = cm; - dat = new DynamicAcceptThread(cm, local_port); - dat.setDaemon(true); - dat.start(); - } - - DynamicPortForwarder(ChannelManager cm, InetSocketAddress addr) throws IOException { - this.cm = cm; - dat = new DynamicAcceptThread(cm, addr); - dat.setDaemon(true); - dat.start(); - } - - /** - * Stop TCP/IP forwarding of newly arriving connections. - * - * @throws IOException - */ - public void close() throws IOException { - dat.stopWorking(); - } -}
--- a/src/ch/ethz/ssh2/HTTPProxyData.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * A <code>HTTPProxyData</code> object is used to specify the needed connection data - * to connect through a HTTP proxy. - * - * @see Connection#setProxyData(ProxyData) - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public class HTTPProxyData implements ProxyData { - public final String proxyHost; - public final int proxyPort; - public final String proxyUser; - public final String proxyPass; - public final String[] requestHeaderLines; - - /** - * Same as calling {@link #HTTPProxyData(String, int, String, String) HTTPProxyData(proxyHost, proxyPort, <code>null</code>, <code>null</code>)} - * - * @param proxyHost Proxy hostname. - * @param proxyPort Proxy port. - */ - public HTTPProxyData(String proxyHost, int proxyPort) { - this(proxyHost, proxyPort, null, null); - } - - /** - * Same as calling {@link #HTTPProxyData(String, int, String, String, String[]) HTTPProxyData(proxyHost, proxyPort, <code>null</code>, <code>null</code>, <code>null</code>)} - * - * @param proxyHost Proxy hostname. - * @param proxyPort Proxy port. - * @param proxyUser Username for basic authentication (<code>null</code> if no authentication is needed). - * @param proxyPass Password for basic authentication (<code>null</code> if no authentication is needed). - */ - public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass) { - this(proxyHost, proxyPort, proxyUser, proxyPass, null); - } - - /** - * Connection data for a HTTP proxy. It is possible to specify a username and password - * if the proxy requires basic authentication. Also, additional request header lines can - * be specified (e.g., "User-Agent: CERN-LineMode/2.15 libwww/2.17b3"). - * <p> - * Please note: if you want to use basic authentication, then both <code>proxyUser</code> - * and <code>proxyPass</code> must be non-null. - * <p> - * Here is an example: - * <p> - * <code> - * new HTTPProxyData("192.168.1.1", "3128", "proxyuser", "secret", new String[] {"User-Agent: GanymedBasedClient/1.0", "X-My-Proxy-Option: something"}); - * </code> - * - * @param proxyHost Proxy hostname. - * @param proxyPort Proxy port. - * @param proxyUser Username for basic authentication (<code>null</code> if no authentication is needed). - * @param proxyPass Password for basic authentication (<code>null</code> if no authentication is needed). - * @param requestHeaderLines An array with additional request header lines (without end-of-line markers) - * that have to be sent to the server. May be <code>null</code>. - */ - - public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass, - String[] requestHeaderLines) { - if (proxyHost == null) - throw new IllegalArgumentException("proxyHost must be non-null"); - - if (proxyPort < 0) - throw new IllegalArgumentException("proxyPort must be non-negative"); - - this.proxyHost = proxyHost; - this.proxyPort = proxyPort; - this.proxyUser = proxyUser; - this.proxyPass = proxyPass; - this.requestHeaderLines = requestHeaderLines; - } -}
--- a/src/ch/ethz/ssh2/HTTPProxyException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; - -/** - * May be thrown upon connect() if a HTTP proxy is being used. - * - * @see Connection#connect() - * @see Connection#setProxyData(ProxyData) - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public class HTTPProxyException extends IOException { - private static final long serialVersionUID = 2241537397104426186L; - - public final String httpResponse; - public final int httpErrorCode; - - public HTTPProxyException(String httpResponse, int httpErrorCode) { - super("HTTP Proxy Error (" + httpErrorCode + " " + httpResponse + ")"); - this.httpResponse = httpResponse; - this.httpErrorCode = httpErrorCode; - } -}
--- a/src/ch/ethz/ssh2/InteractiveCallback.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * An <code>InteractiveCallback</code> is used to respond to challenges sent - * by the server if authentication mode "keyboard-interactive" is selected. - * - * @see Connection#authenticateWithKeyboardInteractive(String, - * String[], InteractiveCallback) - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public interface InteractiveCallback { - /** - * This callback interface is used during a "keyboard-interactive" - * authentication. Every time the server sends a set of challenges (however, - * most often just one challenge at a time), this callback function will be - * called to give your application a chance to talk to the user and to - * determine the response(s). - * <p> - * Some copy-paste information from the standard: a command line interface - * (CLI) client SHOULD print the name and instruction (if non-empty), adding - * newlines. Then for each prompt in turn, the client SHOULD display the - * prompt and read the user input. The name and instruction fields MAY be - * empty strings, the client MUST be prepared to handle this correctly. The - * prompt field(s) MUST NOT be empty strings. - * <p> - * Please refer to draft-ietf-secsh-auth-kbdinteract-XX.txt for the details. - * <p> - * Note: clients SHOULD use control character filtering as discussed in - * RFC4251 to avoid attacks by including - * terminal control characters in the fields to be displayed. - * - * @param name - * the name String sent by the server. - * @param instruction - * the instruction String sent by the server. - * @param numPrompts - * number of prompts - may be zero (in this case, you should just - * return a String array of length zero). - * @param prompt - * an array (length <code>numPrompts</code>) of Strings - * @param echo - * an array (length <code>numPrompts</code>) of booleans. For - * each prompt, the corresponding echo field indicates whether or - * not the user input should be echoed as characters are typed. - * @return an array of reponses - the array size must match the parameter - * <code>numPrompts</code>. - */ - public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) - throws Exception; -}
--- a/src/ch/ethz/ssh2/KnownHosts.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,814 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2; - -import java.io.BufferedReader; -import java.io.CharArrayReader; -import java.io.CharArrayWriter; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.security.DigestException; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import ch.ethz.ssh2.crypto.Base64; -import ch.ethz.ssh2.crypto.SecureRandomFix; -import ch.ethz.ssh2.crypto.digest.Digest; -import ch.ethz.ssh2.crypto.digest.HMAC; -import ch.ethz.ssh2.crypto.digest.MD5; -import ch.ethz.ssh2.crypto.digest.SHA1; - -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.interfaces.DSAPublicKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPublicKey; -import ch.ethz.ssh2.signature.DSASHA1Verify; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; -import ch.ethz.ssh2.signature.RSASHA1Verify; -import ch.ethz.ssh2.util.StringEncoder; - -/** - * The <code>KnownHosts</code> class is a handy tool to verify received server hostkeys - * based on the information in <code>known_hosts</code> files (the ones used by OpenSSH). - * <p/> - * It offers basically an in-memory database for known_hosts entries, as well as some - * helper functions. Entries from a <code>known_hosts</code> file can be loaded at construction time. - * It is also possible to add more keys later (e.g., one can parse different - * <code>known_hosts<code> files). - * <p/> - * It is a thread safe implementation, therefore, you need only to instantiate one - * <code>KnownHosts</code> for your whole application. - * - * @author Christian Plattner - * @version $Id: KnownHosts.java 152 2014-04-28 11:02:23Z dkocher@sudo.ch $ - */ - -public class KnownHosts { - public static final int HOSTKEY_IS_OK = 0; - public static final int HOSTKEY_IS_NEW = 1; - public static final int HOSTKEY_HAS_CHANGED = 2; - - private class KnownHostsEntry { - String[] patterns; - PublicKey key; - - KnownHostsEntry(String[] patterns, PublicKey key) { - this.patterns = patterns; - this.key = key; - } - } - - private final LinkedList<KnownHostsEntry> publicKeys = new LinkedList<KnownHosts.KnownHostsEntry>(); - - public KnownHosts() { - } - - public KnownHosts(char[] knownHostsData) throws IOException { - initialize(knownHostsData); - } - - public KnownHosts(String knownHosts) throws IOException { - initialize(new File(knownHosts)); - } - - public KnownHosts(File knownHosts) throws IOException { - initialize(knownHosts); - } - - /** - * Adds a single public key entry to the database. Note: this will NOT add the public key - * to any physical file (e.g., "~/.ssh/known_hosts") - use <code>addHostkeyToFile()</code> for that purpose. - * This method is designed to be used in a {@link ServerHostKeyVerifier}. - * - * @param hostnames a list of hostname patterns - at least one most be specified. Check out the - * OpenSSH sshd man page for a description of the pattern matching algorithm. - * @param serverHostKeyAlgorithm as passed to the {@link ServerHostKeyVerifier}. - * @param serverHostKey as passed to the {@link ServerHostKeyVerifier}. - * @throws IOException - */ - public void addHostkey(String hostnames[], String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { - if (hostnames == null) { - throw new IllegalArgumentException("hostnames may not be null"); - } - - if ("ssh-rsa".equals(serverHostKeyAlgorithm)) { - RSAPublicKey rpk = RSASHA1Verify.decodeSSHRSAPublicKey(serverHostKey); - - synchronized (publicKeys) { - publicKeys.add(new KnownHostsEntry(hostnames, rpk)); - } - } - else if ("ssh-dss".equals(serverHostKeyAlgorithm)) { - DSAPublicKey dpk = DSASHA1Verify.decodeSSHDSAPublicKey(serverHostKey); - - synchronized (publicKeys) { - publicKeys.add(new KnownHostsEntry(hostnames, dpk)); - } - } - else if (serverHostKeyAlgorithm.startsWith("ecdsa-sha2-")) { - ECPublicKey epk = ECDSASHA2Verify.decodeSSHECDSAPublicKey(serverHostKey); - - synchronized (publicKeys) { - publicKeys.add(new KnownHostsEntry(hostnames, epk)); - } - } - else { - throw new IOException(String.format("Unknown host key type %s", serverHostKeyAlgorithm)); - } - } - - /** - * Parses the given known_hosts data and adds entries to the database. - * - * @param knownHostsData - * @throws IOException - */ - public void addHostkeys(char[] knownHostsData) throws IOException { - initialize(knownHostsData); - } - - /** - * Parses the given known_hosts file and adds entries to the database. - * - * @param knownHosts - * @throws IOException - */ - public void addHostkeys(File knownHosts) throws IOException { - initialize(knownHosts); - } - - /** - * Generate the hashed representation of the given hostname. Useful for adding entries - * with hashed hostnames to a known_hosts file. (see -H option of OpenSSH key-gen). - * - * @param hostname - * @return the hashed representation, e.g., "|1|cDhrv7zwEUV3k71CEPHnhHZezhA=|Xo+2y6rUXo2OIWRAYhBOIijbJMA=" - */ - public static String createHashedHostname(String hostname) throws IOException { - SHA1 sha1 = new SHA1(); - byte[] salt = new byte[sha1.getDigestLength()]; - new SecureRandomFix().nextBytes(salt); - byte[] hash; - - try { - hash = hmacSha1Hash(salt, hostname); - } - catch (IOException e) { - throw new IOException(e); - } - - String base64_salt = new String(Base64.encode(salt)); - String base64_hash = new String(Base64.encode(hash)); - return String.format("|1|%s|%s", base64_salt, base64_hash); - } - - private static byte[] hmacSha1Hash(byte[] salt, String hostname) throws IOException { - SHA1 sha1 = new SHA1(); - - if (salt.length != sha1.getDigestLength()) { - throw new IllegalArgumentException("Salt has wrong length (" + salt.length + ")"); - } - - try { - HMAC hmac = new HMAC(sha1, salt, salt.length); - hmac.update(StringEncoder.GetBytes(hostname)); - byte[] dig = new byte[hmac.getDigestLength()]; - hmac.digest(dig); - return dig; - } - catch (DigestException e) { - throw new IOException(e); - } - } - - private boolean checkHashed(String entry, String hostname) { - if (entry.startsWith("|1|") == false) { - return false; - } - - int delim_idx = entry.indexOf('|', 3); - - if (delim_idx == -1) { - return false; - } - - String salt_base64 = entry.substring(3, delim_idx); - String hash_base64 = entry.substring(delim_idx + 1); - byte[] salt; - byte[] hash; - - try { - salt = Base64.decode(salt_base64.toCharArray()); - hash = Base64.decode(hash_base64.toCharArray()); - } - catch (IOException e) { - return false; - } - - SHA1 sha1 = new SHA1(); - - if (salt.length != sha1.getDigestLength()) { - return false; - } - - byte[] dig = new byte[0]; - - try { - dig = hmacSha1Hash(salt, hostname); - } - catch (IOException e) { - return false; - } - - for (int i = 0; i < dig.length; i++) { - if (dig[i] != hash[i]) { - return false; - } - } - - return true; - } - - private int checkKey(String remoteHostname, PublicKey remoteKey) { - int result = HOSTKEY_IS_NEW; - - synchronized (publicKeys) { - for (KnownHostsEntry ke : publicKeys) { - if (hostnameMatches(ke.patterns, remoteHostname) == false) { - continue; - } - - boolean res = matchKeys(ke.key, remoteKey); - - if (res == true) { - return HOSTKEY_IS_OK; - } - - result = HOSTKEY_HAS_CHANGED; - } - } - - return result; - } - - private List<Object> getAllKeys(String hostname) { - List<Object> keys = new ArrayList<Object>(); - - synchronized (publicKeys) { - for (KnownHostsEntry ke : publicKeys) { - if (hostnameMatches(ke.patterns, hostname) == false) { - continue; - } - - keys.add(ke.key); - } - } - - return keys; - } - - /** - * Try to find the preferred order of hostkey algorithms for the given hostname. - * Based on the type of hostkey that is present in the internal database - * (i.e., either <code>ssh-rsa</code> or <code>ssh-dss</code>) - * an ordered list of hostkey algorithms is returned which can be passed - * to <code>Connection.setServerHostKeyAlgorithms</code>. - * - * @param hostname - * @return <code>null</code> if no key for the given hostname is present or - * there are keys of multiple types present for the given hostname. Otherwise, - * an array with hostkey algorithms is returned (i.e., an array of length 2). - */ - public String[] getPreferredServerHostkeyAlgorithmOrder(String hostname) { - String[] algos = recommendHostkeyAlgorithms(hostname); - - if (algos != null) { - return algos; - } - - InetAddress[] ipAdresses; - - try { - ipAdresses = InetAddress.getAllByName(hostname); - } - catch (UnknownHostException e) { - return null; - } - - for (int i = 0; i < ipAdresses.length; i++) { - algos = recommendHostkeyAlgorithms(ipAdresses[i].getHostAddress()); - - if (algos != null) { - return algos; - } - } - - return null; - } - - private boolean hostnameMatches(String[] hostpatterns, String hostname) { - boolean isMatch = false; - boolean negate; - hostname = hostname.toLowerCase(); - - for (int k = 0; k < hostpatterns.length; k++) { - if (hostpatterns[k] == null) { - continue; - } - - String pattern; - - /* In contrast to OpenSSH we also allow negated hash entries (as well as hashed - * entries in lines with multiple entries). - */ - - if ((hostpatterns[k].length() > 0) && (hostpatterns[k].charAt(0) == '!')) { - pattern = hostpatterns[k].substring(1); - negate = true; - } - else { - pattern = hostpatterns[k]; - negate = false; - } - - /* Optimize, no need to check this entry */ - - if ((isMatch) && (negate == false)) { - continue; - } - - /* Now compare */ - - if (pattern.charAt(0) == '|') { - if (checkHashed(pattern, hostname)) { - if (negate) { - return false; - } - - isMatch = true; - } - } - else { - pattern = pattern.toLowerCase(); - - if ((pattern.indexOf('?') != -1) || (pattern.indexOf('*') != -1)) { - if (pseudoRegex(pattern.toCharArray(), 0, hostname.toCharArray(), 0)) { - if (negate) { - return false; - } - - isMatch = true; - } - } - else if (pattern.compareTo(hostname) == 0) { - if (negate) { - return false; - } - - isMatch = true; - } - } - } - - return isMatch; - } - - private void initialize(char[] knownHostsData) throws IOException { - BufferedReader br = new BufferedReader(new CharArrayReader(knownHostsData)); - - while (true) { - String line = br.readLine(); - - if (line == null) { - break; - } - - line = line.trim(); - - if (line.startsWith("#")) { - continue; - } - - String[] arr = line.split(" "); - - if (arr.length >= 3) { - if ((arr[1].compareTo("ssh-rsa") == 0) || - (arr[1].compareTo("ssh-dss") == 0) || - (arr[1].startsWith("ecdsa-sha2-"))) { - String[] hostnames = arr[0].split(","); - byte[] msg = Base64.decode(arr[2].toCharArray()); - - try { - addHostkey(hostnames, arr[1], msg); - } - catch (IOException e) { - continue; - } - } - } - } - } - - private void initialize(File knownHosts) throws IOException { - char[] buff = new char[512]; - CharArrayWriter cw = new CharArrayWriter(); - knownHosts.createNewFile(); - FileReader fr = new FileReader(knownHosts); - - while (true) { - int len = fr.read(buff); - - if (len < 0) { - break; - } - - cw.write(buff, 0, len); - } - - fr.close(); - initialize(cw.toCharArray()); - } - - private final boolean matchKeys(PublicKey key1, PublicKey key2) { - return key1.equals(key2); - } - - private boolean pseudoRegex(char[] pattern, int i, char[] match, int j) { - /* This matching logic is equivalent to the one present in OpenSSH 4.1 */ - while (true) { - /* Are we at the end of the pattern? */ - if (pattern.length == i) { - return (match.length == j); - } - - if (pattern[i] == '*') { - i++; - - if (pattern.length == i) { - return true; - } - - if ((pattern[i] != '*') && (pattern[i] != '?')) { - while (true) { - if ((pattern[i] == match[j]) && pseudoRegex(pattern, i + 1, match, j + 1)) { - return true; - } - - j++; - - if (match.length == j) { - return false; - } - } - } - - while (true) { - if (pseudoRegex(pattern, i, match, j)) { - return true; - } - - j++; - - if (match.length == j) { - return false; - } - } - } - - if (match.length == j) { - return false; - } - - if ((pattern[i] != '?') && (pattern[i] != match[j])) { - return false; - } - - i++; - j++; - } - } - - private String[] recommendHostkeyAlgorithms(String hostname) { - String preferredAlgo = null; - List<Object> keys = getAllKeys(hostname); - - for (Object key : keys) { - String thisAlgo; - - if (key instanceof RSAPublicKey) { - thisAlgo = "ssh-rsa"; - } - else if (key instanceof DSAPublicKey) { - thisAlgo = "ssh-dss"; - } - else if (key instanceof ECPublicKey) { - ECPublicKey ecPub = (ECPublicKey) key; - String keyType = ECDSASHA2Verify.getCurveName(ecPub.getParams().getCurve().getField().getFieldSize()); - thisAlgo = ECDSASHA2Verify.ECDSA_SHA2_PREFIX + keyType; - } - else { - continue; - } - - if (preferredAlgo != null) { - /* If we find different key types, then return null */ - if (preferredAlgo.compareTo(thisAlgo) != 0) { - return null; - } - } - else { - preferredAlgo = thisAlgo; - } - } - - /* If we did not find anything that we know of, return null */ - - if (preferredAlgo == null) { - return null; - } - - /* Now put the preferred algo to the start of the array. - * You may ask yourself why we do it that way - basically, we could just - * return only the preferred algorithm: since we have a saved key of that - * type (sent earlier from the remote host), then that should work out. - * However, imagine that the server is (for whatever reasons) not offering - * that type of hostkey anymore (e.g., "ssh-rsa" was disabled and - * now "ssh-dss" is being used). If we then do not let the server send us - * a fresh key of the new type, then we shoot ourself into the foot: - * the connection cannot be established and hence the user cannot decide - * if he/she wants to accept the new key. - */ - - if (preferredAlgo.equals("ssh-rsa")) { - return new String[] {"ssh-rsa", "ssh-dss", "ecdsa-sha2-nistp256"}; - } - - return new String[] {"ssh-dss", "ssh-rsa", "ecdsa-sha2-nistp256"}; - } - - /** - * Checks the internal hostkey database for the given hostkey. - * If no matching key can be found, then the hostname is resolved to an IP address - * and the search is repeated using that IP address. - * - * @param hostname the server's hostname, will be matched with all hostname patterns - * @param serverHostKeyAlgorithm type of hostkey, either <code>ssh-rsa</code> or <code>ssh-dss</code> - * @param serverHostKey the key blob - * @return <ul> - * <li><code>HOSTKEY_IS_OK</code>: the given hostkey matches an entry for the given hostname</li> - * <li><code>HOSTKEY_IS_NEW</code>: no entries found for this hostname and this type of hostkey</li> - * <li><code>HOSTKEY_HAS_CHANGED</code>: hostname is known, but with another key of the same type - * (man-in-the-middle attack?)</li> - * </ul> - * @throws IOException if the supplied key blob cannot be parsed or does not match the given hostkey type. - */ - public int verifyHostkey(String hostname, String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { - PublicKey remoteKey; - - if ("ssh-rsa".equals(serverHostKeyAlgorithm)) { - remoteKey = RSASHA1Verify.decodeSSHRSAPublicKey(serverHostKey); - } - else if ("ssh-dss".equals(serverHostKeyAlgorithm)) { - remoteKey = DSASHA1Verify.decodeSSHDSAPublicKey(serverHostKey); - } - else if (serverHostKeyAlgorithm.startsWith("ecdsa-sha2-")) { - remoteKey = ECDSASHA2Verify.decodeSSHECDSAPublicKey(serverHostKey); - } - else { - throw new IllegalArgumentException("Unknown hostkey type " + serverHostKeyAlgorithm); - } - - int result = checkKey(hostname, remoteKey); - - if (result == HOSTKEY_IS_OK) { - return result; - } - - InetAddress[] ipAdresses; - - try { - ipAdresses = InetAddress.getAllByName(hostname); - } - catch (UnknownHostException e) { - return result; - } - - for (int i = 0; i < ipAdresses.length; i++) { - int newresult = checkKey(ipAdresses[i].getHostAddress(), remoteKey); - - if (newresult == HOSTKEY_IS_OK) { - return newresult; - } - - if (newresult == HOSTKEY_HAS_CHANGED) { - result = HOSTKEY_HAS_CHANGED; - } - } - - return result; - } - - /** - * Adds a single public key entry to the a known_hosts file. - * This method is designed to be used in a {@link ServerHostKeyVerifier}. - * - * @param knownHosts the file where the publickey entry will be appended. - * @param hostnames a list of hostname patterns - at least one most be specified. Check out the - * OpenSSH sshd man page for a description of the pattern matching algorithm. - * @param serverHostKeyAlgorithm as passed to the {@link ServerHostKeyVerifier}. - * @param serverHostKey as passed to the {@link ServerHostKeyVerifier}. - * @throws IOException - */ - public static void addHostkeyToFile(File knownHosts, String[] hostnames, String serverHostKeyAlgorithm, - byte[] serverHostKey) throws IOException { - if ((hostnames == null) || (hostnames.length == 0)) { - throw new IllegalArgumentException("Need at least one hostname specification"); - } - - if ((serverHostKeyAlgorithm == null) || (serverHostKey == null)) { - throw new IllegalArgumentException(); - } - - CharArrayWriter writer = new CharArrayWriter(); - - for (int i = 0; i < hostnames.length; i++) { - if (i != 0) { - writer.write(','); - } - - writer.write(hostnames[i]); - } - - writer.write(' '); - writer.write(serverHostKeyAlgorithm); - writer.write(' '); - writer.write(Base64.encode(serverHostKey)); - writer.write("\n"); - char[] entry = writer.toCharArray(); - RandomAccessFile raf = new RandomAccessFile(knownHosts, "rw"); - long len = raf.length(); - - if (len > 0) { - raf.seek(len - 1); - int last = raf.read(); - - if (last != '\n') { - raf.write('\n'); - } - } - - raf.write(StringEncoder.GetBytes(new String(entry))); - raf.close(); - } - - /** - * Generates a "raw" fingerprint of a hostkey. - * - * @param type either "md5" or "sha1" - * @param keyType either "ssh-rsa" or "ssh-dss" or "ecdsa-sha2..." - * @param hostkey the hostkey - * @return the raw fingerprint - */ - static private byte[] rawFingerPrint(String type, String keyType, byte[] hostkey) throws IOException { - Digest dig; - - if ("md5".equals(type)) { - dig = new MD5(); - } - else if ("sha1".equals(type)) { - dig = new SHA1(); - } - else { - throw new IllegalArgumentException("Unknown hash type " + type); - } - - if ("ssh-rsa".equals(keyType)) { - } - else if ("ssh-dss".equals(keyType)) { - } - else if (keyType.startsWith("ecdsa-sha2-")) { - } - else { - throw new IllegalArgumentException("Unknown key type " + keyType); - } - - if (hostkey == null) { - throw new IllegalArgumentException("hostkey is null"); - } - - dig.update(hostkey); - byte[] res = new byte[dig.getDigestLength()]; - - try { - dig.digest(res); - } - catch (DigestException e) { - throw new IOException(e); - } - - return res; - } - - /** - * Convert a raw fingerprint to hex representation (XX:YY:ZZ...). - * - * @param fingerprint raw fingerprint - * @return the hex representation - */ - static private String rawToHexFingerprint(byte[] fingerprint) { - final char[] alpha = "0123456789abcdef".toCharArray(); - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < fingerprint.length; i++) { - if (i != 0) { - sb.append(':'); - } - - int b = fingerprint[i] & 0xff; - sb.append(alpha[b >> 4]); - sb.append(alpha[b & 15]); - } - - return sb.toString(); - } - - /** - * Convert a raw fingerprint to bubblebabble representation. - * - * @param raw raw fingerprint - * @return the bubblebabble representation - */ - static private String rawToBubblebabbleFingerprint(byte[] raw) { - final char[] v = "aeiouy".toCharArray(); - final char[] c = "bcdfghklmnprstvzx".toCharArray(); - StringBuilder sb = new StringBuilder(); - int seed = 1; - int rounds = (raw.length / 2) + 1; - sb.append('x'); - - for (int i = 0; i < rounds; i++) { - if (((i + 1) < rounds) || ((raw.length) % 2 != 0)) { - sb.append(v[(((raw[2 * i] >> 6) & 3) + seed) % 6]); - sb.append(c[(raw[2 * i] >> 2) & 15]); - sb.append(v[((raw[2 * i] & 3) + (seed / 6)) % 6]); - - if ((i + 1) < rounds) { - sb.append(c[(((raw[(2 * i) + 1])) >> 4) & 15]); - sb.append('-'); - sb.append(c[(((raw[(2 * i) + 1]))) & 15]); - // As long as seed >= 0, seed will be >= 0 afterwards - seed = ((seed * 5) + (((raw[2 * i] & 0xff) * 7) + (raw[(2 * i) + 1] & 0xff))) % 36; - } - } - else { - sb.append(v[seed % 6]); // seed >= 0, therefore index positive - sb.append('x'); - sb.append(v[seed / 6]); - } - } - - sb.append('x'); - return sb.toString(); - } - - /** - * Convert a ssh2 key-blob into a human readable hex fingerprint. - * Generated fingerprints are identical to those generated by OpenSSH. - * <p/> - * Example fingerprint: d0:cb:76:19:99:5a:03:fc:73:10:70:93:f2:44:63:47. - * - * @param keytype either "ssh-rsa" or "ssh-dss" or "ecdsa-sha2..." - * @param publickey key blob - * @return Hex fingerprint - */ - public static String createHexFingerprint(String keytype, byte[] publickey) throws IOException { - byte[] raw = rawFingerPrint("md5", keytype, publickey); - return rawToHexFingerprint(raw); - } - - /** - * Convert a ssh2 key-blob into a human readable bubblebabble fingerprint. - * The used bubblebabble algorithm (taken from OpenSSH) generates fingerprints - * that are easier to remember for humans. - * <p/> - * Example fingerprint: xofoc-bubuz-cazin-zufyl-pivuk-biduk-tacib-pybur-gonar-hotat-lyxux. - * - * @param keytype either "ssh-rsa" or "ssh-dss" - * @param publickey key data - * @return Bubblebabble fingerprint - */ - public static String createBubblebabbleFingerprint(String keytype, byte[] publickey) throws IOException { - byte[] raw = rawFingerPrint("sha1", keytype, publickey); - return rawToBubblebabbleFingerprint(raw); - } -}
--- a/src/ch/ethz/ssh2/LocalPortForwarder.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; - -import ch.ethz.ssh2.channel.ChannelManager; -import ch.ethz.ssh2.channel.LocalAcceptThread; - -/** - * A <code>LocalPortForwarder</code> forwards TCP/IP connections to a local - * port via the secure tunnel to another host (which may or may not be identical - * to the remote SSH-2 server). Checkout {@link Connection#createLocalPortForwarder(int, String, int)} - * on how to create one. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class LocalPortForwarder { - final ChannelManager cm; - - final String host_to_connect; - - final int port_to_connect; - - final LocalAcceptThread lat; - - LocalPortForwarder(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) - throws IOException { - this.cm = cm; - this.host_to_connect = host_to_connect; - this.port_to_connect = port_to_connect; - lat = new LocalAcceptThread(cm, local_port, host_to_connect, port_to_connect); - lat.setDaemon(true); - lat.start(); - } - - LocalPortForwarder(ChannelManager cm, InetSocketAddress addr, String host_to_connect, int port_to_connect) - throws IOException { - this.cm = cm; - this.host_to_connect = host_to_connect; - this.port_to_connect = port_to_connect; - lat = new LocalAcceptThread(cm, addr, host_to_connect, port_to_connect); - lat.setDaemon(true); - lat.start(); - } - - /** - * Return the local socket address of the {@link ServerSocket} used to accept connections. - * @return - */ - public InetSocketAddress getLocalSocketAddress() { - return (InetSocketAddress) lat.getServerSocket().getLocalSocketAddress(); - } - - /** - * Stop TCP/IP forwarding of newly arriving connections. - * - * @throws IOException - */ - public void close() throws IOException { - lat.stopWorking(); - } -}
--- a/src/ch/ethz/ssh2/LocalStreamForwarder.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; - -import ch.ethz.ssh2.channel.Channel; -import ch.ethz.ssh2.channel.ChannelManager; - -/** - * A <code>LocalStreamForwarder</code> forwards an Input- and Outputstream - * pair via the secure tunnel to another host (which may or may not be identical - * to the remote SSH-2 server). - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class LocalStreamForwarder { - private ChannelManager cm; - - private Channel cn; - - LocalStreamForwarder(ChannelManager cm, String host_to_connect, int port_to_connect) throws IOException { - this.cm = cm; - cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, - InetAddress.getLocalHost().getHostAddress(), 0); - } - - /** - * @return An <code>InputStream</code> object. - * @throws IOException - */ - public InputStream getInputStream() throws IOException { - return cn.getStdoutStream(); - } - - /** - * Get the OutputStream. Please be aware that the implementation MAY use an - * internal buffer. To make sure that the buffered data is sent over the - * tunnel, you have to call the <code>flush</code> method of the - * <code>OutputStream</code>. To signal EOF, please use the - * <code>close</code> method of the <code>OutputStream</code>. - * - * @return An <code>OutputStream</code> object. - * @throws IOException - */ - public OutputStream getOutputStream() throws IOException { - return cn.getStdinStream(); - } - - /** - * Close the underlying SSH forwarding channel and free up resources. - * You can also use this method to force the shutdown of the underlying - * forwarding channel. Pending output (OutputStream not flushed) will NOT - * be sent. Pending input (InputStream) can still be read. If the shutdown - * operation is already in progress (initiated from either side), then this - * call is a no-op. - * - * @throws IOException - */ - public void close() throws IOException { - cm.closeChannel(cn, "Closed due to user request.", true); - } -}
--- a/src/ch/ethz/ssh2/PacketFormatException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -package ch.ethz.ssh2; - -import java.io.IOException; - -/** - * @version $Id: PacketFormatException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class PacketFormatException extends IOException { - - public PacketFormatException(String message) { - super(message); - } -}
--- a/src/ch/ethz/ssh2/PacketListener.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2011 David Kocher. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * @version $Id: PacketListener.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public interface PacketListener { - void read(String packet); - - void write(String packet); -}
--- a/src/ch/ethz/ssh2/PacketTypeException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -package ch.ethz.ssh2; - -import java.io.IOException; - -/** - * @version $Id: PacketTypeException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class PacketTypeException extends IOException { - - public PacketTypeException() { - } - - public PacketTypeException(final String message) { - super(message); - } - - public PacketTypeException(final int packet) { - super(String.format("The SFTP server sent an unexpected packet type (%d)", packet)); - } - - public PacketTypeException(final int packet, final String message) { - super(String.format("The SFTP server sent an invalid packet type (%d). %s", packet, message)); - } -}
--- a/src/ch/ethz/ssh2/ProxyData.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * An abstract marker interface implemented by all proxy data implementations. - * - * @see HTTPProxyData - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public abstract interface ProxyData { -}
--- a/src/ch/ethz/ssh2/PtySettings.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * PTY settings for a SSH session. Zero dimension parameters are ignored. The character/row dimensions - * override the pixel dimensions (when nonzero). Pixel dimensions refer to - * the drawable area of the window. The dimension parameters are only - * informational. The encoding of terminal modes (parameter - * <code>terminal_modes</code>) is described in RFC4254. - * - * @author Christian - */ -public class PtySettings { - /** - * TERM environment variable value (e.g., vt100) - */ - public String term; - - /** - * Terminal width, characters (e.g., 80) - */ - public int term_width_characters; - - /** - * Terminal height, rows (e.g., 24) - */ - public int term_height_characters; - - /** - * Terminal width, pixels (e.g., 640) - */ - public int term_width_pixels; - - /** - * Terminal height, pixels (e.g., 480) - */ - public int term_height_pixels; - - /** - * Encoded terminal modes - */ - public byte[] terminal_modes; -}
--- a/src/ch/ethz/ssh2/RequestMismatchException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package ch.ethz.ssh2; - -import java.io.IOException; - -/** - * @version $Id: RequestMismatchException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class RequestMismatchException extends IOException { - - public RequestMismatchException() { - super("The server sent an invalid id field."); - } - - public RequestMismatchException(final String message) { - super(message); - } -}
--- a/src/ch/ethz/ssh2/SCPClient.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,742 +0,0 @@ -package ch.ethz.ssh2; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; - -/** - * A very basic <code>SCPClient</code> that can be used to copy files from/to - * the SSH-2 server. On the server side, the "scp" program must be in the PATH. - * <p/> - * This scp client is thread safe - you can download (and upload) different sets - * of files concurrently without any troubles. The <code>SCPClient</code> is - * actually mapping every request to a distinct {@link ch.ethz.ssh2.Session}. - * - * @author Christian Plattner, plattner@inf.ethz.ch - * @version $Id: SCPClient.java 85 2014-04-07 14:05:09Z dkocher@sudo.ch $ - */ - -public class SCPClient { - Connection conn; - - String charsetName = null; - - /** - * Set the charset used to convert between Java Unicode Strings and byte encodings - * used by the server for paths and file names. - * - * @param charset the name of the charset to be used or <code>null</code> to use the platform's - * default encoding. - * @throws IOException - * @see #getCharset() - */ - public void setCharset(String charset) throws IOException { - if (charset == null) { - charsetName = charset; - return; - } - - try { - Charset.forName(charset); - } - catch (UnsupportedCharsetException e) { - throw new IOException("This charset is not supported", e); - } - - charsetName = charset; - } - - /** - * The currently used charset for filename encoding/decoding. - * - * @return The name of the charset (<code>null</code> if the platform's default charset is being used) - * @see #setCharset(String) - */ - public String getCharset() { - return charsetName; - } - - public class LenNamePair { - public long length; - String filename; - } - - public SCPClient(Connection conn) { - if (conn == null) - throw new IllegalArgumentException("Cannot accept null argument!"); - - this.conn = conn; - } - - protected void readResponse(InputStream is) throws IOException { - int c = is.read(); - - if (c == 0) - return; - - if (c == -1) - throw new IOException("Remote scp terminated unexpectedly."); - - if ((c != 1) && (c != 2)) - throw new IOException("Remote scp sent illegal error code."); - - if (c == 2) - throw new IOException("Remote scp terminated with error."); - - String err = receiveLine(is); - throw new IOException("Remote scp terminated with error (" + err + ")."); - } - - protected String receiveLine(InputStream is) throws IOException { - StringBuilder sb = new StringBuilder(30); - - while (true) { - /* This is a random limit - if your path names are longer, then adjust it */ - if (sb.length() > 8192) - throw new IOException("Remote scp sent a too long line"); - - int c = is.read(); - - if (c < 0) - throw new IOException("Remote scp terminated unexpectedly."); - - if (c == '\n') - break; - - sb.append((char) c); - } - - return sb.toString(); - } - - protected LenNamePair parseCLine(String line) throws IOException { - /* Minimum line: "xxxx y z" ---> 8 chars */ - if (line.length() < 8) - throw new IOException("Malformed C line sent by remote SCP binary, line too short."); - - if ((line.charAt(4) != ' ') || (line.charAt(5) == ' ')) - throw new IOException("Malformed C line sent by remote SCP binary."); - - int length_name_sep = line.indexOf(' ', 5); - - if (length_name_sep == -1) - throw new IOException("Malformed C line sent by remote SCP binary."); - - String length_substring = line.substring(5, length_name_sep); - String name_substring = line.substring(length_name_sep + 1); - - if ((length_substring.length() <= 0) || (name_substring.length() <= 0)) - throw new IOException("Malformed C line sent by remote SCP binary."); - - if ((6 + length_substring.length() + name_substring.length()) != line.length()) - throw new IOException("Malformed C line sent by remote SCP binary."); - - final long len; - - try { - len = Long.parseLong(length_substring); - } - catch (NumberFormatException e) { - throw new IOException("Malformed C line sent by remote SCP binary, cannot parse file length."); - } - - if (len < 0) - throw new IOException("Malformed C line sent by remote SCP binary, illegal file length."); - - LenNamePair lnp = new LenNamePair(); - lnp.length = len; - lnp.filename = name_substring; - return lnp; - } - - /** - * The session for opened for this SCP transfer must be closed using - * SCPOutputStream#close - * - * @param remoteFile - * @param length The size of the file to send - * @param remoteTargetDirectory - * @param mode - * @return - * @throws IOException - */ - public SCPOutputStream put(final String remoteFile, long length, String remoteTargetDirectory, String mode) - throws IOException { - Session sess = null; - - if (null == remoteFile) - throw new IllegalArgumentException("Null argument."); - - if (null == remoteTargetDirectory) - remoteTargetDirectory = ""; - - if (null == mode) - mode = "0600"; - - if (mode.length() != 4) - throw new IllegalArgumentException("Invalid mode."); - - for (int i = 0; i < mode.length(); i++) - if (Character.isDigit(mode.charAt(i)) == false) - throw new IllegalArgumentException("Invalid mode."); - - remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; - String cmd = "scp -t -d \"" + remoteTargetDirectory + "\""; - sess = conn.openSession(); - sess.execCommand(cmd, charsetName); - return new SCPOutputStream(this, sess, remoteFile, length, mode); - } - - /** - * The session for opened for this SCP transfer must be closed using - * SCPInputStream#close - * - * @param remoteFile - * @return - * @throws IOException - */ - public SCPInputStream get(final String remoteFile) throws IOException { - Session sess = null; - - if (null == remoteFile) - throw new IllegalArgumentException("Null argument."); - - if (remoteFile.length() == 0) - throw new IllegalArgumentException("Cannot accept empty filename."); - - String cmd = "scp -f"; - cmd += (" \"" + remoteFile + "\""); - sess = conn.openSession(); - sess.execCommand(cmd, charsetName); - return new SCPInputStream(this, sess); - } - private void sendBytes(Session sess, byte[] data, String fileName, String mode) throws IOException { - OutputStream os = sess.getStdin(); - InputStream is = new BufferedInputStream(sess.getStdout(), 512); - readResponse(is); - String cline = "C" + mode + " " + data.length + " " + fileName + "\n"; - os.write(cline.getBytes("ISO-8859-1")); - os.flush(); - readResponse(is); - os.write(data, 0, data.length); - os.write(0); - os.flush(); - readResponse(is); - os.write("E\n".getBytes("ISO-8859-1")); - os.flush(); - } - - private void sendFiles(Session sess, String[] files, String[] remoteFiles, String mode) throws IOException { - byte[] buffer = new byte[8192]; - OutputStream os = new BufferedOutputStream(sess.getStdin(), 40000); - InputStream is = new BufferedInputStream(sess.getStdout(), 512); - readResponse(is); - - for (int i = 0; i < files.length; i++) { - File f = new File(files[i]); - long remain = f.length(); - String remoteName; - - if ((remoteFiles != null) && (remoteFiles.length > i) && (remoteFiles[i] != null)) - remoteName = remoteFiles[i]; - else - remoteName = f.getName(); - - String cline = "C" + mode + " " + remain + " " + remoteName + "\n"; - os.write(cline.getBytes("ISO-8859-1")); - os.flush(); - readResponse(is); - FileInputStream fis = null; - - try { - fis = new FileInputStream(f); - - while (remain > 0) { - int trans; - - if (remain > buffer.length) - trans = buffer.length; - else - trans = (int) remain; - - if (fis.read(buffer, 0, trans) != trans) - throw new IOException("Cannot read enough from local file " + files[i]); - - os.write(buffer, 0, trans); - remain -= trans; - } - } - finally { - if (fis != null) - fis.close(); - } - - os.write(0); - os.flush(); - readResponse(is); - } - - os.write("E\n".getBytes("ISO-8859-1")); - os.flush(); - } - - private void receiveFiles(Session sess, OutputStream[] targets) throws IOException { - byte[] buffer = new byte[8192]; - OutputStream os = new BufferedOutputStream(sess.getStdin(), 512); - InputStream is = new BufferedInputStream(sess.getStdout(), 40000); - os.write(0x0); - os.flush(); - - for (int i = 0; i < targets.length; i++) { - LenNamePair lnp = null; - - while (true) { - int c = is.read(); - - if (c < 0) - throw new IOException("Remote scp terminated unexpectedly."); - - String line = receiveLine(is); - - if (c == 'T') { - /* Ignore modification times */ - continue; - } - - if ((c == 1) || (c == 2)) - throw new IOException("Remote SCP error: " + line); - - if (c == 'C') { - lnp = parseCLine(line); - break; - } - - throw new IOException("Remote SCP error: " + ((char) c) + line); - } - - os.write(0x0); - os.flush(); - long remain = lnp.length; - - while (remain > 0) { - int trans; - - if (remain > buffer.length) - trans = buffer.length; - else - trans = (int) remain; - - int this_time_received = is.read(buffer, 0, trans); - - if (this_time_received < 0) { - throw new IOException("Remote scp terminated connection unexpectedly"); - } - - targets[i].write(buffer, 0, this_time_received); - remain -= this_time_received; - } - - readResponse(is); - os.write(0x0); - os.flush(); - } - } - - private void receiveFiles(Session sess, String[] files, String target) throws IOException { - byte[] buffer = new byte[8192]; - OutputStream os = new BufferedOutputStream(sess.getStdin(), 512); - InputStream is = new BufferedInputStream(sess.getStdout(), 40000); - os.write(0x0); - os.flush(); - - for (int i = 0; i < files.length; i++) { - LenNamePair lnp = null; - - while (true) { - int c = is.read(); - - if (c < 0) - throw new IOException("Remote scp terminated unexpectedly."); - - String line = receiveLine(is); - - if (c == 'T') { - /* Ignore modification times */ - continue; - } - - if ((c == 1) || (c == 2)) - throw new IOException("Remote SCP error: " + line); - - if (c == 'C') { - lnp = parseCLine(line); - break; - } - - throw new IOException("Remote SCP error: " + ((char) c) + line); - } - - os.write(0x0); - os.flush(); - File f = new File(target + File.separatorChar + lnp.filename); - FileOutputStream fop = null; - - try { - fop = new FileOutputStream(f); - long remain = lnp.length; - - while (remain > 0) { - int trans; - - if (remain > buffer.length) - trans = buffer.length; - else - trans = (int) remain; - - int this_time_received = is.read(buffer, 0, trans); - - if (this_time_received < 0) { - throw new IOException("Remote scp terminated connection unexpectedly"); - } - - fop.write(buffer, 0, this_time_received); - remain -= this_time_received; - } - } - finally { - if (fop != null) - fop.close(); - } - - readResponse(is); - os.write(0x0); - os.flush(); - } - } - - /** - * Copy a local file to a remote directory, uses mode 0600 when creating the - * file on the remote side. - * - * @param localFile - * Path and name of local file. - * @param remoteTargetDirectory - * Remote target directory. Use an empty string to specify the - * default directory. - * - * @throws IOException - */ - public void put(String localFile, String remoteTargetDirectory) throws IOException { - put(new String[] { localFile }, remoteTargetDirectory, "0600"); - } - - /** - * Copy a set of local files to a remote directory, uses mode 0600 when - * creating files on the remote side. - * - * @param localFiles - * Paths and names of local file names. - * @param remoteTargetDirectory - * Remote target directory. Use an empty string to specify the - * default directory. - * - * @throws IOException - */ - - public void put(String[] localFiles, String remoteTargetDirectory) throws IOException { - put(localFiles, remoteTargetDirectory, "0600"); - } - - /** - * Copy a local file to a remote directory, uses the specified mode when - * creating the file on the remote side. - * - * @param localFile - * Path and name of local file. - * @param remoteTargetDirectory - * Remote target directory. Use an empty string to specify the - * default directory. - * @param mode - * a four digit string (e.g., 0644, see "man chmod", "man open") - * @throws IOException - */ - public void put(String localFile, String remoteTargetDirectory, String mode) throws IOException { - put(new String[] { localFile }, remoteTargetDirectory, mode); - } - - /** - * Copy a local file to a remote directory, uses the specified mode and - * remote filename when creating the file on the remote side. - * - * @param localFile - * Path and name of local file. - * @param remoteFileName - * The name of the file which will be created in the remote - * target directory. - * @param remoteTargetDirectory - * Remote target directory. Use an empty string to specify the - * default directory. - * @param mode - * a four digit string (e.g., 0644, see "man chmod", "man open") - * @throws IOException - */ - public void put(String localFile, String remoteFileName, String remoteTargetDirectory, String mode) - throws IOException { - put(new String[] { localFile }, new String[] { remoteFileName }, remoteTargetDirectory, mode); - } - - /** - * Create a remote file and copy the contents of the passed byte array into - * it. Uses mode 0600 for creating the remote file. - * - * @param data - * the data to be copied into the remote file. - * @param remoteFileName - * The name of the file which will be created in the remote - * target directory. - * @param remoteTargetDirectory - * Remote target directory. Use an empty string to specify the - * default directory. - * @throws IOException - */ - - public void put(byte[] data, String remoteFileName, String remoteTargetDirectory) throws IOException { - put(data, remoteFileName, remoteTargetDirectory, "0600"); - } - - /** - * Create a remote file and copy the contents of the passed byte array into - * it. The method use the specified mode when creating the file on the - * remote side. - * - * @param data - * the data to be copied into the remote file. - * @param remoteFileName - * The name of the file which will be created in the remote - * target directory. - * @param remoteTargetDirectory - * Remote target directory. Use an empty string to specify the - * default directory. - * @param mode - * a four digit string (e.g., 0644, see "man chmod", "man open") - * @throws IOException - */ - public void put(byte[] data, String remoteFileName, String remoteTargetDirectory, String mode) throws IOException { - Session sess = null; - - if ((remoteFileName == null) || (remoteTargetDirectory == null) || (mode == null)) - throw new IllegalArgumentException("Null argument."); - - if (mode.length() != 4) - throw new IllegalArgumentException("Invalid mode."); - - for (int i = 0; i < mode.length(); i++) - if (Character.isDigit(mode.charAt(i)) == false) - throw new IllegalArgumentException("Invalid mode."); - - remoteTargetDirectory = remoteTargetDirectory.trim(); - remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; - String cmd = "scp -t -d " + remoteTargetDirectory; - - try { - sess = conn.openSession(); - sess.execCommand(cmd); - sendBytes(sess, data, remoteFileName, mode); - } - catch (IOException e) { - throw(IOException) new IOException("Error during SCP transfer.").initCause(e); - } - finally { - if (sess != null) - sess.close(); - } - } - - /** - * Copy a set of local files to a remote directory, uses the specified mode - * when creating the files on the remote side. - * - * @param localFiles - * Paths and names of the local files. - * @param remoteTargetDirectory - * Remote target directory. Use an empty string to specify the - * default directory. - * @param mode - * a four digit string (e.g., 0644, see "man chmod", "man open") - * @throws IOException - */ - public void put(String[] localFiles, String remoteTargetDirectory, String mode) throws IOException { - put(localFiles, null, remoteTargetDirectory, mode); - } - - public void put(String[] localFiles, String[] remoteFiles, String remoteTargetDirectory, String mode) - throws IOException { - Session sess = null; - - /* - * remoteFiles may be null, indicating that the local filenames shall be - * used - */ - - if ((localFiles == null) || (remoteTargetDirectory == null) || (mode == null)) - throw new IllegalArgumentException("Null argument."); - - if (mode.length() != 4) - throw new IllegalArgumentException("Invalid mode."); - - for (int i = 0; i < mode.length(); i++) - if (Character.isDigit(mode.charAt(i)) == false) - throw new IllegalArgumentException("Invalid mode."); - - if (localFiles.length == 0) - return; - - remoteTargetDirectory = remoteTargetDirectory.trim(); - remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; - String cmd = "scp -t -d " + remoteTargetDirectory; - - for (int i = 0; i < localFiles.length; i++) { - if (localFiles[i] == null) - throw new IllegalArgumentException("Cannot accept null filename."); - } - - try { - sess = conn.openSession(); - sess.execCommand(cmd); - sendFiles(sess, localFiles, remoteFiles, mode); - } - catch (IOException e) { - throw(IOException) new IOException("Error during SCP transfer.").initCause(e); - } - finally { - if (sess != null) - sess.close(); - } - } - - /** - * Download a file from the remote server to a local directory. - * - * @param remoteFile - * Path and name of the remote file. - * @param localTargetDirectory - * Local directory to put the downloaded file. - * - * @throws IOException - */ - public void get(String remoteFile, String localTargetDirectory) throws IOException { - get(new String[] { remoteFile }, localTargetDirectory); - } - - /** - * Download a file from the remote server and pipe its contents into an - * <code>OutputStream</code>. Please note that, to enable flexible usage - * of this method, the <code>OutputStream</code> will not be closed nor - * flushed. - * - * @param remoteFile - * Path and name of the remote file. - * @param target - * OutputStream where the contents of the file will be sent to. - * @throws IOException - */ - public void get(String remoteFile, OutputStream target) throws IOException { - get(new String[] { remoteFile }, new OutputStream[] { target }); - } - - private void get(String remoteFiles[], OutputStream[] targets) throws IOException { - Session sess = null; - - if ((remoteFiles == null) || (targets == null)) - throw new IllegalArgumentException("Null argument."); - - if (remoteFiles.length != targets.length) - throw new IllegalArgumentException("Length of arguments does not match."); - - if (remoteFiles.length == 0) - return; - - String cmd = "scp -f"; - - for (int i = 0; i < remoteFiles.length; i++) { - if (remoteFiles[i] == null) - throw new IllegalArgumentException("Cannot accept null filename."); - - String tmp = remoteFiles[i].trim(); - - if (tmp.length() == 0) - throw new IllegalArgumentException("Cannot accept empty filename."); - - cmd += (" " + tmp); - } - - try { - sess = conn.openSession(); - sess.execCommand(cmd); - receiveFiles(sess, targets); - } - catch (IOException e) { - throw(IOException) new IOException("Error during SCP transfer.").initCause(e); - } - finally { - if (sess != null) - sess.close(); - } - } - - /** - * Download a set of files from the remote server to a local directory. - * - * @param remoteFiles - * Paths and names of the remote files. - * @param localTargetDirectory - * Local directory to put the downloaded files. - * - * @throws IOException - */ - public void get(String remoteFiles[], String localTargetDirectory) throws IOException { - Session sess = null; - - if ((remoteFiles == null) || (localTargetDirectory == null)) - throw new IllegalArgumentException("Null argument."); - - if (remoteFiles.length == 0) - return; - - String cmd = "scp -f"; - - for (int i = 0; i < remoteFiles.length; i++) { - if (remoteFiles[i] == null) - throw new IllegalArgumentException("Cannot accept null filename."); - - String tmp = remoteFiles[i].trim(); - - if (tmp.length() == 0) - throw new IllegalArgumentException("Cannot accept empty filename."); - - cmd += (" " + tmp); - } - - try { - sess = conn.openSession(); - sess.execCommand(cmd); - receiveFiles(sess, remoteFiles, localTargetDirectory); - } - catch (IOException e) { - throw(IOException) new IOException("Error during SCP transfer.").initCause(e); - } - finally { - if (sess != null) - sess.close(); - } - } -} - -
--- a/src/ch/ethz/ssh2/SCPInputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2011 David Kocher. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * @version $Id: SCPInputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class SCPInputStream extends BufferedInputStream { - private Session session; - - /** - * Bytes remaining to be read from the stream - */ - private long remaining; - - public SCPInputStream(SCPClient client, Session session) throws IOException { - super(session.getStdout()); - this.session = session; - OutputStream os = new BufferedOutputStream(session.getStdin(), 512); - os.write(0x0); - os.flush(); - final SCPClient.LenNamePair lnp; - - while (true) { - int c = session.getStdout().read(); - - if (c < 0) { - throw new IOException("Remote scp terminated unexpectedly."); - } - - String line = client.receiveLine(session.getStdout()); - - if (c == 'T') { - /* Ignore modification times */ - continue; - } - - if ((c == 1) || (c == 2)) { - throw new IOException("Remote SCP error: " + line); - } - - if (c == 'C') { - lnp = client.parseCLine(line); - break; - } - - throw new IOException("Remote SCP error: " + ((char) c) + line); - } - - os.write(0x0); - os.flush(); - this.remaining = lnp.length; - } - - @Override - public int read() throws IOException { - if (!(remaining > 0)) { - return -1; - } - - int b = super.read(); - - if (b < 0) { - throw new IOException("Remote scp terminated connection unexpectedly"); - } - - remaining -= 1; - return b; - } - - @Override - public int read(byte b[], int off, int len) throws IOException { - if (!(remaining > 0)) { - return -1; - } - - int trans = (int) remaining; - - if (remaining > len) { - trans = len; - } - - int read = super.read(b, off, trans); - - if (read < 0) { - throw new IOException("Remote scp terminated connection unexpectedly"); - } - - remaining -= read; - return read; - } - - @Override - public void close() throws IOException { - try { - session.getStdin().write(0x0); - session.getStdin().flush(); - } - finally { - if (session != null) { - session.close(); - } - } - } -}
--- a/src/ch/ethz/ssh2/SCPOutputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2011 David Kocher. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import ch.ethz.ssh2.util.StringEncoder; - -/** - * @version $Id: SCPOutputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class SCPOutputStream extends BufferedOutputStream { - - private Session session; - - private SCPClient scp; - - public SCPOutputStream(SCPClient client, Session session, final String remoteFile, long length, String mode) throws IOException { - super(session.getStdin(), 40000); - this.session = session; - this.scp = client; - InputStream is = new BufferedInputStream(session.getStdout(), 512); - scp.readResponse(is); - String cline = "C" + mode + " " + length + " " + remoteFile + "\n"; - super.write(StringEncoder.GetBytes(cline)); - this.flush(); - scp.readResponse(is); - } - - @Override - public void close() throws IOException { - try { - this.write(0); - this.flush(); - scp.readResponse(session.getStdout()); - this.write(StringEncoder.GetBytes("E\n")); - this.flush(); - } - finally { - if (session != null) - session.close(); - } - } -}
--- a/src/ch/ethz/ssh2/SFTPClient.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ -package ch.ethz.ssh2; - -import java.io.IOException; -import java.util.List; - -/** - * @version $Id: SFTPClient.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public interface SFTPClient { - - /** - * Retrieve the file attributes of an open file. - * - * @param handle a SFTPv3FileHandle handle. - * @return a SFTPv3FileAttributes object. - * @throws IOException - */ - SFTPFileAttributes fstat(SFTPFileHandle handle) throws IOException; - - /** - * Retrieve the file attributes of a file. This method - * follows symbolic links on the server. - * - * @param path See the {@link SFTPClient comment} for the class for more details. - * @return a SFTPv3FileAttributes object. - * @throws IOException - * @see #lstat(String) - */ - SFTPFileAttributes stat(String path) throws IOException; - - /** - * Retrieve the file attributes of a file. This method - * does NOT follow symbolic links on the server. - * - * @param path See the {@link SFTPClient comment} for the class for more details. - * @return a SFTPv3FileAttributes object. - * @throws IOException - * @see #stat(String) - */ - SFTPFileAttributes lstat(String path) throws IOException; - - /** - * Read the target of a symbolic link. Note: OpenSSH (as of version 4.4) gets very upset - * (SSH_FX_BAD_MESSAGE error) if you want to read the target of a file that is not a - * symbolic link. Better check first with {@link #lstat(String)}. - * - * @param path See the {@link SFTPClient comment} for the class for more details. - * @return The target of the link. - * @throws IOException - */ - String readLink(String path) throws IOException; - - /** - * Modify the attributes of a file. Used for operations such as changing - * the ownership, permissions or access times, as well as for truncating a file. - * - * @param path See the {@link SFTPClient comment} for the class for more details. - * @param attr A SFTPv3FileAttributes object. Specifies the modifications to be - * made to the attributes of the file. Empty fields will be ignored. - * @throws IOException - */ - void setstat(String path, SFTPFileAttributes attr) throws IOException; - - /** - * Modify the attributes of a file. Used for operations such as changing - * the ownership, permissions or access times, as well as for truncating a file. - * - * @param handle a SFTPv3FileHandle handle - * @param attr A SFTPv3FileAttributes object. Specifies the modifications to be - * made to the attributes of the file. Empty fields will be ignored. - * @throws IOException - */ - void fsetstat(SFTPFileHandle handle, SFTPFileAttributes attr) throws IOException; - - /** - * Create a symbolic link on the server. Creates a link "src" that points - * to "target". - * - * @param src See the {@link SFTPClient comment} for the class for more details. - * @param target See the {@link SFTPClient comment} for the class for more details. - * @throws IOException - */ - void createSymlink(String src, String target) throws IOException; - - /** - * Create a symbolic link on the server. Creates a link "src" that points - * to "target". - * - * @param src See the {@link SFTPClient comment} for the class for more details. - * @param target See the {@link SFTPClient comment} for the class for more details. - * @throws IOException - */ - void createHardlink(String src, String target) throws IOException; - - /** - * Have the server canonicalize any given path name to an absolute path. - * This is useful for converting path names containing ".." components or - * relative pathnames without a leading slash into absolute paths. - * - * @param path See the {@link SFTPClient comment} for the class for more details. - * @return An absolute path. - * @throws IOException - */ - String canonicalPath(String path) throws IOException; - - void setCharset(String charset) throws IOException; - - String getCharset(); - - SFTPFileHandle openDirectory(String path) throws IOException; - - boolean isConnected(); - - void close(); - - List<? extends SFTPDirectoryEntry> ls(String dirName) throws IOException; - - /** - * Create a new directory. - * - * @param name See the {@link SFTPClient comment} for the class for more details. - * @param posixPermissions the permissions for this directory, e.g., "0700" (remember that - * this is octal noation). The server will likely apply a umask. - * @throws IOException - */ - void mkdir(String name, int posixPermissions) throws IOException; - - /** - * Remove a file. - * - * @param filename See the {@link SFTPClient comment} for the class for more details. - * @throws IOException - */ - void rm(String filename) throws IOException; - - /** - * Remove an empty directory. - * - * @param dirName See the {@link SFTPClient comment} for the class for more details. - * @throws IOException - */ - void rmdir(String dirName) throws IOException; - - /** - * Move a file or directory. - * - * @param oldPath See the {@link SFTPClient comment} for the class for more details. - * @param newPath See the {@link SFTPClient comment} for the class for more details. - * @throws IOException - */ - void mv(String oldPath, String newPath) throws IOException; - - /** - * Create a file and open it for reading and writing. - * Same as {@link #createFile(String, SFTPFileAttributes) createFile(filename, null)}. - * - * @param filename See the {@link SFTPClient comment} for the class for more details. - * @return a SFTPv3FileHandle handle - * @throws IOException - */ - SFTPFileHandle createFile(String filename) throws IOException; - - /** - * Create a file and open it for reading and writing. - * You can specify the default attributes of the file (the server may or may - * not respect your wishes). - * - * @param filename See the {@link SFTPv3Client comment} for the class for more details. - * @param attr may be <code>null</code> to use server defaults. Probably only - * the <code>uid</code>, <code>gid</code> and <code>permissions</code> - * (remember the server may apply a umask) entries of the {@link SFTPv3FileHandle} - * structure make sense. You need only to set those fields where you want - * to override the server's defaults. - * @return a SFTPv3FileHandle handle - * @throws IOException - */ - SFTPFileHandle createFile(String filename, SFTPFileAttributes attr) throws IOException; - - SFTPFileHandle openFile(String filename, int flags) throws IOException; - - /** - * Read bytes from a file in a parallel fashion. As many bytes as you want will be read. - * <p/> - * <ul> - * <li>The server will read as many bytes as it can from the file (up to <code>len</code>), - * and return them.</li> - * <li>If EOF is encountered before reading any data, <code>-1</code> is returned. - * <li>If an error occurs, an exception is thrown</li>. - * <li>For normal disk files, it is guaranteed that the server will return the specified - * number of bytes, or up to end of file. For, e.g., device files this may return - * fewer bytes than requested.</li> - * </ul> - * - * @param handle a SFTPv3FileHandle handle - * @param fileOffset offset (in bytes) in the file - * @param dst the destination byte array - * @param dstoff offset in the destination byte array - * @param len how many bytes to read, 0 < len - * @return the number of bytes that could be read, may be less than requested if - * the end of the file is reached, -1 is returned in case of <code>EOF</code> - * @throws IOException - */ - int read(SFTPFileHandle handle, long fileOffset, byte[] dst, int dstoff, int len) throws IOException; - - /** - * Write bytes to a file. If <code>len</code> > 32768, then the write operation will - * be split into multiple writes. - * - * @param handle a SFTPv3FileHandle handle. - * @param fileOffset offset (in bytes) in the file. - * @param src the source byte array. - * @param srcoff offset in the source byte array. - * @param len how many bytes to write. - * @throws IOException - */ - void write(SFTPFileHandle handle, long fileOffset, byte[] src, int srcoff, int len) throws IOException; - - /** - * Close a file. - * - * @param handle a file handle - * @throws IOException - */ - void closeFile(SFTPFileHandle handle) throws IOException; -}
--- a/src/ch/ethz/ssh2/SFTPDirectoryEntry.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -package ch.ethz.ssh2; - -/** - * @version $Id: SFTPDirectoryEntry.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public interface SFTPDirectoryEntry { - - public String getFilename(); - - public SFTPFileAttributes getAttributes(); - -}
--- a/src/ch/ethz/ssh2/SFTPException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please see the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; - -import ch.ethz.ssh2.sftp.ErrorCodes; - -/** - * Used in combination with the SFTPv3Client. This exception wraps - * error messages sent by the SFTP server. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public class SFTPException extends IOException { - private static final long serialVersionUID = 578654644222421811L; - - private final String sftpErrorMessage; - private final int sftpErrorCode; - - private static String constructMessage(String s, int errorCode) { - String[] detail = ErrorCodes.getDescription(errorCode); - - if (detail == null) - return s + " (UNKNOWN SFTP ERROR CODE)"; - - return s + " (" + detail[0] + ": " + detail[1] + ")"; - } - - SFTPException(String msg, int errorCode) { - super(constructMessage(msg, errorCode)); - sftpErrorMessage = msg; - sftpErrorCode = errorCode; - } - - /** - * Get the error message sent by the server. Often, this - * message does not help a lot (e.g., "failure"). - * - * @return the plain string as sent by the server. - */ - public String getServerErrorMessage() { - return sftpErrorMessage; - } - - /** - * Get the error code sent by the server. - * - * @return an error code as defined in the SFTP specs. - */ - public int getServerErrorCode() { - return sftpErrorCode; - } - - /** - * Get the symbolic name of the error code as given in the SFTP specs. - * - * @return e.g., "SSH_FX_INVALID_FILENAME". - */ - public String getServerErrorCodeSymbol() { - String[] detail = ErrorCodes.getDescription(sftpErrorCode); - - if (detail == null) - return "UNKNOWN SFTP ERROR CODE " + sftpErrorCode; - - return detail[0]; - } - - /** - * Get the description of the error code as given in the SFTP specs. - * - * @return e.g., "The filename is not valid." - */ - public String getServerErrorCodeVerbose() { - String[] detail = ErrorCodes.getDescription(sftpErrorCode); - - if (detail == null) - return "The error code " + sftpErrorCode + " is unknown."; - - return detail[1]; - } -}
--- a/src/ch/ethz/ssh2/SFTPFileAttributes.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package ch.ethz.ssh2; - -/** - * @version $Id: SFTPFileAttributes.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public interface SFTPFileAttributes { - - boolean isDirectory(); - - boolean isRegularFile(); - - boolean isSymlink(); - - byte[] toBytes(); -}
--- a/src/ch/ethz/ssh2/SFTPFileHandle.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -package ch.ethz.ssh2; - -import java.io.IOException; - -/** - * @version $Id: SFTPFileHandle.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class SFTPFileHandle { - - private final SFTPClient client; - - private final byte[] handle; - - protected SFTPFileHandle(final SFTPClient client, final byte[] handle) { - this.client = client; - this.handle = handle; - } - - /** - * Get the SFTPv3Client instance which created this handle. - * - * @return A SFTPv3Client instance. - */ - public SFTPClient getClient() { - return client; - } - - public byte[] getHandle() { - return handle; - } - - public void close() throws IOException { - client.closeFile(this); - } -}
--- a/src/ch/ethz/ssh2/SFTPInputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2011 David Kocher. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; -import java.io.InputStream; - -/** - * @version $Id: SFTPInputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class SFTPInputStream extends InputStream { - - private SFTPFileHandle handle; - - /** - * Offset (in bytes) in the file to read - */ - private long readOffset = 0; - - public SFTPInputStream(SFTPFileHandle handle) { - this.handle = handle; - } - - /** - * Reads up to <code>len</code> bytes of data from the input stream into - * an array of bytes. An attempt is made to read as many as - * <code>len</code> bytes, but a smaller number may be read, possibly - * zero. The number of bytes actually read is returned as an integer. - * - * @see SFTPClient#read(SFTPFileHandle, long, byte[], int, int) - */ - @Override - public int read(byte[] buffer, int offset, int len) throws IOException { - int read = handle.getClient().read(handle, readOffset, buffer, offset, len); - - if (read > 0) { - readOffset += read; - } - - return read; - } - - /** - * Reads the next byte of data from the input stream. The value byte is - * returned as an <code>int</code> in the range <code>0</code> to - * <code>255</code>. If no byte is available because the end of the stream - * has been reached, the value <code>-1</code> is returned. This method - * blocks until input data is available, the end of the stream is detected, - * or an exception is thrown. - * <p/> - * <p> A subclass must provide an implementation of this method. - * - * @return the next byte of data, or <code>-1</code> if the end of the - * stream is reached. - * @throws IOException if an I/O error occurs. - */ - @Override - public int read() throws IOException { - byte[] buffer = new byte[1]; - int b = handle.getClient().read(handle, readOffset, buffer, 0, 1); - - if (b > 0) { - readOffset += 1; - } - - return b; - } - - /** - * Skips over and discards <code>n</code> bytes of data from this input - * stream. - * - * @param n the number of bytes to be skipped. - * @return the actual number of bytes skipped. - */ - @Override - public long skip(long n) { - readOffset += n; - return n; - } - - @Override - public void close() throws IOException { - handle.getClient().closeFile(handle); - } -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/SFTPOutputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2011 David Kocher. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * @version $Id: SFTPOutputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class SFTPOutputStream extends OutputStream { - - private SFTPFileHandle handle; - - /** - * Offset (in bytes) in the file to write - */ - private long writeOffset = 0; - - public SFTPOutputStream(SFTPFileHandle handle) { - this.handle = handle; - } - - /** - * Writes <code>len</code> bytes from the specified byte array - * starting at offset <code>off</code> to this output stream. - * The general contract for <code>write(b, off, len)</code> is that - * some of the bytes in the array <code>b</code> are written to the - * output stream in order; element <code>b[off]</code> is the first - * byte written and <code>b[off+len-1]</code> is the last byte written - * by this operation. - * - * @see SFTPClient#write(SFTPFileHandle, long, byte[], int, int) - */ - @Override - public void write(byte[] buffer, int offset, int len) throws IOException { - // We can just blindly write the whole buffer at once. - // if <code>len</code> > 32768, then the write operation will - // be split into multiple writes in SFTPv3Client#write. - handle.getClient().write(handle, writeOffset, buffer, offset, len); - writeOffset += len; - } - - @Override - public void write(int b) throws IOException { - byte[] buffer = new byte[1]; - buffer[0] = (byte) b; - handle.getClient().write(handle, writeOffset, buffer, 0, 1); - writeOffset += 1; - } - - public long skip(long n) { - writeOffset += n; - return n; - } - - @Override - public void close() throws IOException { - handle.getClient().closeFile(handle); - } -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/SFTPv3Client.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,433 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.packets.TypesWriter; -import ch.ethz.ssh2.sftp.ErrorCodes; -import ch.ethz.ssh2.sftp.Packet; - -/** - * A <code>SFTPv3Client</code> represents a SFTP (protocol version 3) - * client connection tunnelled over a SSH-2 connection. This is a very simple - * (synchronous) implementation. - * <p/> - * Basically, most methods in this class map directly to one of - * the packet types described in draft-ietf-secsh-filexfer-02.txt. - * <p/> - * Note: this is experimental code. - * <p/> - * Error handling: the methods of this class throw IOExceptions. However, unless - * there is catastrophic failure, exceptions of the type {@link SFTPv3Client} will - * be thrown (a subclass of IOException). Therefore, you can implement more verbose - * behavior by checking if a thrown exception if of this type. If yes, then you - * can cast the exception and access detailed information about the failure. - * <p/> - * Notes about file names, directory names and paths, copy-pasted - * from the specs: - * <ul> - * <li>SFTP v3 represents file names as strings. File names are - * assumed to use the slash ('/') character as a directory separator.</li> - * <li>File names starting with a slash are "absolute", and are relative to - * the root of the file system. Names starting with any other character - * are relative to the user's default directory (home directory).</li> - * <li>Servers SHOULD interpret a path name component ".." as referring to - * the parent directory, and "." as referring to the current directory. - * If the server implementation limits access to certain parts of the - * file system, it must be extra careful in parsing file names when - * enforcing such restrictions. There have been numerous reported - * security bugs where a ".." in a path name has allowed access outside - * the intended area.</li> - * <li>An empty path name is valid, and it refers to the user's default - * directory (usually the user's home directory).</li> - * </ul> - * <p/> - * If you are still not tired then please go on and read the comment for - * {@link #setCharset(String)}. - * - * @author Christian Plattner, plattner@inf.ethz.ch - * @version $Id: SFTPv3Client.java 133 2014-04-14 12:26:29Z dkocher@sudo.ch $ - */ -public class SFTPv3Client extends AbstractSFTPClient { - private static final Logger log = Logger.getLogger(SFTPv3Client.class); - - /** - * Open the file for reading. - */ - public static final int SSH_FXF_READ = 0x00000001; - /** - * Open the file for writing. If both this and SSH_FXF_READ are - * specified, the file is opened for both reading and writing. - */ - public static final int SSH_FXF_WRITE = 0x00000002; - /** - * Force all writes to append data at the end of the file. - */ - public static final int SSH_FXF_APPEND = 0x00000004; - /** - * If this flag is specified, then a new file will be created if one - * does not alread exist (if O_TRUNC is specified, the new file will - * be truncated to zero length if it previously exists). - */ - public static final int SSH_FXF_CREAT = 0x00000008; - /** - * Forces an existing file with the same name to be truncated to zero - * length when creating a file by specifying SSH_FXF_CREAT. - * SSH_FXF_CREAT MUST also be specified if this flag is used. - */ - public static final int SSH_FXF_TRUNC = 0x00000010; - /** - * Causes the request to fail if the named file already exists. - */ - public static final int SSH_FXF_EXCL = 0x00000020; - - private PacketListener listener; - - /** - * Create a SFTP v3 client. - * - * @param conn The underlying SSH-2 connection to be used. - * @throws IOException - */ - public SFTPv3Client(Connection conn) throws IOException { - this(conn, new PacketListener() { - public void read(String packet) { - log.debug("Read packet " + packet); - } - public void write(String packet) { - log.debug("Write packet " + packet); - } - }); - } - - /** - * Create a SFTP v3 client. - * - * @param conn The underlying SSH-2 connection to be used. - * @throws IOException - */ - public SFTPv3Client(Connection conn, PacketListener listener) throws IOException { - super(conn, 3, listener); - this.listener = listener; - } - - public SFTPv3FileAttributes fstat(SFTPFileHandle handle) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(handle.getHandle(), 0, handle.getHandle().length); - sendMessage(Packet.SSH_FXP_FSTAT, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_ATTRS) { - return new SFTPv3FileAttributes(tr); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - private SFTPv3FileAttributes statBoth(String path, int statMethod) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(path, this.getCharset()); - sendMessage(statMethod, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_ATTRS) { - return new SFTPv3FileAttributes(tr); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - public SFTPv3FileAttributes stat(String path) throws IOException { - return statBoth(path, Packet.SSH_FXP_STAT); - } - - public SFTPv3FileAttributes lstat(String path) throws IOException { - return statBoth(path, Packet.SSH_FXP_LSTAT); - } - - - private List<SFTPv3DirectoryEntry> scanDirectory(byte[] handle) throws IOException { - List<SFTPv3DirectoryEntry> files = new ArrayList<SFTPv3DirectoryEntry>(); - - while (true) { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(handle, 0, handle.length); - sendMessage(Packet.SSH_FXP_READDIR, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_NAME) { - int count = tr.readUINT32(); - - if (log.isDebugEnabled()) { - log.debug(String.format("Parsing %d name entries", count)); - } - - while (count > 0) { - SFTPv3DirectoryEntry file = new SFTPv3DirectoryEntry(); - file.filename = tr.readString(this.getCharset()); - file.longEntry = tr.readString(this.getCharset()); - listener.read(file.longEntry); - file.attributes = new SFTPv3FileAttributes(tr); - - if (log.isDebugEnabled()) { - log.debug(String.format("Adding file %s", file)); - } - - files.add(file); - count--; - } - - continue; - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - - if (errorCode == ErrorCodes.SSH_FX_EOF) { - return files; - } - - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - } - - public final SFTPv3FileHandle openDirectory(String path) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(path, this.getCharset()); - sendMessage(Packet.SSH_FXP_OPENDIR, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_HANDLE) { - return new SFTPv3FileHandle(this, tr.readByteString()); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - /** - * List the contents of a directory. - * - * @param dirName See the {@link SFTPv3Client comment} for the class for more details. - * @return A Vector containing {@link SFTPv3DirectoryEntry} objects. - * @throws IOException - */ - public List<SFTPv3DirectoryEntry> ls(String dirName) throws IOException { - SFTPv3FileHandle handle = openDirectory(dirName); - List<SFTPv3DirectoryEntry> result = scanDirectory(handle.getHandle()); - closeFile(handle); - return result; - } - - /** - * Open a file for reading. - * - * @param filename See the {@link SFTPv3Client comment} for the class for more details. - * @return a SFTPv3FileHandle handle - * @throws IOException - */ - public SFTPv3FileHandle openFileRO(String filename) throws IOException { - return openFile(filename, SSH_FXF_READ, new SFTPv3FileAttributes()); - } - - /** - * Open a file for reading and writing. - * - * @param filename See the {@link SFTPv3Client comment} for the class for more details. - * @return a SFTPv3FileHandle handle - * @throws IOException - */ - public SFTPv3FileHandle openFileRW(String filename) throws IOException { - return openFile(filename, SSH_FXF_READ | SSH_FXF_WRITE, new SFTPv3FileAttributes()); - } - - /** - * Open a file in append mode. The SFTP v3 draft says nothing but assuming normal POSIX - * behavior, all writes will be appendend to the end of the file, no matter which offset - * one specifies. - * <p/> - * A side note for the curious: OpenSSH does an lseek() to the specified writing offset before each write(), - * even for writes to files opened in O_APPEND mode. However, bear in mind that when working - * in the O_APPEND mode, each write() includes an implicit lseek() to the end of the file - * (well, this is what the newsgroups say). - * - * @param filename See the {@link SFTPv3Client comment} for the class for more details. - * @return a SFTPv3FileHandle handle - * @throws IOException - */ - public SFTPv3FileHandle openFileRWAppend(String filename) throws IOException { - return openFile(filename, SSH_FXF_READ | SSH_FXF_WRITE | SSH_FXF_APPEND, new SFTPv3FileAttributes()); - } - - /** - * Open a file in append mode. The SFTP v3 draft says nothing but assuming normal POSIX - * behavior, all writes will be appendend to the end of the file, no matter which offset - * one specifies. - * <p/> - * A side note for the curious: OpenSSH does an lseek() to the specified writing offset before each write(), - * even for writes to files opened in O_APPEND mode. However, bear in mind that when working - * in the O_APPEND mode, each write() includes an implicit lseek() to the end of the file - * (well, this is what the newsgroups say). - * - * @param filename See the {@link SFTPv3Client comment} for the class for more details. - * @return a SFTPv3FileHandle handle - * @throws IOException - */ - public SFTPv3FileHandle openFileWAppend(String filename) throws IOException { - return openFile(filename, SSH_FXF_WRITE | SSH_FXF_APPEND, new SFTPv3FileAttributes()); - } - - public SFTPv3FileHandle createFile(String filename) throws IOException { - return createFile(filename, new SFTPv3FileAttributes()); - } - - public SFTPv3FileHandle createFile(String filename, SFTPFileAttributes attr) throws IOException { - return openFile(filename, SSH_FXF_CREAT | SSH_FXF_READ | SSH_FXF_WRITE, attr); - } - - /** - * Create a file (truncate it if it already exists) and open it for writing. - * Same as {@link #createFileTruncate(String, SFTPFileAttributes) createFileTruncate(filename, null)}. - * - * @param filename See the {@link SFTPv3Client comment} for the class for more details. - * @return a SFTPv3FileHandle handle - * @throws IOException - */ - public SFTPv3FileHandle createFileTruncate(String filename) throws IOException { - return createFileTruncate(filename, new SFTPv3FileAttributes()); - } - - /** - * reate a file (truncate it if it already exists) and open it for writing. - * You can specify the default attributes of the file (the server may or may - * not respect your wishes). - * - * @param filename See the {@link SFTPv3Client comment} for the class for more details. - * @param attr may be <code>null</code> to use server defaults. Probably only - * the <code>uid</code>, <code>gid</code> and <code>permissions</code> - * (remember the server may apply a umask) entries of the {@link SFTPv3FileHandle} - * structure make sense. You need only to set those fields where you want - * to override the server's defaults. - * @return a SFTPv3FileHandle handle - * @throws IOException - */ - public SFTPv3FileHandle createFileTruncate(String filename, SFTPFileAttributes attr) throws IOException { - return openFile(filename, SSH_FXF_CREAT | SSH_FXF_TRUNC | SSH_FXF_WRITE, attr); - } - - public SFTPv3FileHandle openFile(String filename, int flags) throws IOException { - return openFile(filename, flags, new SFTPv3FileAttributes()); - } - - @Override - public SFTPv3FileHandle openFile(String filename, int flags, SFTPFileAttributes attr) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(filename, this.getCharset()); - tw.writeUINT32(flags); - tw.writeBytes(attr.toBytes()); - sendMessage(Packet.SSH_FXP_OPEN, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_HANDLE) { - return new SFTPv3FileHandle(this, tr.readByteString()); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - @Override - public void createSymlink(String src, String target) throws IOException { - int req_id = generateNextRequestID(); - // Changed semantics of src and target. The bug is known on SFTP servers shipped with all - // versions of OpenSSH (Bug #861). - TypesWriter tw = new TypesWriter(); - tw.writeString(target, this.getCharset()); - tw.writeString(src, this.getCharset()); - sendMessage(Packet.SSH_FXP_SYMLINK, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } -}
--- a/src/ch/ethz/ssh2/SFTPv3DirectoryEntry.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * A <code>SFTPv3DirectoryEntry</code> as returned by {@link SFTPv3Client#ls(String)}. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class SFTPv3DirectoryEntry implements SFTPDirectoryEntry { - /** - * A relative name within the directory, without any path components. - */ - public String filename; - - /** - * An expanded format for the file name, similar to what is returned by - * "ls -l" on Un*x systems. - * <p/> - * The format of this field is unspecified by the SFTP v3 protocol. - * It MUST be suitable for use in the output of a directory listing - * command (in fact, the recommended operation for a directory listing - * command is to simply display this data). However, clients SHOULD NOT - * attempt to parse the longname field for file attributes; they SHOULD - * use the attrs field instead. - * <p/> - * The recommended format for the longname field is as follows:<br> - * <code>-rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer</code> - */ - public String longEntry; - - /** - * The attributes of this entry. - */ - public SFTPv3FileAttributes attributes; - - public String getFilename() { - return filename; - } - - public SFTPv3FileAttributes getAttributes() { - return attributes; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("SFTPv3DirectoryEntry{"); - sb.append("filename='").append(filename).append('\''); - sb.append(", attributes=").append(attributes); - sb.append('}'); - return sb.toString(); - } -}
--- a/src/ch/ethz/ssh2/SFTPv3FileAttributes.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,276 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; - -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.packets.TypesWriter; -import ch.ethz.ssh2.sftp.AttribFlags; - -/** - * A <code>SFTPv3FileAttributes</code> object represents detail information - * about a file on the server. Not all fields may/must be present. - * - * @author Christian Plattner, plattner@inf.ethz.ch - * @version $Id: SFTPv3FileAttributes.java 133 2014-04-14 12:26:29Z dkocher@sudo.ch $ - */ -public class SFTPv3FileAttributes implements SFTPFileAttributes { - /** - * The SIZE attribute. <code>NULL</code> if not present. - */ - public Long size = null; - - /** - * The UID attribute. <code>NULL</code> if not present. - */ - public Integer uid = null; - - /** - * The GID attribute. <code>NULL</code> if not present. - */ - public Integer gid = null; - - /** - * The POSIX permissions. <code>NULL</code> if not present. - * <p/> - * Here is a list: - * <p/> - * <pre>Note: these numbers are all OCTAL. - * <p/> - * S_IFMT 0170000 bitmask for the file type bitfields - * S_IFSOCK 0140000 socket - * S_IFLNK 0120000 symbolic link - * S_IFREG 0100000 regular file - * S_IFBLK 0060000 block device - * S_IFDIR 0040000 directory - * S_IFCHR 0020000 character device - * S_IFIFO 0010000 fifo - * S_ISUID 0004000 set UID bit - * S_ISGID 0002000 set GID bit - * S_ISVTX 0001000 sticky bit - * <p/> - * S_IRWXU 00700 mask for file owner permissions - * S_IRUSR 00400 owner has read permission - * S_IWUSR 00200 owner has write permission - * S_IXUSR 00100 owner has execute permission - * S_IRWXG 00070 mask for group permissions - * S_IRGRP 00040 group has read permission - * S_IWGRP 00020 group has write permission - * S_IXGRP 00010 group has execute permission - * S_IRWXO 00007 mask for permissions for others (not in group) - * S_IROTH 00004 others have read permission - * S_IWOTH 00002 others have write permisson - * S_IXOTH 00001 others have execute permission - * </pre> - */ - public Integer permissions = null; - - /** - * Last access time of the file. - * <p/> - * The atime attribute. Represented as seconds from Jan 1, 1970 in UTC. - * <code>NULL</code> if not present. - */ - public Integer atime = null; - - /** - * The mtime attribute. Represented as seconds from Jan 1, 1970 in UTC. - * <code>NULL</code> if not present. - */ - public Integer mtime = null; - - /** - * Checks if this entry is a directory. - * - * @return Returns true if permissions are available and they indicate - * that this entry represents a directory. - */ - public boolean isDirectory() { - if (permissions == null) { - return false; - } - - return ((permissions & 0040000) == 0040000); - } - - /** - * Checks if this entry is a regular file. - * - * @return Returns true if permissions are available and they indicate - * that this entry represents a regular file. - */ - public boolean isRegularFile() { - if (permissions == null) { - return false; - } - - return ((permissions & 0100000) == 0100000); - } - - /** - * Checks if this entry is a a symlink. - * - * @return Returns true if permissions are available and they indicate - * that this entry represents a symlink. - */ - public boolean isSymlink() { - if (permissions == null) { - return false; - } - - return ((permissions & 0120000) == 0120000); - } - - /** - * Turn the POSIX permissions into a 7 digit octal representation. - * Note: the returned value is first masked with <code>0177777</code>. - * - * @return <code>NULL</code> if permissions are not available. - */ - public String getOctalPermissions() { - if (permissions == null) { - return null; - } - - String res = Integer.toString(permissions.intValue() & 0177777, 8); - StringBuilder sb = new StringBuilder(); - int leadingZeros = 7 - res.length(); - - while (leadingZeros > 0) { - sb.append('0'); - leadingZeros--; - } - - sb.append(res); - return sb.toString(); - } - - public SFTPv3FileAttributes() { - // - } - - /** - * uint32 valid-attribute-flags - * byte type always present - * uint64 size if flag SIZE - * uint64 allocation-size if flag ALLOCATION_SIZE - * string owner if flag OWNERGROUP - * string group if flag OWNERGROUP - * uint32 permissions if flag PERMISSIONS - * int64 atime if flag ACCESSTIME - * uint32 atime-nseconds if flag SUBSECOND_TIMES - * int64 createtime if flag CREATETIME - * uint32 createtime-nseconds if flag SUBSECOND_TIMES - * int64 mtime if flag MODIFYTIME - * uint32 mtime-nseconds if flag SUBSECOND_TIMES - * int64 ctime if flag CTIME - * uint32 ctime-nseconds if flag SUBSECOND_TIMES - * string acl if flag ACL - * uint32 attrib-bits if flag BITS - * uint32 attrib-bits-valid if flag BITS - * byte text-hint if flag TEXT_HINT - * string mime-type if flag MIME_TYPE - * uint32 link-count if flag LINK_COUNT - * string untranslated-name if flag UNTRANSLATED_NAME - * uint32 extended-count if flag EXTENDED - * extension-pair extensions - */ - public SFTPv3FileAttributes(final TypesReader tr) throws IOException { - int flags = tr.readUINT32(); - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SIZE) != 0) { - this.size = tr.readUINT64(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_V3_UIDGID) != 0) { - this.uid = tr.readUINT32(); - this.gid = tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { - this.permissions = tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_V3_ACMODTIME) != 0) { - this.atime = tr.readUINT32(); - this.mtime = tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_EXTENDED) != 0) { - int count = tr.readUINT32(); - - // Read it anyway to detect corrupt packets - while (count > 0) { - tr.readByteString(); - tr.readByteString(); - count--; - } - } - } - - /** - * The same encoding is used both when returning file - * attributes from the server and when sending file attributes to the - * server. - * - * @return Encoded attributes - */ - public byte[] toBytes() { - TypesWriter tw = new TypesWriter(); - int attrFlags = 0; - - if (this.size != null) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_SIZE; - } - - if ((this.uid != null) && (this.gid != null)) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_V3_UIDGID; - } - - if (this.permissions != null) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS; - } - - if ((this.atime != null) && (this.mtime != null)) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_V3_ACMODTIME; - } - - tw.writeUINT32(attrFlags); - - if (this.size != null) { - tw.writeUINT64(this.size); - } - - if ((this.uid != null) && (this.gid != null)) { - tw.writeUINT32(this.uid); - tw.writeUINT32(this.gid); - } - - if (this.permissions != null) { - tw.writeUINT32(this.permissions); - } - - if ((this.atime != null) && (this.mtime != null)) { - tw.writeUINT32(this.atime); - tw.writeUINT32(this.mtime); - } - - return tw.getBytes(); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("SFTPv3FileAttributes{"); - sb.append("size=").append(size); - sb.append(", uid=").append(uid); - sb.append(", gid=").append(gid); - sb.append(", permissions=").append(permissions); - sb.append(", atime=").append(atime); - sb.append(", mtime=").append(mtime); - sb.append('}'); - return sb.toString(); - } -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/SFTPv3FileHandle.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * A <code>SFTPv3FileHandle</code>. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class SFTPv3FileHandle extends SFTPFileHandle { - protected SFTPv3FileHandle(final SFTPv3Client client, final byte[] handle) { - super(client, handle); - } -}
--- a/src/ch/ethz/ssh2/SFTPv6Client.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,300 +0,0 @@ -package ch.ethz.ssh2; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.packets.TypesWriter; -import ch.ethz.ssh2.sftp.AceMask; -import ch.ethz.ssh2.sftp.ErrorCodes; -import ch.ethz.ssh2.sftp.OpenFlags; -import ch.ethz.ssh2.sftp.Packet; - -/** - * @version $Id: SFTPv6Client.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class SFTPv6Client extends AbstractSFTPClient { - private static final Logger log = Logger.getLogger(SFTPv6Client.class); - - private PacketListener listener; - - public SFTPv6Client(Connection conn) throws IOException { - this(conn, new PacketListener() { - public void read(String packet) { - log.debug("Read packet " + packet); - } - public void write(String packet) { - log.debug("Write packet " + packet); - } - }); - } - - public SFTPv6Client(Connection conn, PacketListener listener) throws IOException { - super(conn, 6, listener); - this.listener = listener; - } - - public SFTPv6FileAttributes fstat(SFTPFileHandle handle) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(handle.getHandle(), 0, handle.getHandle().length); - sendMessage(Packet.SSH_FXP_FSTAT, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_ATTRS) { - return new SFTPv6FileAttributes(tr); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - private SFTPv6FileAttributes statBoth(String path, int statMethod) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(path, this.getCharset()); - sendMessage(statMethod, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_ATTRS) { - return new SFTPv6FileAttributes(tr); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - public SFTPv6FileAttributes stat(String path) throws IOException { - return statBoth(path, Packet.SSH_FXP_STAT); - } - - public SFTPv6FileAttributes lstat(String path) throws IOException { - return statBoth(path, Packet.SSH_FXP_LSTAT); - } - - - private List<SFTPv6DirectoryEntry> scanDirectory(byte[] handle) throws IOException { - List<SFTPv6DirectoryEntry> files = new ArrayList<SFTPv6DirectoryEntry>(); - - while (true) { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(handle, 0, handle.length); - sendMessage(Packet.SSH_FXP_READDIR, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_NAME) { - int count = tr.readUINT32(); - - if (log.isDebugEnabled()) { - log.debug(String.format("Parsing %d name entries", count)); - } - - while (count > 0) { - SFTPv6DirectoryEntry file = new SFTPv6DirectoryEntry(); - file.filename = tr.readString(this.getCharset()); - listener.read(file.filename); - file.attributes = new SFTPv6FileAttributes(tr); - - if (log.isDebugEnabled()) { - log.debug(String.format("Adding file %s", file)); - } - - files.add(file); - count--; - } - - continue; - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - - if (errorCode == ErrorCodes.SSH_FX_EOF) { - return files; - } - - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - } - - public final SFTPFileHandle openDirectory(String path) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(path, this.getCharset()); - sendMessage(Packet.SSH_FXP_OPENDIR, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_HANDLE) { - return new SFTPFileHandle(this, tr.readByteString()); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - /** - * List the contents of a directory. - * - * @param dirName See the {@link SFTPv6Client comment} for the class for more details. - * @return A Vector containing {@link SFTPv6DirectoryEntry} objects. - * @throws IOException - */ - public List<SFTPv6DirectoryEntry> ls(String dirName) throws IOException { - SFTPFileHandle handle = openDirectory(dirName); - List<SFTPv6DirectoryEntry> result = scanDirectory(handle.getHandle()); - closeFile(handle); - return result; - } - - /** - * Create a file and open it for reading and writing. - * Same as {@link #createFile(String, SFTPFileAttributes) createFile(fileName, null)}. - * - * @param filename See the {@link SFTPv6Client comment} for the class for more details. - * @return a SFTPFileHandle handle - * @throws IOException - */ - public SFTPFileHandle createFile(String filename) throws IOException { - return createFile(filename, new SFTPv6FileAttributes()); - } - - /** - * Create a file and open it for reading and writing. - * You can specify the default attributes of the file (the server may or may - * not respect your wishes). - * - * @param filename See the {@link SFTPv6Client comment} for the class for more details. - * @param attr may be <code>null</code> to use server defaults. Probably only - * the <code>uid</code>, <code>gid</code> and <code>permissions</code> - * (remember the server may apply a umask) entries of the {@link SFTPFileHandle} - * structure make sense. You need only to set those fields where you want - * to override the server's defaults. - * @return a SFTPFileHandle handle - * @throws IOException - */ - public SFTPFileHandle createFile(String filename, SFTPFileAttributes attr) throws IOException { - return openFile(filename, OpenFlags.SSH_FXF_CREATE_NEW, attr); - } - - public SFTPFileHandle openFile(String filename, int flags) throws IOException { - return this.openFile(filename, flags, new SFTPv6FileAttributes()); - } - - @Override - public SFTPFileHandle openFile(String filename, int flags, SFTPFileAttributes attr) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - tw.writeString(filename, this.getCharset()); - tw.writeUINT32(AceMask.ACE4_READ_DATA | AceMask.ACE4_READ_ATTRIBUTES | AceMask.ACE4_READ_ACL | AceMask.ACE4_READ_NAMED_ATTRS - | AceMask.ACE4_WRITE_DATA | AceMask.ACE4_APPEND_DATA | AceMask.ACE4_WRITE_ATTRIBUTES | AceMask.ACE4_WRITE_ACL | AceMask.ACE4_WRITE_NAMED_ATTRS); - tw.writeUINT32(flags); - tw.writeBytes(attr.toBytes()); - sendMessage(Packet.SSH_FXP_OPEN, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); - listener.read(Packet.forName(t)); - int rep_id = tr.readUINT32(); - - if (rep_id != req_id) { - throw new RequestMismatchException(); - } - - if (t == Packet.SSH_FXP_HANDLE) { - return new SFTPFileHandle(this, tr.readByteString()); - } - - if (t != Packet.SSH_FXP_STATUS) { - throw new PacketTypeException(t); - } - - int errorCode = tr.readUINT32(); - String errorMessage = tr.readString(); - listener.read(errorMessage); - throw new SFTPException(errorMessage, errorCode); - } - - @Override - public void createSymlink(String src, String target) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - // new-link-path - tw.writeString(src, this.getCharset()); - // existing-path - tw.writeString(target, this.getCharset()); - tw.writeBoolean(true); - sendMessage(Packet.SSH_FXP_LINK, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } - - @Override - public void createHardlink(String src, String target) throws IOException { - int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); - // new-link-path - tw.writeString(src, this.getCharset()); - // existing-path - tw.writeString(target, this.getCharset()); - tw.writeBoolean(false); - sendMessage(Packet.SSH_FXP_LINK, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); - } -}
--- a/src/ch/ethz/ssh2/SFTPv6DirectoryEntry.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -package ch.ethz.ssh2; - -/** - * @version $Id: SFTPv6DirectoryEntry.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class SFTPv6DirectoryEntry implements SFTPDirectoryEntry { - /** - * A relative name within the directory, without any path components. - */ - public String filename; - - /** - * The attributes of this entry. - */ - public SFTPv6FileAttributes attributes; - - public String getFilename() { - return filename; - } - - public SFTPv6FileAttributes getAttributes() { - return attributes; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("SFTPv6DirectoryEntry{"); - sb.append("filename='").append(filename).append('\''); - sb.append(", attributes=").append(attributes); - sb.append('}'); - return sb.toString(); - } -}
--- a/src/ch/ethz/ssh2/SFTPv6FileAttributes.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,371 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; - -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.packets.TypesWriter; -import ch.ethz.ssh2.sftp.AttribFlags; -import ch.ethz.ssh2.sftp.AttribTypes; - -/** - * A <code>SFTPv3FileAttributes</code> object represents detail information - * about a file on the server. Not all fields may/must be present. - * - * @author Christian Plattner, plattner@inf.ethz.ch - * @version $Id: SFTPv6FileAttributes.java 133 2014-04-14 12:26:29Z dkocher@sudo.ch $ - */ - -public class SFTPv6FileAttributes implements SFTPFileAttributes { - - /** - * The type field is always present - * - * @see ch.ethz.ssh2.sftp.AttribTypes - */ - private Integer type = null; - - /** - * The SIZE attribute. <code>NULL</code> if not present. - */ - public Long size = null; - - /** - * The POSIX permissions. <code>NULL</code> if not present. - * <p/> - * Here is a list: - * <p/> - * <pre>Note: these numbers are all OCTAL. - * <p/> - * S_IFMT 0170000 bitmask for the file type bitfields - * S_IFSOCK 0140000 socket - * S_IFLNK 0120000 symbolic link - * S_IFREG 0100000 regular file - * S_IFBLK 0060000 block device - * S_IFDIR 0040000 directory - * S_IFCHR 0020000 character device - * S_IFIFO 0010000 fifo - * S_ISUID 0004000 set UID bit - * S_ISGID 0002000 set GID bit - * S_ISVTX 0001000 sticky bit - * <p/> - * S_IRWXU 00700 mask for file owner permissions - * S_IRUSR 00400 owner has read permission - * S_IWUSR 00200 owner has write permission - * S_IXUSR 00100 owner has execute permission - * S_IRWXG 00070 mask for group permissions - * S_IRGRP 00040 group has read permission - * S_IWGRP 00020 group has write permission - * S_IXGRP 00010 group has execute permission - * S_IRWXO 00007 mask for permissions for others (not in group) - * S_IROTH 00004 others have read permission - * S_IWOTH 00002 others have write permisson - * S_IXOTH 00001 others have execute permission - * </pre> - */ - public Integer permissions = null; - - /** - * Creation time of the file. - * <p/> - * The createtime attribute. Represented as seconds from Jan 1, 1970 in UTC. - * <code>NULL</code> if not present. - */ - public Long createtime = null; - - /** - * Last access time of the file. - * <p/> - * The atime attribute. Represented as seconds from Jan 1, 1970 in UTC. - * <code>NULL</code> if not present. - */ - public Long atime = null; - - /** - * The mtime attribute. Represented as seconds from Jan 1, 1970 in UTC. - * <code>NULL</code> if not present. - */ - public Long mtime = null; - - /** - * Last time the file attributes were changed. The exact meaning of this field depends on the server. - * <p/> - * The ctime attribute. Represented as seconds from Jan 1, 1970 in UTC. - * <code>NULL</code> if not present. - */ - public Long ctime = null; - - /** - * The 'owner' and 'group' fields are represented as UTF-8 strings. user@localhost represents - * a user in the context of the server. - */ - public String owner = null; - - /** - * The 'owner' and 'group' fields are represented as UTF-8 strings - */ - public String group = null; - - /** - * Checks if this entry is a directory. - * - * @return Returns true if permissions are available and they indicate - * that this entry represents a directory. - */ - public boolean isDirectory() { - return (type & AttribTypes.SSH_FILEXFER_TYPE_DIRECTORY) == AttribTypes.SSH_FILEXFER_TYPE_DIRECTORY; - } - - /** - * Checks if this entry is a regular file. - * - * @return Returns true if permissions are available and they indicate - * that this entry represents a regular file. - */ - public boolean isRegularFile() { - return (type & AttribTypes.SSH_FILEXFER_TYPE_REGULAR) == AttribTypes.SSH_FILEXFER_TYPE_REGULAR; - } - - /** - * Checks if this entry is a a symlink. - * - * @return Returns true if permissions are available and they indicate - * that this entry represents a symlink. - */ - public boolean isSymlink() { - return (type & AttribTypes.SSH_FILEXFER_TYPE_SYMLINK) == AttribTypes.SSH_FILEXFER_TYPE_SYMLINK; - } - - public SFTPv6FileAttributes() { - // - } - - /** - * uint32 valid-attribute-flags - * byte type always present - * uint64 size if flag SIZE - * uint64 allocation-size if flag ALLOCATION_SIZE - * string owner if flag OWNERGROUP - * string group if flag OWNERGROUP - * uint32 permissions if flag PERMISSIONS - * int64 atime if flag ACCESSTIME - * uint32 atime-nseconds if flag SUBSECOND_TIMES - * int64 createtime if flag CREATETIME - * uint32 createtime-nseconds if flag SUBSECOND_TIMES - * int64 mtime if flag MODIFYTIME - * uint32 mtime-nseconds if flag SUBSECOND_TIMES - * int64 ctime if flag CTIME - * uint32 ctime-nseconds if flag SUBSECOND_TIMES - * string acl if flag ACL - * uint32 attrib-bits if flag BITS - * uint32 attrib-bits-valid if flag BITS - * byte text-hint if flag TEXT_HINT - * string mime-type if flag MIME_TYPE - * uint32 link-count if flag LINK_COUNT - * string untranslated-name if flag UNTRANSLATED_NAME - * uint32 extended-count if flag EXTENDED - * extension-pair extensions - */ - public SFTPv6FileAttributes(final TypesReader tr) throws IOException { - int flags = tr.readUINT32(); - // The type field is always present - this.type = tr.readByte(); - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SIZE) != 0) { - this.size = tr.readUINT64(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_ALLOCATION_SIZE) != 0) { - // Ignore - tr.readUINT64(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_OWNERGROUP) != 0) { - this.owner = tr.readString(); - this.group = tr.readString(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { - this.permissions = tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_ACCESSTIME) != 0) { - this.atime = tr.readUINT64(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { - // Ignore - tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_CREATETIME) != 0) { - this.createtime = tr.readUINT64(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { - // Ignore - tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_MODIFYTIME) != 0) { - this.mtime = tr.readUINT64(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { - // Ignore - tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_CTIME) != 0) { - this.ctime = tr.readUINT64(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { - // Ignore - tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_ACL) != 0) { - // Ignore - tr.readString(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_BITS) != 0) { - // Ignore attrib-bits - tr.readUINT32(); - // Ignore attrib-bits-valid - tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_TEXT_HINT) != 0) { - // Ignore - tr.readByte(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_MIME_TYPE) != 0) { - // Ignore - tr.readString(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_LINK_COUNT) != 0) { - // Ignore - tr.readUINT32(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_UNTRANSLATED_NAME) != 0) { - // Ignore - tr.readString(); - } - - if ((flags & AttribFlags.SSH_FILEXFER_ATTR_EXTENDED) != 0) { - int count = tr.readUINT32(); - - // Read it anyway to detect corrupt packets - while (count > 0) { - // extension-name - tr.readByteString(); - // extension-data - tr.readByteString(); - count--; - } - } - } - - /** - * The same encoding is used both when returning file - * attributes from the server and when sending file attributes to the - * server. - * - * @return Encoded attributes - */ - public byte[] toBytes() { - TypesWriter tw = new TypesWriter(); - // The 'valid-attribute-flags' specifies which of the fields are present. Those fields - // for which the corresponding flag is not set are not present - int attrFlags = 0; - - if (this.size != null) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_SIZE; - } - - if ((this.owner != null) && (this.group != null)) { - // If either the owner or group field is zero length, the field should - // be considered absent, and no change should be made to that specific - // field during a modification operation. - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_OWNERGROUP; - } - - if (this.permissions != null) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS; - } - - if (this.atime != null) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_ACCESSTIME; - } - - if (this.createtime != null) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_CREATETIME; - } - - if (this.mtime != null) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_MODIFYTIME; - } - - if (this.ctime != null) { - attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_CTIME; - } - - tw.writeUINT32(attrFlags); - - // The type field is always present. - if (this.size != null) { - tw.writeUINT64(this.size); - } - - if ((this.owner != null) && (this.group != null)) { - tw.writeString(owner); - tw.writeString(group); - } - - if (this.permissions != null) { - tw.writeUINT32(this.permissions); - } - - if (this.atime != null) { - tw.writeUINT64(this.atime); - } - - if (this.createtime != null) { - tw.writeUINT64(this.createtime); - } - - if (this.mtime != null) { - tw.writeUINT64(this.mtime); - } - - if (this.ctime != null) { - tw.writeUINT64(this.ctime); - } - - return tw.getBytes(); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("SFTPv6FileAttributes{"); - sb.append("type=").append(type); - sb.append(", size=").append(size); - sb.append(", permissions=").append(permissions); - sb.append(", createtime=").append(createtime); - sb.append(", atime=").append(atime); - sb.append(", mtime=").append(mtime); - sb.append(", ctime=").append(ctime); - sb.append(", owner='").append(owner).append('\''); - sb.append(", group='").append(group).append('\''); - sb.append('}'); - return sb.toString(); - } -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/ServerAuthenticationCallback.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2; - -/** - * A callback used during the authentication phase (see RFC 4252) when - * implementing a SSH server. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public interface ServerAuthenticationCallback { - /** - * The method name for host-based authentication. - */ - public final String METHOD_HOSTBASED = "hostbased"; - - /** - * The method name for public-key authentication. - */ - public final String METHOD_PUBLICKEY = "publickey"; - - /** - * The method name for password authentication. - */ - public final String METHOD_PASSWORD = "password"; - - /** - * Called when the client enters authentication. - * This gives you the chance to set a custom authentication banner - * for this SSH-2 session. This is the first method called in this interface. - * It will only called at most once per <code>ServerConnection</code>. - * - * @param sc The corresponding <code>ServerConnection</code> - * @return The authentication banner or <code>NULL</code> in case no banner should be send. - */ - public String initAuthentication(ServerConnection sc); - - /** - * Return the authentication methods that are currently available to the client. - * Be prepared to return this information at any time during the authentication procedure. - * <p/> - * The returned name-list of 'method names' (see RFC4252) indicate the authentication methods - * that may productively continue the authentication dialog. - * </p> - * It is RECOMMENDED that servers only include those 'method name' - * values in the name-list that are actually useful. However, it is not - * illegal to include 'method name' values that cannot be used to - * authenticate the user. - * <p/> - * Already successfully completed authentications SHOULD NOT be included - * in the name-list, unless they should be performed again for some reason. - * - * @see #METHOD_HOSTBASED - * @see #METHOD_PASSWORD - * @see #METHOD_PUBLICKEY - * - * @param sc - * @return A list of method names. - */ - public String[] getRemainingAuthMethods(ServerConnection sc); - - /** - * Typically, this will be called be the client to get the list of - * authentication methods that can continue. You should simply return - * {@link AuthenticationResult#FAILURE}. - * - * @param sc - * @param username Name of the user that wants to log in with the "none" method. - * @return - */ - public AuthenticationResult authenticateWithNone(ServerConnection sc, String username); - - public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password); - - /** - * NOTE: Not implemented yet. - * - * @param sc - * @param username - * @param algorithm - * @param publickey - * @param signature - * @return - */ - public AuthenticationResult authenticateWithPublicKey(ServerConnection sc, String username, String algorithm, - byte[] publickey, byte[] signature); -}
--- a/src/ch/ethz/ssh2/ServerConnection.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,376 +0,0 @@ -/* - * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2; - -import java.io.CharArrayWriter; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.net.Socket; -import java.util.List; -import java.util.ArrayList; - -import ch.ethz.ssh2.crypto.CryptoWishList; -import ch.ethz.ssh2.crypto.PEMDecoder; -import ch.ethz.ssh2.server.ServerConnectionState; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.RSAPrivateKey; -import ch.ethz.ssh2.transport.ServerTransportManager; - -/** - * A server-side SSH-2 connection. - * - * @author Christian - * - */ -public class ServerConnection { - /** - * The softwareversion presented to the SSH-2 client. - */ - private String softwareversion = String.format("Ganymed_SSHD_%s", Version.getSpecification()); - - private final ServerConnectionState state = new ServerConnectionState(this); - - /** - * Creates a new <code>ServerConnection</code> that will communicate - * with the client over the given <code>Socket</code>. - * <p> - * Note: you need to call {@link #connect()} or {@link #connect(int)} to - * perform the initial handshake and establish the encrypted communication. - * - * @see #connect(int) - * - * @param s The socket - */ - public ServerConnection(Socket s) { - this(s, null, null, null); - } - - public ServerConnection(Socket s, String softwareversion) { - this(s, null, null, null); - this.softwareversion = softwareversion; - } - - /** - * Creates a new <code>ServerConnection</code> that will communicate - * with the client over the given <code>Socket</code>. - * <p> - * Note: you need to call {@link #connect()} or {@link #connect(int)} to - * perform the initial handshake and establish the encrypted communication. - * <p> - * Please read the javadoc for the {@link #connect(int)} method. - * - * @see #connect(int) - * - * @param s The socket - * @param dsa_key The DSA hostkey, may be <code>NULL</code> - * @param rsa_key The RSA hostkey, may be <code>NULL</code> - * @param ec_key The EC hostkey, may be <code>NULL</code> - */ - public ServerConnection(Socket s, KeyPair dsa_key, KeyPair rsa_key, KeyPair ec_key) { - state.s = s; - state.softwareversion = softwareversion; - state.next_dsa_key = dsa_key; - state.next_rsa_key = rsa_key; - state.next_ec_key = ec_key; - fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } - - /** - * Establish the connection and block until the first handshake has completed. - * <p> - * Note: this is a wrapper that calls <code>connect(0)</code> (i.e., connect with no timeout). - * <p> - * Please read the javadoc for the {@link #connect(int)} method. - * - * @see #connect(int) - * - * @throws IOException - */ - - public synchronized void connect() throws IOException { - connect(0); - } - - /** - * Establish the connection and block until the first handshake has completed. - * <p> - * Note 1: at least one DSA, RSA or EC hostkey must be set before calling this method. - * <p> - * Note 2: You must set the callbacks for authentication ({@link #setAuthenticationCallback(ServerAuthenticationCallback)}) - * and connection events ({@link #setServerConnectionCallback(ServerConnectionCallback)}). - * - * @see #setPEMHostKey(char[], String) - * @see #setPEMHostKey(File, String) - * @see #setRsaHostKey(RSAPrivateKey) - * @see #setDsaHostKey(DSAPrivateKey) - * - * @param timeout_milliseconds Timeout in milliseconds, <code>0</code> means no timeout. - * @throws IOException - */ - - public synchronized void connect(int timeout_milliseconds) throws IOException { - synchronized (state) { - if (state.cb_conn == null) - throw new IllegalStateException("The callback for connection events has not been set."); - - if (state.cb_auth == null) - throw new IllegalStateException("The callback for authentication events has not been set."); - - if (state.tm != null) - throw new IllegalStateException("The initial handshake has already been started."); - - if ((state.next_dsa_key == null) && (state.next_rsa_key == null) && (state.next_ec_key == null)) - throw new IllegalStateException("Neither an RSA nor a DSA nor an EC host key has been specified!"); - - state.tm = new ServerTransportManager(state.s); - } - - state.tm.connect(state); - /* Wait until first KEX has finished */ - state.tm.getConnectionInfo(1); - } - - /** - * Retrieve the underlying socket. - * - * @return the socket that has been passed to the constructor. - */ - public Socket getSocket() { - return state.s; - } - - /** - * Force an asynchronous key re-exchange (the call does not block). The - * latest values set for MAC, Cipher and DH group exchange parameters will - * be used. If a key exchange is currently in progress, then this method has - * the only effect that the so far specified parameters will be used for the - * next (client driven) key exchange. You may call this method only after - * the initial key exchange has been established. - * <p> - * Note: This implementation will never start automatically a key exchange (other than the initial one) - * unless you or the connected SSH-2 client ask for it. - * - * @throws IOException - * In case of any failure behind the scenes. - */ - - public synchronized void forceKeyExchange() throws IOException { - synchronized (state) { - if (state.tm == null) - throw new IllegalStateException( - "Cannot force another key exchange, you need to start the key exchange first."); - - state.tm.forceKeyExchange(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } - } - - /** - * Returns a {@link ConnectionInfo} object containing the details of - * the connection. May be called as soon as the first key exchange has been - * started. The method blocks in case the first key exchange has not been completed. - * <p> - * Note: upon return of this method, authentication may still be pending. - * - * @return A {@link ConnectionInfo} object. - * @throws IOException - * In case of any failure behind the scenes; e.g., first key exchange was aborted. - */ - - public synchronized ConnectionInfo getConnectionInfo() throws IOException { - synchronized (state) { - if (state.tm == null) - throw new IllegalStateException( - "Cannot get details of connection, you need to start the key exchange first."); - } - - return state.tm.getConnectionInfo(1); - } - - /** - * Change the current DSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with - * the client. - * <p> - * Note: You can change an existing DSA hostkey after the initial kex exchange (the new value will - * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the - * current DSA key, otherwise the next key exchange may fail in case the client supports only DSA hostkeys. - * - * @param dsa_hostkey - */ - - public synchronized void setDsaHostKey(KeyPair dsa_hostkey) { - synchronized (state) { - if ((dsa_hostkey == null) && (state.next_dsa_key != null) && (state.tm != null)) - throw new IllegalStateException("Cannot remove DSA hostkey after first key exchange."); - - state.next_dsa_key = dsa_hostkey; - fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } - } - - /** - * Change the current RSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with - * the client. - * <p> - * Note: You can change an existing RSA hostkey after the initial kex exchange (the new value will - * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the - * current RSA key, otherwise the next key exchange may fail in case the client supports only RSA hostkeys. - * - * @param rsa_hostkey - */ - - public synchronized void setRsaHostKey(KeyPair rsa_hostkey) { - synchronized (state) { - if ((rsa_hostkey == null) && (state.next_rsa_key != null) && (state.tm != null)) - throw new IllegalStateException("Cannot remove RSA hostkey after first key exchange."); - - state.next_rsa_key = rsa_hostkey; - fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } - } - - /** - * Change the current EC hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with - * the client. - * <p> - * Note: You can change an existing EC hostkey after the initial kex exchange (the new value will - * be used during the next server initiated key exchange), but you cannot remove (i.e., set to <code>null</code>) the - * current EC key, otherwise the next key exchange may fail in case the client supports only EC hostkeys. - * - * @param rsa_hostkey - */ - - public synchronized void setEcHostKey(KeyPair ec_hostkey) { - synchronized (state) { - if ((ec_hostkey == null) && (state.next_ec_key != null) && (state.tm != null)) - throw new IllegalStateException("Cannot remove EC hostkey after first key exchange."); - - state.next_ec_key = ec_hostkey; - fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } - } - - /** - * Utility method that loads a PEM based hostkey (either RSA or DSA based) and - * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. - * - * @param pemdata The PEM data - * @param password Password, may be null in case the PEM data is not password protected - * @throws IOException In case of any error. - */ - public void setPEMHostKey(char[] pemdata, String password) throws IOException { - KeyPair pair = PEMDecoder.decode(pemdata, password); - PrivateKey key = pair.getPrivate(); - - if (key instanceof DSAPrivateKey) setDsaHostKey(pair); - - if (key instanceof RSAPrivateKey) setRsaHostKey(pair); - - if (key instanceof ECPrivateKey) setEcHostKey(pair); - } - - /** - * Utility method that loads a hostkey from a PEM file (either RSA or DSA based) and - * calls either <code>setRsaHostKey()</code> or <code>setDsaHostKey()</code>. - * - * @param pemFile The PEM file - * @param password Password, may be null in case the PEM file is not password protected - * @throws IOException - */ - public void setPEMHostKey(File pemFile, String password) throws IOException { - if (pemFile == null) - throw new IllegalArgumentException("pemfile argument is null"); - - char[] buff = new char[256]; - CharArrayWriter cw = new CharArrayWriter(); - FileReader fr = new FileReader(pemFile); - - while (true) { - int len = fr.read(buff); - - if (len < 0) - break; - - cw.write(buff, 0, len); - } - - fr.close(); - setPEMHostKey(cw.toCharArray(), password); - } - - private void fixCryptoWishList(CryptoWishList next_cryptoWishList, KeyPair next_dsa_key, KeyPair next_rsa_key, KeyPair next_ec_key) { - List<String> algos = new ArrayList<String>(); - - if (next_rsa_key != null) algos.add("ssh-rsa"); - if (next_dsa_key != null) algos.add("ssh-dss"); - if (next_ec_key != null) algos.add("ecdsa-sha2-nistp521"); - if (next_ec_key != null) algos.add("ecdsa-sha2-nistp384"); - if (next_ec_key != null) algos.add("ecdsa-sha2-nistp256"); - - next_cryptoWishList.serverHostKeyAlgorithms = new String[algos.size()]; - algos.toArray(next_cryptoWishList.serverHostKeyAlgorithms); - } - - /** - * Callback interface with methods that will be called upon events - * generated by the client (e.g., client opens a new Session which results in a <code>ServerSession</code>). - * <p> - * Note: This must be set before the first handshake. - * - * @param cb The callback implementation - */ - - public synchronized void setServerConnectionCallback(ServerConnectionCallback cb) { - synchronized (state) { - state.cb_conn = cb; - } - } - - /** - * Callback interface with methods that will be called upon authentication events. - * <p> - * Note: This must be set before the first handshake. - * - * @param cb The callback implementation - */ - - public synchronized void setAuthenticationCallback(ServerAuthenticationCallback cb) { - synchronized (state) { - state.cb_auth = cb; - } - } - - /** - * Close the connection to the SSH-2 server. All assigned sessions will be - * closed, too. Can be called at any time. Don't forget to call this once - * you don't need a connection anymore - otherwise the receiver thread may - * run forever. - */ - public void close() { - synchronized (state) { - if (state.cm != null) - state.cm.closeAllChannels(); - - if (state.tm != null) { - state.tm.close(new Throwable("Closed due to user request."), false); - } - } - } - - public void close(IOException t) { - synchronized (state) { - if (state.cm != null) - state.cm.closeAllChannels(); - - if (state.tm != null) { - state.tm.close(t, false); - } - } - } -}
--- a/src/ch/ethz/ssh2/ServerConnectionCallback.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -public interface ServerConnectionCallback { - public ServerSessionCallback acceptSession(ServerSession session); -}
--- a/src/ch/ethz/ssh2/ServerHostKeyVerifier.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -/** - * A callback interface used to implement a client specific method of checking - * server host keys. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public interface ServerHostKeyVerifier { - /** - * The actual verifier method, it will be called by the key exchange code - * on EVERY key exchange - this can happen several times during the lifetime - * of a connection. - * <p> - * Note: SSH-2 servers are allowed to change their hostkey at ANY time. - * - * @param hostname the hostname used to create the {@link Connection} object - * @param port the remote TCP port - * @param serverHostKeyAlgorithm the public key algorithm (<code>ssh-rsa</code> or <code>ssh-dss</code>) - * @param serverHostKey the server's public key blob - * @return if the client wants to accept the server's host key - if not, the - * connection will be closed. - * @throws Exception Will be wrapped with an IOException, extended version of returning false =) - */ - public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) - throws Exception; -}
--- a/src/ch/ethz/ssh2/ServerSession.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.InputStream; -import java.io.OutputStream; - -/** - * A ServerSession represents the server-side of a session channel. - * - * @see Session - * - * @author Christian - * - */ -public interface ServerSession { - public InputStream getStdout(); - - public InputStream getStderr(); - - public OutputStream getStdin(); - - public void close(); -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/ServerSessionCallback.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2; - -import java.io.IOException; - -/** - * The interface for an object that receives events based on requests that - * a client sends on a session channel. Once the session channel has been set up, - * a program is started at the server end. The program can be a shell, an application - * program, or a subsystem with a host-independent name. Only one of these requests - * can succeed per channel. - * <p/> - * <b>CAUTION: These event methods are being called from the receiver thread. The receiving of - * messages will be blocked until your event handler returns. To signal to the client that you - * are willing to accept its request, return a {@link Runnable} object which will be executed - * in a new thread <i>after</i> the acknowledgment has been sent back to the client.</b> - * <p/> - * <b>If a method does not allow you to return a {@link Runnable}, then the - * SSH protocol does not allow to send a status back to the client (more exactly, the client cannot - * request an acknowledgment). In these cases, if you need to invoke - * methods on the {@link ServerSession} or plan to execute long-running activity, then please do this from within a new {@link Thread}.</b> - * <p/> - * If you want to signal a fatal error, then please throw an <code>IOException</code>. Currently, this will - * tear down the whole SSH connection. - * - * @see ServerSession - * - * @author Christian - * - */ -public interface ServerSessionCallback { - public Runnable requestPtyReq(ServerSession ss, PtySettings pty) throws IOException; - - public Runnable requestEnv(ServerSession ss, String name, String value) throws IOException; - - public Runnable requestShell(ServerSession ss) throws IOException; - - public Runnable requestExec(ServerSession ss, String command) throws IOException; - - public Runnable requestSubsystem(ServerSession ss, String subsystem) throws IOException; - - /** - * When the window (terminal) size changes on the client side, it MAY send a message to the other side to inform it of the new dimensions. - * - * @param ss the corresponding session - * @param term_width_columns - * @param term_height_rows - * @param term_width_pixels - */ - public void requestWindowChange(ServerSession ss, int term_width_columns, int term_height_rows, - int term_width_pixels, int term_height_pixels) throws IOException; - - /** - * A signal can be delivered to the remote process/service. Some systems may not implement signals, in which case they SHOULD ignore this message. - * - * @param ss the corresponding session - * @param signal (a string without the "SIG" prefix) - * @return - * @throws IOException - */ - -}
--- a/src/ch/ethz/ssh2/Session.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,476 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.SecureRandom; - -import ch.ethz.ssh2.channel.Channel; -import ch.ethz.ssh2.channel.ChannelManager; -import ch.ethz.ssh2.channel.X11ServerData; - -/** - * A <code>Session</code> is a remote execution of a program. "Program" means - * in this context either a shell, an application or a system command. The - * program may or may not have a tty. Only one single program can be started on - * a session. However, multiple sessions can be active simultaneously. - * - * @author Christian Plattner - * @version $Id: Session.java 96 2014-04-08 15:14:37Z dkocher@sudo.ch $ - */ -public class Session { - private ChannelManager cm; - private Channel cn; - - private boolean flag_pty_requested = false; - private boolean flag_x11_requested = false; - private boolean flag_execution_started = false; - private boolean flag_closed = false; - - private String x11FakeCookie = null; - - private final SecureRandom rnd; - - protected Session(ChannelManager cm, SecureRandom rnd) throws IOException { - this.cm = cm; - this.cn = cm.openSessionChannel(); - this.rnd = rnd; - } - - /** - * Basically just a wrapper for lazy people - identical to calling - * <code>requestPTY("dumb", 0, 0, 0, 0, null)</code>. - * - * @throws IOException - */ - public void requestDumbPTY() throws IOException { - requestPTY("dumb", 0, 0, 0, 0, null); - } - - /** - * Basically just another wrapper for lazy people - identical to calling - * <code>requestPTY(term, 0, 0, 0, 0, null)</code>. - * - * @throws IOException - */ - public void requestPTY(String term) throws IOException { - requestPTY(term, 0, 0, 0, 0, null); - } - - /** - * Allocate a pseudo-terminal for this session. - * <p/> - * This method may only be called before a program or shell is started in - * this session. - * <p/> - * Different aspects can be specified: - * <p/> - * <ul> - * <li>The TERM environment variable value (e.g., vt100)</li> - * <li>The terminal's dimensions.</li> - * <li>The encoded terminal modes.</li> - * </ul> - * Zero dimension parameters are ignored. The character/row dimensions - * override the pixel dimensions (when nonzero). Pixel dimensions refer to - * the drawable area of the window. The dimension parameters are only - * informational. The encoding of terminal modes (parameter - * <code>terminal_modes</code>) is described in RFC4254. - * - * @param term The TERM environment variable value (e.g., vt100) - * @param term_width_characters terminal width, characters (e.g., 80) - * @param term_height_characters terminal height, rows (e.g., 24) - * @param term_width_pixels terminal width, pixels (e.g., 640) - * @param term_height_pixels terminal height, pixels (e.g., 480) - * @param terminal_modes encoded terminal modes (may be <code>null</code>) - * @throws IOException - */ - public void requestPTY(String term, int term_width_characters, int term_height_characters, int term_width_pixels, - int term_height_pixels, byte[] terminal_modes) throws IOException { - if (term == null) - throw new IllegalArgumentException("TERM cannot be null."); - - if ((terminal_modes != null) && (terminal_modes.length > 0)) { - if (terminal_modes[terminal_modes.length - 1] != 0) - throw new IOException("Illegal terminal modes description, does not end in zero byte"); - } - else - terminal_modes = new byte[] {0}; - - synchronized (this) { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); - - if (flag_pty_requested) - throw new IOException("A PTY was already requested."); - - if (flag_execution_started) - throw new IOException( - "Cannot request PTY at this stage anymore, a remote execution has already started."); - - flag_pty_requested = true; - } - - cm.requestPTY(cn, term, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels, - terminal_modes); - } - - /** - * Tells the server that the size of the terminal has changed. - * - * See {@link #requestPTY(String, int, int, int, int, byte[])} for more details about how parameters are interpreted. - * - * @param term_width_characters - * terminal width, characters (e.g., 80) - * @param term_height_characters - * terminal height, rows (e.g., 24) - * @param term_width_pixels - * terminal width, pixels (e.g., 640) - * @param term_height_pixels - * terminal height, pixels (e.g., 480) - * @throws IOException - */ - public void resizePTY(int term_width_characters, int term_height_characters, int term_width_pixels, int term_height_pixels) throws IOException { - requestWindowChange(term_width_characters, term_height_characters, term_width_pixels, term_height_pixels); - } - - public void requestWindowChange(int term_width_characters, int term_height_characters, int term_width_pixels, - int term_height_pixels) throws IOException { - synchronized (this) { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); - - if (!flag_pty_requested) - throw new IOException("A PTY was not requested."); - } - - cm.requestWindowChange(cn, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels); - } - - /** - * Request X11 forwarding for the current session. - * <p/> - * You have to supply the name and port of your X-server. - * <p/> - * This method may only be called before a program or shell is started in - * this session. - * - * @param hostname the hostname of the real (target) X11 server (e.g., 127.0.0.1) - * @param port the port of the real (target) X11 server (e.g., 6010) - * @param cookie if non-null, then present this cookie to the real X11 server - * @param singleConnection if true, then the server is instructed to only forward one single - * connection, no more connections shall be forwarded after first, or after the session - * channel has been closed - * @throws IOException - */ - public void requestX11Forwarding(String hostname, int port, byte[] cookie, boolean singleConnection) - throws IOException { - if (hostname == null) - throw new IllegalArgumentException("hostname argument may not be null"); - - synchronized (this) { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); - - if (flag_x11_requested) - throw new IOException("X11 forwarding was already requested."); - - if (flag_execution_started) - throw new IOException( - "Cannot request X11 forwarding at this stage anymore, a remote execution has already started."); - - flag_x11_requested = true; - } - - /* X11ServerData - used to store data about the target X11 server */ - X11ServerData x11data = new X11ServerData(); - x11data.hostname = hostname; - x11data.port = port; - x11data.x11_magic_cookie = cookie; /* if non-null, then present this cookie to the real X11 server */ - /* Generate fake cookie - this one is used between remote clients and the ganymed proxy */ - byte[] fakeCookie = new byte[16]; - String hexEncodedFakeCookie; - - /* Make sure that this fake cookie is unique for this connection */ - - while (true) { - rnd.nextBytes(fakeCookie); - /* Generate also hex representation of fake cookie */ - StringBuilder tmp = new StringBuilder(32); - - for (int i = 0; i < fakeCookie.length; i++) { - String digit2 = Integer.toHexString(fakeCookie[i] & 0xff); - tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2); - } - - hexEncodedFakeCookie = tmp.toString(); - - /* Well, yes, chances are low, but we want to be on the safe side */ - - if (cm.checkX11Cookie(hexEncodedFakeCookie) == null) - break; - } - - /* Ask for X11 forwarding */ - cm.requestX11(cn, singleConnection, "MIT-MAGIC-COOKIE-1", hexEncodedFakeCookie, 0); - - /* OK, that went fine, get ready to accept X11 connections... */ - /* ... but only if the user has not called close() in the meantime =) */ - - synchronized (this) { - if (flag_closed == false) { - this.x11FakeCookie = hexEncodedFakeCookie; - cm.registerX11Cookie(hexEncodedFakeCookie, x11data); - } - } - - /* Now it is safe to start remote X11 programs */ - } - - /** - * Execute a command on the remote machine. - * - * @param cmd The command to execute on the remote host. - * @throws IOException - */ - public void execCommand(String cmd) throws IOException { - this.execCommand(cmd, null); - } - - /** - * Execute a command on the remote machine. - * - * @param cmd The command to execute on the remote host. - * @param charsetName The charset used to convert between Java Unicode Strings and byte encodings - * @throws IOException - */ - public void execCommand(String cmd, String charsetName) throws IOException { - if (cmd == null) - throw new IllegalArgumentException("cmd argument may not be null"); - - synchronized (this) { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); - - if (flag_execution_started) - throw new IOException("A remote execution has already started."); - - flag_execution_started = true; - } - - cm.requestExecCommand(cn, cmd, charsetName); - } - - /** - * Start a shell on the remote machine. - * - * @throws IOException - */ - public void startShell() throws IOException { - synchronized (this) { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); - - if (flag_execution_started) - throw new IOException("A remote execution has already started."); - - flag_execution_started = true; - } - - cm.requestShell(cn); - } - - /** - * Start a subsystem on the remote machine. - * Unless you know what you are doing, you will never need this. - * - * @param name the name of the subsystem. - * @throws IOException - */ - public void startSubSystem(String name) throws IOException { - if (name == null) - throw new IllegalArgumentException("name argument may not be null"); - - synchronized (this) { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); - - if (flag_execution_started) - throw new IOException("A remote execution has already started."); - - flag_execution_started = true; - } - - cm.requestSubSystem(cn, name); - } - - /** - * Request authentication agent forwarding. - * @param agent object that implements the callbacks - * - * @throws IOException in case of any problem or when the session is closed - */ - - public synchronized void requestAuthAgentForwarding(AuthAgentCallback agent) throws IOException { - synchronized (this) { - /* - * The following is just a nicer error, we would catch it anyway - * later in the channel code - */ - if (flag_closed) - throw new IOException("This session is closed."); - } - - cm.requestChannelAgentForwarding(cn, agent); - } - - public int getState() { - return cn.getState(); - } - - public InputStream getStdout() { - return cn.getStdoutStream(); - } - - public InputStream getStderr() { - return cn.getStderrStream(); - } - - public OutputStream getStdin() { - return cn.getStdinStream(); - } - - /** - * This method blocks until there is more data available on either the - * stdout or stderr InputStream of this <code>Session</code>. Very useful - * if you do not want to use two parallel threads for reading from the two - * InputStreams. One can also specify a timeout. NOTE: do NOT call this - * method if you use concurrent threads that operate on either of the two - * InputStreams of this <code>Session</code> (otherwise this method may - * block, even though more data is available). - * - * @param timeout The (non-negative) timeout in <code>ms</code>. <code>0</code> means no - * timeout, the call may block forever. - * @return <ul> - * <li><code>0</code> if no more data will arrive.</li> - * <li><code>1</code> if more data is available.</li> - * <li><code>-1</code> if a timeout occurred.</li> - * </ul> - * @throws IOException - * @deprecated This method has been replaced with a much more powerful wait-for-condition - * interface and therefore acts only as a wrapper. - */ - public int waitUntilDataAvailable(long timeout) throws IOException { - if (timeout < 0) - throw new IllegalArgumentException("timeout must not be negative!"); - - int conditions = cm.waitForCondition(cn, timeout, ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA - | ChannelCondition.EOF); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) - return -1; - - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) != 0) - return 1; - - /* Here we do not need to check separately for CLOSED, since CLOSED implies EOF */ - - if ((conditions & ChannelCondition.EOF) != 0) - return 0; - - throw new IllegalStateException("Unexpected condition result (" + conditions + ")"); - } - - /** - * This method blocks until certain conditions hold true on the underlying SSH-2 channel. - * <p/> - * This method returns as soon as one of the following happens: - * <ul> - * <li>at least of the specified conditions (see {@link ChannelCondition}) holds true</li> - * <li>timeout > 0 and a timeout occured (TIMEOUT will be set in result conditions)</a> - * <li>the underlying channel was closed (CLOSED will be set in result conditions)</a> - * </ul> - * <p/> - * In any case, the result value contains ALL current conditions, which may be more - * than the specified condition set (i.e., never use the "==" operator to test for conditions - * in the bitmask, see also comments in {@link ChannelCondition}). - * <p/> - * Note: do NOT call this method if you want to wait for STDOUT_DATA or STDERR_DATA and - * there are concurrent threads (e.g., StreamGobblers) that operate on either of the two - * InputStreams of this <code>Session</code> (otherwise this method may - * block, even though more data is available in the StreamGobblers). - * - * @param condition_set a bitmask based on {@link ChannelCondition} values - * @param timeout non-negative timeout in ms, <code>0</code> means no timeout - * @return all bitmask specifying all current conditions that are true - */ - - public int waitForCondition(int condition_set, long timeout) throws IOException { - if (timeout < 0) - throw new IllegalArgumentException("timeout must be non-negative!"); - - return cm.waitForCondition(cn, timeout, condition_set); - } - - /** - * Get the exit code/status from the remote command - if available. Be - * careful - not all server implementations return this value. It is - * generally a good idea to call this method only when all data from the - * remote side has been consumed (see also the <code<WaitForCondition</code> method). - * - * @return An <code>Integer</code> holding the exit code, or - * <code>null</code> if no exit code is (yet) available. - */ - public Integer getExitStatus() { - return cn.getExitStatus(); - } - - /** - * Get the name of the signal by which the process on the remote side was - * stopped - if available and applicable. Be careful - not all server - * implementations return this value. - * - * @return An <code>String</code> holding the name of the signal, or - * <code>null</code> if the process exited normally or is still - * running (or if the server forgot to send this information). - */ - public String getExitSignal() { - return cn.getExitSignal(); - } - - /** - * Close this session. NEVER forget to call this method to free up resources - - * even if you got an exception from one of the other methods (or when - * getting an Exception on the Input- or OutputStreams). Sometimes these other - * methods may throw an exception, saying that the underlying channel is - * closed (this can happen, e.g., if the other server sent a close message.) - * However, as long as you have not called the <code>close()</code> - * method, you may be wasting (local) resources. - */ - public void close() { - synchronized (this) { - if (flag_closed) - return; - - flag_closed = true; - - if (x11FakeCookie != null) - cm.unRegisterX11Cookie(x11FakeCookie, true); - - try { - cm.closeChannel(cn, "Closed due to user request", true); - } - catch (IOException ignored) { - } - } - } -}
--- a/src/ch/ethz/ssh2/SimpleServerSessionCallback.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2; - -import java.io.IOException; - -/** - * A basic ServerSessionCallback implementation. - * <p> - * Note: you should derive from this class instead of implementing - * the {@link ServerSessionCallback} interface directly. This way - * your code works also in case the interface gets extended in future - * versions. - * - * @author Christian - * - */ -public class SimpleServerSessionCallback implements ServerSessionCallback { - public Runnable requestShell(ServerSession ss) throws IOException { - return null; - } - - public Runnable requestExec(ServerSession ss, String command) throws IOException { - return null; - } - - public Runnable requestSubsystem(ServerSession ss, String subsystem) throws IOException { - return null; - } - - public Runnable requestPtyReq(ServerSession ss, PtySettings pty) throws IOException { - return null; - } - - /** - * By default, silently ignore passwd environment variables. - */ - public Runnable requestEnv(ServerSession ss, String name, String value) throws IOException { - return new Runnable() { - public void run() { - /* Do nothing */ - } - }; - } - - public void requestWindowChange(ServerSession ss, int term_width_columns, int term_height_rows, - int term_width_pixels, int term_height_pixels) throws IOException { - } - -}
--- a/src/ch/ethz/ssh2/StreamGobbler.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; - -/** - * A <code>StreamGobbler</code> is an InputStream that uses an internal worker - * thread to constantly consume input from another InputStream. It uses a buffer - * to store the consumed data. The buffer size is automatically adjusted, if needed. - * <p/> - * This class is sometimes very convenient - if you wrap a session's STDOUT and STDERR - * InputStreams with instances of this class, then you don't have to bother about - * the shared window of STDOUT and STDERR in the low level SSH-2 protocol, - * since all arriving data will be immediatelly consumed by the worker threads. - * Also, as a side effect, the streams will be buffered (e.g., single byte - * read() operations are faster). - * <p/> - * Other SSH for Java libraries include this functionality by default in - * their STDOUT and STDERR InputStream implementations, however, please be aware - * that this approach has also a downside: - * <p/> - * If you do not call the StreamGobbler's <code>read()</code> method often enough - * and the peer is constantly sending huge amounts of data, then you will sooner or later - * encounter a low memory situation due to the aggregated data (well, it also depends on the Java heap size). - * Joe Average will like this class anyway - a paranoid programmer would never use such an approach. - * <p/> - * The term "StreamGobbler" was taken from an article called "When Runtime.exec() won't", - * see http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public class StreamGobbler extends InputStream { - class GobblerThread extends Thread { - @Override - public void run() { - byte[] buff = new byte[8192]; - - while (true) { - try { - int avail = is.read(buff); - - synchronized (synchronizer) { - if (avail <= 0) { - isEOF = true; - synchronizer.notifyAll(); - break; - } - - int space_available = buffer.length - write_pos; - - if (space_available < avail) { - /* compact/resize buffer */ - int unread_size = write_pos - read_pos; - int need_space = unread_size + avail; - byte[] new_buffer = buffer; - - if (need_space > buffer.length) { - int inc = need_space / 3; - inc = (inc < 256) ? 256 : inc; - inc = (inc > 8192) ? 8192 : inc; - new_buffer = new byte[need_space + inc]; - } - - if (unread_size > 0) - System.arraycopy(buffer, read_pos, new_buffer, 0, unread_size); - - buffer = new_buffer; - read_pos = 0; - write_pos = unread_size; - } - - System.arraycopy(buff, 0, buffer, write_pos, avail); - write_pos += avail; - synchronizer.notifyAll(); - } - } - catch (IOException e) { - synchronized (synchronizer) { - exception = e; - synchronizer.notifyAll(); - break; - } - } - } - } - } - - private InputStream is; - - private final Object synchronizer = new Object(); - - private boolean isEOF = false; - private boolean isClosed = false; - private IOException exception = null; - - private byte[] buffer = new byte[2048]; - private int read_pos = 0; - private int write_pos = 0; - - public StreamGobbler(InputStream is) { - this.is = is; - GobblerThread t = new GobblerThread(); - t.setDaemon(true); - t.start(); - } - - @Override - public int read() throws IOException { - synchronized (synchronizer) { - if (isClosed) - throw new IOException("This StreamGobbler is closed."); - - while (read_pos == write_pos) { - if (exception != null) - throw exception; - - if (isEOF) - return -1; - - try { - synchronizer.wait(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(); - } - } - - return buffer[read_pos++] & 0xff; - } - } - - @Override - public int available() throws IOException { - synchronized (synchronizer) { - if (isClosed) - throw new IOException("This StreamGobbler is closed."); - - return write_pos - read_pos; - } - } - - @Override - public int read(byte[] b) throws IOException { - return read(b, 0, b.length); - } - - @Override - public void close() throws IOException { - synchronized (synchronizer) { - if (isClosed) - return; - - isClosed = true; - isEOF = true; - synchronizer.notifyAll(); - is.close(); - } - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - if (b == null) - throw new NullPointerException(); - - if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) - throw new IndexOutOfBoundsException(); - - if (len == 0) - return 0; - - synchronized (synchronizer) { - if (isClosed) - throw new IOException("This StreamGobbler is closed."); - - while (read_pos == write_pos) { - if (exception != null) - throw exception; - - if (isEOF) - return -1; - - try { - synchronizer.wait(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(); - } - } - - int avail = write_pos - read_pos; - avail = (avail > len) ? len : avail; - System.arraycopy(buffer, read_pos, b, off, avail); - read_pos += avail; - return avail; - } - } -}
--- a/src/ch/ethz/ssh2/Version.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -package ch.ethz.ssh2; - -/** - * Provides version information from the manifest. - * - * @version $Id: Version.java 140 2014-04-15 13:16:25Z dkocher@sudo.ch $ - */ -public class Version { - public static String getSpecification() { - Package pkg = Version.class.getPackage(); - return (pkg == null) ? "SNAPSHOT" : pkg.getSpecificationVersion() == null ? "SNAPSHOT" : pkg.getSpecificationVersion(); - } - - public static String getImplementation() { - Package pkg = Version.class.getPackage(); - return (pkg == null) ? "SNAPSHOT" : pkg.getImplementationVersion() == null ? "SNAPSHOT" : pkg.getImplementationVersion(); - } - - /** - * A simple main method that prints the version and exits - */ - public static void main(String[] args) { - System.out.println("Version: " + getSpecification()); - System.out.println("Implementation: " + getImplementation()); - } -}
--- a/src/ch/ethz/ssh2/auth/AgentIdentity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.auth; - -public interface AgentIdentity { - String getAlgName(); - byte[] getPublicKeyBlob(); - byte[] sign(byte[] data); -}
--- a/src/ch/ethz/ssh2/auth/AgentProxy.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.auth; - -import java.util.Collection; - -public interface AgentProxy { - public Collection<AgentIdentity> getIdentities(); -}
--- a/src/ch/ethz/ssh2/auth/AuthenticationManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,424 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.auth; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.SecureRandom; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.DSAPublicKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; - -import ch.ethz.ssh2.InteractiveCallback; -import ch.ethz.ssh2.PacketTypeException; -import ch.ethz.ssh2.crypto.PEMDecoder; -import ch.ethz.ssh2.packets.PacketServiceAccept; -import ch.ethz.ssh2.packets.PacketServiceRequest; -import ch.ethz.ssh2.packets.PacketUserauthBanner; -import ch.ethz.ssh2.packets.PacketUserauthFailure; -import ch.ethz.ssh2.packets.PacketUserauthInfoRequest; -import ch.ethz.ssh2.packets.PacketUserauthInfoResponse; -import ch.ethz.ssh2.packets.PacketUserauthRequestInteractive; -import ch.ethz.ssh2.packets.PacketUserauthRequestNone; -import ch.ethz.ssh2.packets.PacketUserauthRequestPassword; -import ch.ethz.ssh2.packets.PacketUserauthRequestPublicKey; -import ch.ethz.ssh2.packets.Packets; -import ch.ethz.ssh2.packets.TypesWriter; -import ch.ethz.ssh2.signature.DSASHA1Verify; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; -import ch.ethz.ssh2.signature.RSASHA1Verify; -import ch.ethz.ssh2.transport.ClientTransportManager; -import ch.ethz.ssh2.transport.MessageHandler; - -/** - * @author Christian Plattner - * @version $Id: AuthenticationManager.java 161 2014-05-01 18:01:55Z dkocher@sudo.ch $ - */ -public class AuthenticationManager implements MessageHandler { - private ClientTransportManager tm; - - private final BlockingQueue<byte[]> packets - = new ArrayBlockingQueue<byte[]>(5); - - private boolean connectionClosed = false; - - private String banner; - - private Set<String> remainingMethods - = new HashSet<String>(); - - private boolean isPartialSuccess = false; - - private boolean authenticated = false; - private boolean initDone = false; - - public AuthenticationManager(ClientTransportManager tm) { - this.tm = tm; - } - - private byte[] deQueue() throws IOException { - if (connectionClosed) { - throw(IOException) new IOException("The connection is closed.").initCause(tm.getReasonClosedCause()); - } - - // Wait for packet - try { - return packets.take(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(e.getMessage()); - } - } - - byte[] getNextMessage() throws IOException { - while (true) { - byte[] message = deQueue(); - - switch (message[0]) { - case Packets.SSH_MSG_USERAUTH_BANNER: - // The server may send an SSH_MSG_USERAUTH_BANNER message at any - // time after this authentication protocol starts and before - // authentication is successful. - PacketUserauthBanner sb = new PacketUserauthBanner(message); - banner = sb.getBanner(); - break; - - default: - return message; - } - } - } - - public Set<String> getRemainingMethods(String user) throws IOException { - initialize(user); - return remainingMethods; - } - - public String getBanner() { - return banner; - } - - public boolean getPartialSuccess() { - return isPartialSuccess; - } - - private boolean initialize(String user) throws IOException { - if (initDone == false) { - tm.registerMessageHandler(this, 0, 255); - PacketServiceRequest sr = new PacketServiceRequest("ssh-userauth"); - tm.sendMessage(sr.getPayload()); - final PacketServiceAccept accept = new PacketServiceAccept(this.getNextMessage()); - PacketUserauthRequestNone auth = new PacketUserauthRequestNone("ssh-connection", user); - tm.sendMessage(auth.getPayload()); - byte[] message = this.getNextMessage(); - initDone = true; - - switch (message[0]) { - case Packets.SSH_MSG_USERAUTH_SUCCESS: - authenticated = true; - tm.removeMessageHandler(this); - return true; - - case Packets.SSH_MSG_USERAUTH_FAILURE: - PacketUserauthFailure puf = new PacketUserauthFailure(message); - remainingMethods = puf.getAuthThatCanContinue(); - isPartialSuccess = puf.isPartialSuccess(); - return false; - } - - throw new PacketTypeException(message[0]); - } - - return authenticated; - } - - public boolean authenticatePublicKey(String user, AgentProxy proxy) throws IOException { - initialize(user); - boolean success; - - for (AgentIdentity identity : proxy.getIdentities()) { - success = authenticatePublicKey(user, identity); - - if (success) { - return true; - } - } - - return false; - } - - private boolean authenticatePublicKey(String user, AgentIdentity identity) throws IOException { - if (!remainingMethods.contains("publickey")) { - throw new IOException("Authentication method not supported"); - } - - byte[] pubKeyBlob = identity.getPublicKeyBlob(); - - if (pubKeyBlob == null) { - return false; - } - - TypesWriter tw = new TypesWriter(); - byte[] H = tm.getSessionIdentifier(); - tw.writeString(H, 0, H.length); - tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); - tw.writeString(user); - tw.writeString("ssh-connection"); - tw.writeString("publickey"); - tw.writeBoolean(true); - tw.writeString(identity.getAlgName()); - tw.writeString(pubKeyBlob, 0, pubKeyBlob.length); - byte[] msg = tw.getBytes(); - byte[] response = identity.sign(msg); - PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey( - "ssh-connection", user, identity.getAlgName(), pubKeyBlob, response); - tm.sendMessage(ua.getPayload()); - byte[] message = getNextMessage(); - final int type = message[0]; - - switch (type) { - case Packets.SSH_MSG_USERAUTH_SUCCESS: - authenticated = true; - tm.removeMessageHandler(this); - return true; - - case Packets.SSH_MSG_USERAUTH_FAILURE: - PacketUserauthFailure puf = new PacketUserauthFailure(message); - remainingMethods = puf.getAuthThatCanContinue(); - isPartialSuccess = puf.isPartialSuccess(); - return false; - } - - throw new PacketTypeException(type); - } - - public boolean authenticatePublicKey(String user, char[] PEMPrivateKey, String password, SecureRandom rnd) - throws IOException { - KeyPair pair = PEMDecoder.decode(PEMPrivateKey, password); - return authenticatePublicKey(user, pair, rnd); - } - - public boolean authenticatePublicKey(String user, KeyPair pair, SecureRandom rnd) - throws IOException { - PrivateKey key = pair.getPrivate(); - - try { - initialize(user); - - if (!remainingMethods.contains("publickey")) { - throw new IOException("Authentication method publickey not supported by the server at this stage."); - } - - if (key instanceof DSAPrivateKey) { - DSAPrivateKey pk = (DSAPrivateKey) key; - byte[] pk_enc = DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey) pair.getPublic()); - TypesWriter tw = new TypesWriter(); - byte[] H = tm.getSessionIdentifier(); - tw.writeString(H, 0, H.length); - tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); - tw.writeString(user); - tw.writeString("ssh-connection"); - tw.writeString("publickey"); - tw.writeBoolean(true); - tw.writeString("ssh-dss"); - tw.writeString(pk_enc, 0, pk_enc.length); - byte[] msg = tw.getBytes(); - byte[] ds = DSASHA1Verify.generateSignature(msg, pk, rnd); - byte[] ds_enc = DSASHA1Verify.encodeSSHDSASignature(ds); - PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, - "ssh-dss", pk_enc, ds_enc); - tm.sendMessage(ua.getPayload()); - } - else if (key instanceof RSAPrivateKey) { - RSAPrivateKey pk = (RSAPrivateKey) key; - byte[] pk_enc = RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey) pair.getPublic()); - TypesWriter tw = new TypesWriter(); - { - byte[] H = tm.getSessionIdentifier(); - tw.writeString(H, 0, H.length); - tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); - tw.writeString(user); - tw.writeString("ssh-connection"); - tw.writeString("publickey"); - tw.writeBoolean(true); - tw.writeString("ssh-rsa"); - tw.writeString(pk_enc, 0, pk_enc.length); - } - byte[] msg = tw.getBytes(); - byte[] ds = RSASHA1Verify.generateSignature(msg, pk); - byte[] rsa_sig_enc = RSASHA1Verify.encodeSSHRSASignature(ds); - PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, - "ssh-rsa", pk_enc, rsa_sig_enc); - tm.sendMessage(ua.getPayload()); - } - else if (key instanceof ECPrivateKey) { - ECPrivateKey pk = (ECPrivateKey) key; - final String algo = ECDSASHA2Verify.ECDSA_SHA2_PREFIX - + ECDSASHA2Verify.getCurveName(pk.getParams()); - byte[] pk_enc = ECDSASHA2Verify.encodeSSHECDSAPublicKey((ECPublicKey) pair.getPublic()); - TypesWriter tw = new TypesWriter(); - { - byte[] H = tm.getSessionIdentifier(); - tw.writeString(H, 0, H.length); - tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); - tw.writeString(user); - tw.writeString("ssh-connection"); - tw.writeString("publickey"); - tw.writeBoolean(true); - tw.writeString(algo); - tw.writeString(pk_enc, 0, pk_enc.length); - } - byte[] msg = tw.getBytes(); - byte[] ds = ECDSASHA2Verify.generateSignature(msg, pk); - byte[] ec_sig_enc = ECDSASHA2Verify.encodeSSHECDSASignature(ds, pk.getParams()); - PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, - algo, pk_enc, ec_sig_enc); - tm.sendMessage(ua.getPayload()); - } - else { - throw new IOException("Unknown private key type returned by the PEM decoder."); - } - - byte[] message = getNextMessage(); - final int type = message[0]; - - switch (type) { - case Packets.SSH_MSG_USERAUTH_SUCCESS: - authenticated = true; - tm.removeMessageHandler(this); - return true; - - case Packets.SSH_MSG_USERAUTH_FAILURE: - PacketUserauthFailure puf = new PacketUserauthFailure(message); - remainingMethods = puf.getAuthThatCanContinue(); - isPartialSuccess = puf.isPartialSuccess(); - return false; - } - - throw new PacketTypeException(type); - } - catch (IOException e) { - tm.close(e, false); - throw e; - } - } - - public boolean authenticateNone(String user) throws IOException { - try { - initialize(user); - return authenticated; - } - catch (IOException e) { - tm.close(e, false); - throw e; - } - } - - public boolean authenticatePassword(String user, String pass) throws IOException { - try { - initialize(user); - - if (!remainingMethods.contains("password")) { - throw new IOException("Authentication method not supported"); - } - - PacketUserauthRequestPassword ua = new PacketUserauthRequestPassword("ssh-connection", user, pass); - tm.sendMessage(ua.getPayload()); - byte[] message = getNextMessage(); - final int type = message[0]; - - switch (type) { - case Packets.SSH_MSG_USERAUTH_SUCCESS: - authenticated = true; - tm.removeMessageHandler(this); - return true; - - case Packets.SSH_MSG_USERAUTH_FAILURE: - PacketUserauthFailure puf = new PacketUserauthFailure(message); - remainingMethods = puf.getAuthThatCanContinue(); - isPartialSuccess = puf.isPartialSuccess(); - return false; - } - - throw new PacketTypeException(type); - } - catch (IOException e) { - tm.close(e, false); - throw e; - } - } - - public boolean authenticateInteractive(String user, String[] submethods, InteractiveCallback cb) throws IOException { - try { - initialize(user); - - if (!remainingMethods.contains("keyboard-interactive")) { - throw new IOException( - "Authentication method keyboard-interactive not supported by the server at this stage."); - } - - PacketUserauthRequestInteractive ua = new PacketUserauthRequestInteractive("ssh-connection", user, - submethods); - tm.sendMessage(ua.getPayload()); - - while (true) { - byte[] message = getNextMessage(); - final int type = message[0]; - - switch (type) { - case Packets.SSH_MSG_USERAUTH_SUCCESS: - authenticated = true; - tm.removeMessageHandler(this); - return true; - - case Packets.SSH_MSG_USERAUTH_FAILURE: - PacketUserauthFailure puf = new PacketUserauthFailure(message); - remainingMethods = puf.getAuthThatCanContinue(); - isPartialSuccess = puf.isPartialSuccess(); - return false; - - case Packets.SSH_MSG_USERAUTH_INFO_REQUEST: - PacketUserauthInfoRequest info = new PacketUserauthInfoRequest(message); - String[] responses; - - try { - responses = cb.replyToChallenge(info.getName(), info.getInstruction(), info.getNumPrompts(), - info.getPrompt(), info.getEcho()); - } - catch (Exception e) { - throw new IOException("Exception in callback.", e); - } - - PacketUserauthInfoResponse puir = new PacketUserauthInfoResponse(responses); - tm.sendMessage(puir.getPayload()); - continue; - } - - throw new PacketTypeException(type); - } - } - catch (IOException e) { - tm.close(e, false); - throw e; - } - } - - public void handleFailure(final IOException failure) { - connectionClosed = true; - } - - public void handleMessage(byte[] message) throws IOException { - packets.add(message); - } -}
--- a/src/ch/ethz/ssh2/auth/ServerAuthenticationManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ - -package ch.ethz.ssh2.auth; - -import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import ch.ethz.ssh2.AuthenticationResult; -import ch.ethz.ssh2.PacketTypeException; -import ch.ethz.ssh2.ServerAuthenticationCallback; -import ch.ethz.ssh2.channel.ChannelManager; -import ch.ethz.ssh2.packets.PacketServiceAccept; -import ch.ethz.ssh2.packets.PacketServiceRequest; -import ch.ethz.ssh2.packets.PacketUserauthBanner; -import ch.ethz.ssh2.packets.PacketUserauthFailure; -import ch.ethz.ssh2.packets.PacketUserauthSuccess; -import ch.ethz.ssh2.packets.Packets; -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.server.ServerConnectionState; -import ch.ethz.ssh2.transport.MessageHandler; - -public class ServerAuthenticationManager implements MessageHandler { - private final ServerConnectionState state; - - public ServerAuthenticationManager(ServerConnectionState state) { - this.state = state; - state.tm.registerMessageHandler(this, 0, 255); - } - - private void sendresult(AuthenticationResult result) throws IOException { - if (AuthenticationResult.SUCCESS == result) { - PacketUserauthSuccess pus = new PacketUserauthSuccess(); - state.tm.sendAsynchronousMessage(pus.getPayload()); - state.tm.removeMessageHandler(this); - state.tm.registerMessageHandler(this, 50, 79); - state.cm = new ChannelManager(state); - state.flag_auth_completed = true; - } - else { - Set<String> remaining_methods = new HashSet<String>(); - - if (state.cb_auth != null) { - remaining_methods.addAll(Arrays.asList( - state.cb_auth.getRemainingAuthMethods(state.conn))); - } - - PacketUserauthFailure puf = new PacketUserauthFailure(remaining_methods, - AuthenticationResult.PARTIAL_SUCCESS == result); - state.tm.sendAsynchronousMessage(puf.getPayload()); - } - } - - public void handleFailure(final IOException failure) { - // - } - - public void handleMessage(byte[] msg) throws IOException { - /* Ignore all authentication messages after successful auth */ - if (state.flag_auth_completed) { - return; - } - - if (!state.flag_auth_serviceRequested) { - /* Must be PacketServiceRequest */ - PacketServiceRequest psr = new PacketServiceRequest(msg); - - if (!"ssh-userauth".equals(psr.getServiceName())) { - throw new IOException("SSH protocol error, expected ssh-userauth service request"); - } - - PacketServiceAccept psa = new PacketServiceAccept("ssh-userauth"); - state.tm.sendAsynchronousMessage(psa.getPayload()); - String banner = state.cb_auth.initAuthentication(state.conn); - - if (banner != null) { - PacketUserauthBanner pub = new PacketUserauthBanner(banner); - state.tm.sendAsynchronousMessage(pub.getPayload()); - } - - state.flag_auth_serviceRequested = true; - return; - } - - ServerAuthenticationCallback cb = state.cb_auth; - TypesReader tr = new TypesReader(msg); - int packet_type = tr.readByte(); - - if (packet_type == Packets.SSH_MSG_USERAUTH_REQUEST) { - String username = tr.readString("UTF-8"); - String service = tr.readString(); - String method = tr.readString(); - - if (!"ssh-connection".equals(service)) { - sendresult(AuthenticationResult.FAILURE); - return; - } - - if ("none".equals(method)) { - if (cb != null) { - sendresult(cb.authenticateWithNone(state.conn, username)); - return; - } - } - - if ("password".equals(method)) { - boolean flag_change_pass = tr.readBoolean(); - - if (flag_change_pass) { - sendresult(AuthenticationResult.FAILURE); - return; - } - - String password = tr.readString("UTF-8"); - - if (cb != null) { - sendresult(cb.authenticateWithPassword(state.conn, username, password)); - return; - } - } - - sendresult(AuthenticationResult.FAILURE); - return; - } - - throw new PacketTypeException(packet_type); - } -}
--- a/src/ch/ethz/ssh2/channel/AuthAgentForwardThread.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,546 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.DSAPrivateKeySpec; -import java.security.spec.DSAPublicKeySpec; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.ECPrivateKeySpec; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import java.security.spec.RSAPrivateCrtKeySpec; -import java.security.spec.RSAPublicKeySpec; -import java.util.Map; -import java.util.Map.Entry; - -import ch.ethz.ssh2.AuthAgentCallback; -import ch.ethz.ssh2.crypto.SecureRandomFix; -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.packets.TypesWriter; -import ch.ethz.ssh2.signature.DSASHA1Verify; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; -import ch.ethz.ssh2.signature.RSASHA1Verify; - -/** - * AuthAgentForwardThread. - * - * @author Kenny Root - * @version $Id$ - */ -public class AuthAgentForwardThread extends Thread implements IChannelWorkerThread { - private static final byte[] SSH_AGENT_FAILURE = {0, 0, 0, 1, 5}; // 5 - private static final byte[] SSH_AGENT_SUCCESS = {0, 0, 0, 1, 6}; // 6 - - private static final int SSH2_AGENTC_REQUEST_IDENTITIES = 11; - private static final int SSH2_AGENT_IDENTITIES_ANSWER = 12; - - private static final int SSH2_AGENTC_SIGN_REQUEST = 13; - private static final int SSH2_AGENT_SIGN_RESPONSE = 14; - - private static final int SSH2_AGENTC_ADD_IDENTITY = 17; - private static final int SSH2_AGENTC_REMOVE_IDENTITY = 18; - private static final int SSH2_AGENTC_REMOVE_ALL_IDENTITIES = 19; - -// private static final int SSH_AGENTC_ADD_SMARTCARD_KEY = 20; -// private static final int SSH_AGENTC_REMOVE_SMARTCARD_KEY = 21; - - private static final int SSH_AGENTC_LOCK = 22; - private static final int SSH_AGENTC_UNLOCK = 23; - - private static final int SSH2_AGENTC_ADD_ID_CONSTRAINED = 25; -// private static final int SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED = 26; - - // Constraints for adding keys - private static final int SSH_AGENT_CONSTRAIN_LIFETIME = 1; - private static final int SSH_AGENT_CONSTRAIN_CONFIRM = 2; - - // Flags for signature requests -// private static final int SSH_AGENT_OLD_SIGNATURE = 1; - - private static final Logger log = Logger.getLogger(RemoteAcceptThread.class); - - AuthAgentCallback authAgent; - OutputStream os; - InputStream is; - Channel c; - - byte[] buffer = new byte[Channel.CHANNEL_BUFFER_SIZE]; - - public AuthAgentForwardThread(Channel c, AuthAgentCallback authAgent) { - this.c = c; - this.authAgent = authAgent; - log.debug("AuthAgentForwardThread started"); - } - - @Override - public void run() { - try { - c.cm.registerThread(this); - } - catch (IOException e) { - stopWorking(); - return; - } - - try { - c.cm.sendOpenConfirmation(c); - is = c.getStdoutStream(); - os = c.getStdinStream(); - int totalSize = 4; - int readSoFar = 0; - - while (true) { - int len; - - try { - len = is.read(buffer, readSoFar, buffer.length - readSoFar); - } - catch (IOException e) { - stopWorking(); - return; - } - - if (len <= 0) - break; - - readSoFar += len; - - if (readSoFar >= 4) { - TypesReader tr = new TypesReader(buffer, 0, 4); - totalSize = tr.readUINT32() + 4; - } - - if (totalSize == readSoFar) { - TypesReader tr = new TypesReader(buffer, 4, readSoFar - 4); - int messageType = tr.readByte(); - - switch (messageType) { - case SSH2_AGENTC_REQUEST_IDENTITIES: - sendIdentities(); - break; - - case SSH2_AGENTC_ADD_IDENTITY: - addIdentity(tr, false); - break; - - case SSH2_AGENTC_ADD_ID_CONSTRAINED: - addIdentity(tr, true); - break; - - case SSH2_AGENTC_REMOVE_IDENTITY: - removeIdentity(tr); - break; - - case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: - removeAllIdentities(tr); - break; - - case SSH2_AGENTC_SIGN_REQUEST: - processSignRequest(tr); - break; - - case SSH_AGENTC_LOCK: - processLockRequest(tr); - break; - - case SSH_AGENTC_UNLOCK: - processUnlockRequest(tr); - break; - - default: - os.write(SSH_AGENT_FAILURE); - break; - } - - readSoFar = 0; - } - } - - c.cm.closeChannel(c, "EOF on both streams reached.", true); - } - catch (IOException e) { - log.debug("IOException in agent forwarder: " + e.getMessage()); - - try { - is.close(); - } - catch (IOException e1) { - } - - try { - os.close(); - } - catch (IOException e2) { - } - - try { - c.cm.closeChannel(c, "IOException in agent forwarder (" + e.getMessage() + ")", true); - } - catch (IOException e3) { - } - } - } - - public void stopWorking() { - try { - /* This will lead to an IOException in the is.read() call */ - is.close(); - } - catch (IOException e) { - } - } - - /** - * @return whether the agent is locked - */ - private boolean failWhenLocked() throws IOException { - if (authAgent.isAgentLocked()) { - os.write(SSH_AGENT_FAILURE); - return true; - } - else - return false; - } - - private void sendIdentities() throws IOException { - Map<String, byte[]> keys = null; - TypesWriter tw = new TypesWriter(); - tw.writeByte(SSH2_AGENT_IDENTITIES_ANSWER); - int numKeys = 0; - - if (!authAgent.isAgentLocked()) - keys = authAgent.retrieveIdentities(); - - if (keys != null) - numKeys = keys.size(); - - tw.writeUINT32(numKeys); - - if (keys != null) { - for (Entry<String, byte[]> entry : keys.entrySet()) { - byte[] keyBytes = entry.getValue(); - tw.writeString(keyBytes, 0, keyBytes.length); - tw.writeString(entry.getKey()); - } - } - - sendPacket(tw.getBytes()); - } - - /** - * @param tr - */ - private void addIdentity(TypesReader tr, boolean checkConstraints) { - try { - if (failWhenLocked()) - return; - - String type = tr.readString(); - String comment; - String keyType; - KeySpec pubSpec; - KeySpec privSpec; - - if (type.equals("ssh-rsa")) { - keyType = "RSA"; - BigInteger n = tr.readMPINT(); - BigInteger e = tr.readMPINT(); - BigInteger d = tr.readMPINT(); - BigInteger iqmp = tr.readMPINT(); - BigInteger p = tr.readMPINT(); - BigInteger q = tr.readMPINT(); - comment = tr.readString(); - // Derive the extra values Java needs. - BigInteger dmp1 = d.mod(p.subtract(BigInteger.ONE)); - BigInteger dmq1 = d.mod(q.subtract(BigInteger.ONE)); - pubSpec = new RSAPublicKeySpec(n, e); - privSpec = new RSAPrivateCrtKeySpec(n, e, d, p, q, dmp1, dmq1, iqmp); - } - else if (type.equals("ssh-dss")) { - keyType = "DSA"; - BigInteger p = tr.readMPINT(); - BigInteger q = tr.readMPINT(); - BigInteger g = tr.readMPINT(); - BigInteger y = tr.readMPINT(); - BigInteger x = tr.readMPINT(); - comment = tr.readString(); - pubSpec = new DSAPublicKeySpec(y, p, q, g); - privSpec = new DSAPrivateKeySpec(x, p, q, g); - } - else if (type.equals("ecdsa-sha2-nistp256")) { - keyType = "EC"; - String curveName = tr.readString(); - byte[] groupBytes = tr.readByteString(); - BigInteger exponent = tr.readMPINT(); - comment = tr.readString(); - - if (!"nistp256".equals(curveName)) { - log.debug("Invalid curve name for ecdsa-sha2-nistp256: " + curveName); - os.write(SSH_AGENT_FAILURE); - return; - } - - ECParameterSpec nistp256 = ECDSASHA2Verify.EllipticCurves.nistp256; - ECPoint group = ECDSASHA2Verify.decodeECPoint(groupBytes, nistp256.getCurve()); - - if (group == null) { - log.debug("No groupfor ecdsa-sha2-nistp256: "); - os.write(SSH_AGENT_FAILURE); - return; - } - - pubSpec = new ECPublicKeySpec(group, nistp256); - privSpec = new ECPrivateKeySpec(exponent, nistp256); - } - else { - log.debug("Unknown key type: " + type); - os.write(SSH_AGENT_FAILURE); - return; - } - - PublicKey pubKey; - PrivateKey privKey; - - try { - KeyFactory kf = KeyFactory.getInstance(keyType); - pubKey = kf.generatePublic(pubSpec); - privKey = kf.generatePrivate(privSpec); - } - catch (NoSuchAlgorithmException ex) { - // TODO: log error - os.write(SSH_AGENT_FAILURE); - return; - } - catch (InvalidKeySpecException ex) { - // TODO: log error - os.write(SSH_AGENT_FAILURE); - return; - } - - KeyPair pair = new KeyPair(pubKey, privKey); - boolean confirmUse = false; - int lifetime = 0; - - if (checkConstraints) { - while (tr.remain() > 0) { - int constraint = tr.readByte(); - - if (constraint == SSH_AGENT_CONSTRAIN_CONFIRM) - confirmUse = true; - else if (constraint == SSH_AGENT_CONSTRAIN_LIFETIME) - lifetime = tr.readUINT32(); - else { - // Unknown constraint. Bail. - os.write(SSH_AGENT_FAILURE); - return; - } - } - } - - if (authAgent.addIdentity(pair, comment, confirmUse, lifetime)) - os.write(SSH_AGENT_SUCCESS); - else - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e) { - try { - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e1) { - } - } - } - - /** - * @param tr - */ - private void removeIdentity(TypesReader tr) { - try { - if (failWhenLocked()) - return; - - byte[] publicKey = tr.readByteString(); - - if (authAgent.removeIdentity(publicKey)) - os.write(SSH_AGENT_SUCCESS); - else - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e) { - try { - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e1) { - } - } - } - - /** - * @param tr - */ - private void removeAllIdentities(TypesReader tr) { - try { - if (failWhenLocked()) - return; - - if (authAgent.removeAllIdentities()) - os.write(SSH_AGENT_SUCCESS); - else - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e) { - try { - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e1) { - } - } - } - - private void processSignRequest(TypesReader tr) { - try { - if (failWhenLocked()) - return; - - byte[] publicKeyBytes = tr.readByteString(); - byte[] challenge = tr.readByteString(); - int flags = tr.readUINT32(); - - if (flags != 0) { - // We don't understand any flags; abort! - os.write(SSH_AGENT_FAILURE); - return; - } - - KeyPair pair = authAgent.getKeyPair(publicKeyBytes); - - if (pair == null) { - os.write(SSH_AGENT_FAILURE); - return; - } - - byte[] response; - PrivateKey privKey = pair.getPrivate(); - - if (privKey instanceof RSAPrivateKey) { - byte[] signature = RSASHA1Verify.generateSignature(challenge, - (RSAPrivateKey) privKey); - response = RSASHA1Verify.encodeSSHRSASignature(signature); - } - else if (privKey instanceof DSAPrivateKey) { - byte[] signature = DSASHA1Verify.generateSignature(challenge, - (DSAPrivateKey) privKey, new SecureRandomFix()); - response = DSASHA1Verify.encodeSSHDSASignature(signature); - } - else if (privKey instanceof ECPrivateKey) { - ECPrivateKey pk = (ECPrivateKey) privKey; - byte[] signature = ECDSASHA2Verify.generateSignature(challenge, pk); - response = ECDSASHA2Verify.encodeSSHECDSASignature(signature, pk.getParams()); - } - else { - os.write(SSH_AGENT_FAILURE); - return; - } - - TypesWriter tw = new TypesWriter(); - tw.writeByte(SSH2_AGENT_SIGN_RESPONSE); - tw.writeString(response, 0, response.length); - sendPacket(tw.getBytes()); - } - catch (IOException e) { - try { - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e1) { - } - } - } - - /** - * @param tr - */ - private void processLockRequest(TypesReader tr) { - try { - if (failWhenLocked()) - return; - - String lockPassphrase = tr.readString(); - - if (!authAgent.setAgentLock(lockPassphrase)) { - os.write(SSH_AGENT_FAILURE); - return; - } - else - os.write(SSH_AGENT_SUCCESS); - } - catch (IOException e) { - try { - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e1) { - } - } - } - - /** - * @param tr - */ - private void processUnlockRequest(TypesReader tr) { - try { - String unlockPassphrase = tr.readString(); - - if (authAgent.requestAgentUnlock(unlockPassphrase)) - os.write(SSH_AGENT_SUCCESS); - else - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e) { - try { - os.write(SSH_AGENT_FAILURE); - } - catch (IOException e1) { - } - } - } - - /** - * @param tw - * @throws IOException - */ - private void sendPacket(byte[] message) throws IOException { - TypesWriter packet = new TypesWriter(); - packet.writeUINT32(message.length); - packet.writeBytes(message); - os.write(packet.getBytes()); - } -}
--- a/src/ch/ethz/ssh2/channel/Channel.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -import java.io.IOException; - -import ch.ethz.ssh2.transport.TransportManager; - -/** - * Channel. - * - * @author Christian Plattner - * @version $Id: Channel.java 123 2014-04-12 21:11:47Z dkocher@sudo.ch $ - */ -public class Channel { - /* - * OK. Here is an important part of the JVM Specification: - * (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html#22214) - * - * Any association between locks and variables is purely conventional. - * Locking any lock conceptually flushes all variables from a thread's - * working memory, and unlocking any lock forces the writing out to main - * memory of all variables that the thread has assigned. That a lock may be - * associated with a particular object or a class is purely a convention. - * (...) - * - * If a thread uses a particular shared variable only after locking a - * particular lock and before the corresponding unlocking of that same lock, - * then the thread will read the shared value of that variable from main - * memory after the lock operation, if necessary, and will copy back to main - * memory the value most recently assigned to that variable before the - * unlock operation. - * - * This, in conjunction with the mutual exclusion rules for locks, suffices - * to guarantee that values are correctly transmitted from one thread to - * another through shared variables. - * - * ====> Always keep that in mind when modifying the Channel/ChannelManger - * code. - * - */ - - public static final int STATE_OPENING = 1; - public static final int STATE_OPEN = 2; - public static final int STATE_CLOSED = 4; - - static final int CHANNEL_BUFFER_SIZE = 32 * 1024 * 3 * 2; - - /* - * To achieve correctness, the following rules have to be respected when - * accessing this object: - */ - - // These fields can always be read - final ChannelManager cm; - final ChannelOutputStream stdinStream; - final ChannelInputStream stdoutStream; - final ChannelInputStream stderrStream; - - // In case this channel belongs to a server-side session. - ServerSessionImpl ss; - - // These two fields will only be written while the Channel is in state - // STATE_OPENING. - // The code makes sure that the two fields are written out when the state is - // changing to STATE_OPEN. - // Therefore, if you know that the Channel is in state STATE_OPEN, then you - // can read these two fields without synchronizing on the Channel. However, make - // sure that you get the latest values (e.g., flush caches by synchronizing on any - // object). However, to be on the safe side, you can lock the channel. - - int localID = -1; - int remoteID = -1; - - /* - * Make sure that we never send a data/EOF/WindowChange msg after a CLOSE - * msg. - * - * This is a little bit complicated, but we have to do it in that way, since - * we cannot keep a lock on the Channel during the send operation (this - * would block sometimes the receiver thread, and, in extreme cases, can - * lead to a deadlock on both sides of the connection (senders are blocked - * since the receive buffers on the other side are full, and receiver - * threads wait for the senders to finish). It all depends on the - * implementation on the other side. But we cannot make any assumptions, we - * have to assume the worst case. Confused? Just believe me. - */ - - /* - * If you send a message on a channel, then you have to aquire the - * "channelSendLock" and check the "closeMessageSent" flag (this variable - * may only be accessed while holding the "channelSendLock" !!! - * - * BTW: NEVER EVER SEND MESSAGES FROM THE RECEIVE THREAD - see explanation - * above. - */ - - final Object channelSendLock = new Object(); - boolean closeMessageSent = false; - - /* - * Stop memory fragmentation by allocating this often used buffer. - * May only be used while holding the channelSendLock - */ - - final byte[] msgWindowAdjust = new byte[9]; - - // If you access (read or write) any of the following fields, then you have - // to synchronize on the channel. - - int state = STATE_OPENING; - - boolean closeMessageRecv = false; - - /* This is a stupid implementation. At the moment we can only wait - * for one pending request per channel. - */ - int successCounter = 0; - int failedCounter = 0; - - int localWindow = 0; /* locally, we use a small window, < 2^31 */ - long remoteWindow = 0; /* long for readable 2^32 - 1 window support */ - - int localMaxPacketSize = -1; - int remoteMaxPacketSize = -1; - - final byte[] stdoutBuffer = new byte[CHANNEL_BUFFER_SIZE]; - final byte[] stderrBuffer = new byte[CHANNEL_BUFFER_SIZE]; - - int stdoutReadpos = 0; - int stdoutWritepos = 0; - int stderrReadpos = 0; - int stderrWritepos = 0; - - boolean EOF = false; - - Integer exit_status; - - String exit_signal; - - // we keep the x11 cookie so that this channel can be closed when this - // specific x11 forwarding gets stopped - - String hexX11FakeCookie; - - // reasonClosed is special, since we sometimes need to access it - // while holding the channelSendLock. - // We protect it with a private short term lock. - - private final Object reasonClosedLock = new Object(); - private IOException reasonClosed = null; - - public Channel(ChannelManager cm) { - this.cm = cm; - this.localWindow = CHANNEL_BUFFER_SIZE; - this.localMaxPacketSize = TransportManager.MAX_PACKET_SIZE; - this.stdinStream = new ChannelOutputStream(this); - this.stdoutStream = new ChannelInputStream(this, false); - this.stderrStream = new ChannelInputStream(this, true); - } - - /* Methods to allow access from classes outside of this package */ - - public ChannelInputStream getStderrStream() { - return stderrStream; - } - - public ChannelOutputStream getStdinStream() { - return stdinStream; - } - - public ChannelInputStream getStdoutStream() { - return stdoutStream; - } - - public String getExitSignal() { - synchronized (this) { - return exit_signal; - } - } - - public Integer getExitStatus() { - synchronized (this) { - return exit_status; - } - } - - public IOException getReasonClosed() { - synchronized (reasonClosedLock) { - return reasonClosed; - } - } - - public void setReasonClosed(IOException e) { - synchronized (reasonClosedLock) { - this.reasonClosed = e; - } - } - - public int getState() { - return this.state; - } -}
--- a/src/ch/ethz/ssh2/channel/ChannelClosedException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2011 David Kocher. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2.channel; - -import java.io.IOException; - -/** - * @version $Id: ChannelClosedException.java 3183 2007-07-30 19:22:34Z dkocher $ - */ -public class ChannelClosedException extends IOException { - - /** - * - */ - private static final long serialVersionUID = 1L; - - public ChannelClosedException(String s) { - super(s); - } -}
--- a/src/ch/ethz/ssh2/channel/ChannelInputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.io.InputStream; - -/** - * ChannelInputStream. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class ChannelInputStream extends InputStream { - Channel c; - - boolean isClosed = false; - boolean isEOF = false; - boolean extendedFlag = false; - - ChannelInputStream(Channel c, boolean isExtended) { - this.c = c; - this.extendedFlag = isExtended; - } - - @Override - public int available() throws IOException { - if (isEOF) - return 0; - - int avail = c.cm.getAvailable(c, extendedFlag); - /* We must not return -1 on EOF */ - return (avail > 0) ? avail : 0; - } - - @Override - public void close() throws IOException { - isClosed = true; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - if (b == null) - throw new NullPointerException(); - - if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) - throw new IndexOutOfBoundsException(); - - if (len == 0) - return 0; - - if (isEOF) - return -1; - - int ret = c.cm.getChannelData(c, extendedFlag, b, off, len); - - if (ret == -1) { - isEOF = true; - } - - return ret; - } - - @Override - public int read(byte[] b) throws IOException { - return read(b, 0, b.length); - } - - @Override - public int read() throws IOException { - /* Yes, this stream is pure and unbuffered, a single byte read() is slow */ - final byte b[] = new byte[1]; - int ret = read(b, 0, 1); - - if (ret != 1) - return -1; - - return b[0] & 0xff; - } -}
--- a/src/ch/ethz/ssh2/channel/ChannelManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1653 +0,0 @@ -/* - - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import ch.ethz.ssh2.AuthAgentCallback; -import ch.ethz.ssh2.ChannelCondition; -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; -import ch.ethz.ssh2.PtySettings; -import ch.ethz.ssh2.ServerConnectionCallback; -import ch.ethz.ssh2.ServerSessionCallback; -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.PacketChannelAuthAgentReq; -import ch.ethz.ssh2.packets.PacketChannelFailure; -import ch.ethz.ssh2.packets.PacketChannelOpenConfirmation; -import ch.ethz.ssh2.packets.PacketChannelOpenFailure; -import ch.ethz.ssh2.packets.PacketChannelSuccess; -import ch.ethz.ssh2.packets.PacketGlobalCancelForwardRequest; -import ch.ethz.ssh2.packets.PacketGlobalForwardRequest; -import ch.ethz.ssh2.packets.PacketOpenDirectTCPIPChannel; -import ch.ethz.ssh2.packets.PacketOpenSessionChannel; -import ch.ethz.ssh2.packets.PacketSessionExecCommand; -import ch.ethz.ssh2.packets.PacketSessionPtyRequest; -import ch.ethz.ssh2.packets.PacketSessionStartShell; -import ch.ethz.ssh2.packets.PacketSessionSubsystemRequest; -import ch.ethz.ssh2.packets.PacketSessionX11Request; -import ch.ethz.ssh2.packets.PacketWindowChange; -import ch.ethz.ssh2.packets.Packets; -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.server.ServerConnectionState; -import ch.ethz.ssh2.transport.MessageHandler; -import ch.ethz.ssh2.transport.TransportManager; - -/** - * ChannelManager. Please read the comments in Channel.java. - * <p/> - * Besides the crypto part, this is the core of the library. - * - * @author Christian Plattner - * @version $Id: ChannelManager.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public class ChannelManager implements MessageHandler { - private static final Logger log = Logger.getLogger(ChannelManager.class); - - private final ServerConnectionState server_state; - private final TransportManager tm; - - private final Map<String, X11ServerData> x11_magic_cookies = new HashMap<String, X11ServerData>(); - - private final List<Channel> channels = new ArrayList<Channel>(); - private int nextLocalChannel = 100; - private boolean shutdown = false; - private int globalSuccessCounter = 0; - private int globalFailedCounter = 0; - - private final HashMap<Integer, RemoteForwardingData> remoteForwardings = new HashMap<Integer, RemoteForwardingData>(); - - private AuthAgentCallback authAgent; - - private final List<IChannelWorkerThread> listenerThreads = new ArrayList<IChannelWorkerThread>(); - - private boolean listenerThreadsAllowed = true; - - /** - * Constructor for client-mode. - * - * @param tm - */ - public ChannelManager(TransportManager tm) { - this.server_state = null; - this.tm = tm; - tm.registerMessageHandler(this, 80, 100); - } - - /** - * Constructor for server-mode. - * - * @param state - */ - public ChannelManager(ServerConnectionState state) { - this.server_state = state; - this.tm = state.tm; - tm.registerMessageHandler(this, 80, 100); - } - - private Channel getChannel(int id) { - synchronized (channels) { - for (Channel c : channels) { - if (c.localID == id) { - return c; - } - } - } - - return null; - } - - private void removeChannel(int id) { - synchronized (channels) { - for (Channel c : channels) { - if (c.localID == id) { - channels.remove(c); - break; - } - } - } - } - - private int addChannel(Channel c) { - synchronized (channels) { - channels.add(c); - return nextLocalChannel++; - } - } - - private void waitUntilChannelOpen(Channel c) throws IOException { - synchronized (c) { - while (c.state == Channel.STATE_OPENING) { - try { - c.wait(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(e.getMessage()); - } - } - - if (c.state != Channel.STATE_OPEN) { - removeChannel(c.localID); - throw c.getReasonClosed(); - } - } - } - - private void waitForGlobalSuccessOrFailure() throws IOException { - synchronized (channels) { - while ((globalSuccessCounter == 0) && (globalFailedCounter == 0)) { - if (shutdown) { - throw new IOException("The connection is being shutdown"); - } - - try { - channels.wait(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(e.getMessage()); - } - } - - if ((globalFailedCounter == 0) && (globalSuccessCounter == 1)) { - return; - } - - if ((globalFailedCounter == 1) && (globalSuccessCounter == 0)) { - throw new IOException("The server denied the request (did you enable port forwarding?)"); - } - - throw new IOException("Illegal state. The server sent " + globalSuccessCounter - + " SSH_MSG_REQUEST_SUCCESS and " + globalFailedCounter + " SSH_MSG_REQUEST_FAILURE messages."); - } - } - - private void waitForChannelSuccessOrFailure(Channel c) throws IOException { - synchronized (c) { - while ((c.successCounter == 0) && (c.failedCounter == 0)) { - if (c.state != Channel.STATE_OPEN) { - throw c.getReasonClosed(); - } - - try { - c.wait(); - } - catch (InterruptedException ignore) { - throw new InterruptedIOException(); - } - } - - if ((c.failedCounter == 0) && (c.successCounter == 1)) { - return; - } - - if ((c.failedCounter == 1) && (c.successCounter == 0)) { - throw new IOException("The server denied the request."); - } - - throw new IOException("Illegal state. The server sent " + c.successCounter - + " SSH_MSG_CHANNEL_SUCCESS and " + c.failedCounter + " SSH_MSG_CHANNEL_FAILURE messages."); - } - } - - public void registerX11Cookie(String hexFakeCookie, X11ServerData data) { - synchronized (x11_magic_cookies) { - x11_magic_cookies.put(hexFakeCookie, data); - } - } - - public void unRegisterX11Cookie(String hexFakeCookie, boolean killChannels) { - if (hexFakeCookie == null) { - throw new IllegalStateException("hexFakeCookie may not be null"); - } - - synchronized (x11_magic_cookies) { - x11_magic_cookies.remove(hexFakeCookie); - } - - if (killChannels == false) { - return; - } - - log.debug("Closing all X11 channels for the given fake cookie"); - List<Channel> channel_copy = new ArrayList<Channel>(); - - synchronized (channels) { - channel_copy.addAll(channels); - } - - for (Channel c : channel_copy) { - synchronized (c) { - if (hexFakeCookie.equals(c.hexX11FakeCookie) == false) { - continue; - } - } - - try { - closeChannel(c, "Closing X11 channel since the corresponding session is closing", true); - } - catch (IOException ignored) { - } - } - } - - public X11ServerData checkX11Cookie(String hexFakeCookie) { - synchronized (x11_magic_cookies) { - if (hexFakeCookie != null) { - return x11_magic_cookies.get(hexFakeCookie); - } - } - - return null; - } - - public void closeAllChannels() { - log.debug("Closing all channels"); - List<Channel> channel_copy = new ArrayList<Channel>(); - - synchronized (channels) { - channel_copy.addAll(channels); - } - - for (Channel c : channel_copy) { - try { - closeChannel(c, "Closing all channels", true); - } - catch (IOException ignored) { - } - } - } - - public void closeChannel(Channel c, String reason, boolean force) throws IOException { - this.closeChannel(c, new ChannelClosedException(reason), force); - } - - public void closeChannel(Channel c, IOException reason, boolean force) throws IOException { - byte msg[] = new byte[5]; - - synchronized (c) { - if (force) { - c.state = Channel.STATE_CLOSED; - c.EOF = true; - } - - c.setReasonClosed(reason); - msg[0] = Packets.SSH_MSG_CHANNEL_CLOSE; - msg[1] = (byte)(c.remoteID >> 24); - msg[2] = (byte)(c.remoteID >> 16); - msg[3] = (byte)(c.remoteID >> 8); - msg[4] = (byte)(c.remoteID); - c.notifyAll(); - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent) { - return; - } - - tm.sendMessage(msg); - c.closeMessageSent = true; - } - - log.debug("Sent SSH_MSG_CHANNEL_CLOSE (channel " + c.localID + ")"); - } - - public void sendEOF(Channel c) throws IOException { - byte[] msg = new byte[5]; - - synchronized (c) { - if (c.state != Channel.STATE_OPEN) { - return; - } - - msg[0] = Packets.SSH_MSG_CHANNEL_EOF; - msg[1] = (byte)(c.remoteID >> 24); - msg[2] = (byte)(c.remoteID >> 16); - msg[3] = (byte)(c.remoteID >> 8); - msg[4] = (byte)(c.remoteID); - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent == true) { - return; - } - - tm.sendMessage(msg); - } - - log.debug("Sent EOF (Channel " + c.localID + "/" + c.remoteID + ")"); - } - - public void sendOpenConfirmation(Channel c) throws IOException { - PacketChannelOpenConfirmation pcoc = null; - - synchronized (c) { - if (c.state != Channel.STATE_OPENING) { - return; - } - - c.state = Channel.STATE_OPEN; - pcoc = new PacketChannelOpenConfirmation(c.remoteID, c.localID, c.localWindow, c.localMaxPacketSize); - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent == true) { - return; - } - - tm.sendMessage(pcoc.getPayload()); - } - } - - public void sendData(Channel c, byte[] buffer, int pos, int len) throws IOException { - while (len > 0) { - int thislen = 0; - byte[] msg; - - synchronized (c) { - while (true) { - if (c.state == Channel.STATE_CLOSED) { - throw c.getReasonClosed(); - } - - if (c.state != Channel.STATE_OPEN) { - throw new ChannelClosedException("SSH channel in strange state. (" + c.state + ")"); - } - - if (c.remoteWindow != 0) { - break; - } - - try { - c.wait(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(e.getMessage()); - } - } - - /* len > 0, no sign extension can happen when comparing */ - thislen = (c.remoteWindow >= len) ? len : (int) c.remoteWindow; - int estimatedMaxDataLen = c.remoteMaxPacketSize - (tm.getPacketOverheadEstimate() + 9); - - /* The worst case scenario =) a true bottleneck */ - - if (estimatedMaxDataLen <= 0) { - estimatedMaxDataLen = 1; - } - - if (thislen > estimatedMaxDataLen) { - thislen = estimatedMaxDataLen; - } - - c.remoteWindow -= thislen; - msg = new byte[1 + 8 + thislen]; - msg[0] = Packets.SSH_MSG_CHANNEL_DATA; - msg[1] = (byte)(c.remoteID >> 24); - msg[2] = (byte)(c.remoteID >> 16); - msg[3] = (byte)(c.remoteID >> 8); - msg[4] = (byte)(c.remoteID); - msg[5] = (byte)(thislen >> 24); - msg[6] = (byte)(thislen >> 16); - msg[7] = (byte)(thislen >> 8); - msg[8] = (byte)(thislen); - System.arraycopy(buffer, pos, msg, 9, thislen); - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent) { - throw c.getReasonClosed(); - } - - tm.sendMessage(msg); - } - - pos += thislen; - len -= thislen; - } - } - - public int requestGlobalForward(String bindAddress, int bindPort, String targetAddress, int targetPort) - throws IOException { - RemoteForwardingData rfd = new RemoteForwardingData(); - rfd.bindAddress = bindAddress; - rfd.bindPort = bindPort; - rfd.targetAddress = targetAddress; - rfd.targetPort = targetPort; - - synchronized (remoteForwardings) { - if (remoteForwardings.get(bindPort) != null) { - throw new IOException("There is already a forwarding for remote port " + bindPort); - } - - remoteForwardings.put(bindPort, rfd); - } - - synchronized (channels) { - globalSuccessCounter = globalFailedCounter = 0; - } - - PacketGlobalForwardRequest pgf = new PacketGlobalForwardRequest(true, bindAddress, bindPort); - tm.sendMessage(pgf.getPayload()); - log.debug("Requesting a remote forwarding ('" + bindAddress + "', " + bindPort + ")"); - - try { - waitForGlobalSuccessOrFailure(); - } - catch (IOException e) { - synchronized (remoteForwardings) { - remoteForwardings.remove(bindPort); - } - - throw e; - } - - return bindPort; - } - - public void requestCancelGlobalForward(int bindPort) throws IOException { - RemoteForwardingData rfd; - - synchronized (remoteForwardings) { - rfd = remoteForwardings.get(bindPort); - - if (rfd == null) { - throw new IOException("Sorry, there is no known remote forwarding for remote port " + bindPort); - } - } - - synchronized (channels) { - globalSuccessCounter = globalFailedCounter = 0; - } - - PacketGlobalCancelForwardRequest pgcf = new PacketGlobalCancelForwardRequest(true, rfd.bindAddress, - rfd.bindPort); - tm.sendMessage(pgcf.getPayload()); - log.debug("Requesting cancelation of remote forward ('" + rfd.bindAddress + "', " + rfd.bindPort + ")"); - waitForGlobalSuccessOrFailure(); - - /* Only now we are sure that no more forwarded connections will arrive */ - - synchronized (remoteForwardings) { - remoteForwardings.remove(bindPort); - } - } - - /** - * @param agent - * @throws IOException - */ - public void requestChannelAgentForwarding(Channel c, AuthAgentCallback authAgent) throws IOException { - synchronized (this) { - if (this.authAgent != null) - throw new IllegalStateException("Auth agent already exists"); - - this.authAgent = authAgent; - } - - synchronized (channels) { - globalSuccessCounter = globalFailedCounter = 0; - } - - log.debug("Requesting agent forwarding"); - PacketChannelAuthAgentReq aar = new PacketChannelAuthAgentReq(c.remoteID); - - synchronized (c.channelSendLock) { - if (c.closeMessageSent) { - throw c.getReasonClosed(); - } - - tm.sendMessage(aar.getPayload()); - } - - try { - waitForChannelSuccessOrFailure(c); - } - catch (IOException e) { - authAgent = null; - throw e; - } - } - - public void registerThread(IChannelWorkerThread thr) throws IOException { - synchronized (listenerThreads) { - if (listenerThreadsAllowed == false) { - throw new IOException("Too late, this connection is closed."); - } - - listenerThreads.add(thr); - } - } - - public Channel openDirectTCPIPChannel(String host_to_connect, int port_to_connect, String originator_IP_address, - int originator_port) throws IOException { - Channel c = new Channel(this); - - synchronized (c) { - c.localID = addChannel(c); - // end of synchronized block forces writing out to main memory - } - - PacketOpenDirectTCPIPChannel dtc = new PacketOpenDirectTCPIPChannel(c.localID, c.localWindow, - c.localMaxPacketSize, host_to_connect, port_to_connect, originator_IP_address, originator_port); - tm.sendMessage(dtc.getPayload()); - waitUntilChannelOpen(c); - return c; - } - - public Channel openSessionChannel() throws IOException { - Channel c = new Channel(this); - - synchronized (c) { - c.localID = addChannel(c); - // end of synchronized block forces the writing out to main memory - } - - log.debug("Sending SSH_MSG_CHANNEL_OPEN (Channel " + c.localID + ")"); - PacketOpenSessionChannel smo = new PacketOpenSessionChannel(c.localID, c.localWindow, c.localMaxPacketSize); - tm.sendMessage(smo.getPayload()); - waitUntilChannelOpen(c); - return c; - } - - public void requestPTY(Channel c, String term, int term_width_characters, int term_height_characters, - int term_width_pixels, int term_height_pixels, byte[] terminal_modes) throws IOException { - PacketSessionPtyRequest spr; - - synchronized (c) { - if (c.state != Channel.STATE_OPEN) { - throw c.getReasonClosed(); - } - - spr = new PacketSessionPtyRequest(c.remoteID, true, term, term_width_characters, term_height_characters, - term_width_pixels, term_height_pixels, terminal_modes); - c.successCounter = c.failedCounter = 0; - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent) { - throw c.getReasonClosed(); - } - - tm.sendMessage(spr.getPayload()); - } - - try { - waitForChannelSuccessOrFailure(c); - } - catch (IOException e) { - throw new IOException("PTY request failed", e); - } - } - - public void requestWindowChange(Channel c, int term_width_characters, int term_height_characters, - int term_width_pixels, int term_height_pixels) throws IOException { - PacketWindowChange pwc; - - synchronized (c) { - if (c.state != Channel.STATE_OPEN) { - throw c.getReasonClosed(); - } - - pwc = new PacketWindowChange(c.remoteID, term_width_characters, term_height_characters, - term_width_pixels, term_height_pixels); - c.successCounter = c.failedCounter = 0; - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent) { - throw c.getReasonClosed(); - } - - tm.sendMessage(pwc.getPayload()); - } - } - - public void requestX11(Channel c, boolean singleConnection, String x11AuthenticationProtocol, - String x11AuthenticationCookie, int x11ScreenNumber) throws IOException { - PacketSessionX11Request psr; - - synchronized (c) { - if (c.state != Channel.STATE_OPEN) { - throw c.getReasonClosed(); - } - - psr = new PacketSessionX11Request(c.remoteID, true, singleConnection, x11AuthenticationProtocol, - x11AuthenticationCookie, x11ScreenNumber); - c.successCounter = c.failedCounter = 0; - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent) { - throw c.getReasonClosed(); - } - - tm.sendMessage(psr.getPayload()); - } - - log.debug("Requesting X11 forwarding (Channel " + c.localID + "/" + c.remoteID + ")"); - - try { - waitForChannelSuccessOrFailure(c); - } - catch (IOException e) { - throw new IOException("The X11 request failed.", e); - } - } - - public void requestSubSystem(Channel c, String subSystemName) throws IOException { - PacketSessionSubsystemRequest ssr; - - synchronized (c) { - if (c.state != Channel.STATE_OPEN) { - throw c.getReasonClosed(); - } - - ssr = new PacketSessionSubsystemRequest(c.remoteID, true, subSystemName); - c.successCounter = c.failedCounter = 0; - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent) { - throw c.getReasonClosed(); - } - - tm.sendMessage(ssr.getPayload()); - } - - try { - waitForChannelSuccessOrFailure(c); - } - catch (IOException e) { - throw new IOException("The subsystem request failed.", e); - } - } - - public void requestExecCommand(Channel c, String cmd) throws IOException { - this.requestExecCommand(c, cmd, null); - } - - /** - * @param charsetName The charset used to convert between Java Unicode Strings and byte encodings - */ - public void requestExecCommand(Channel c, String cmd, String charsetName) throws IOException { - PacketSessionExecCommand sm; - - synchronized (c) { - if (c.state != Channel.STATE_OPEN) { - throw c.getReasonClosed(); - } - - sm = new PacketSessionExecCommand(c.remoteID, true, cmd, charsetName); - c.successCounter = c.failedCounter = 0; - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent) { - throw c.getReasonClosed(); - } - - tm.sendMessage(sm.getPayload()); - } - - log.debug("Executing command (channel " + c.localID + ", '" + cmd + "')"); - - try { - waitForChannelSuccessOrFailure(c); - } - catch (IOException e) { - throw new IOException("The execute request failed.", e); - } - } - - public void requestShell(Channel c) throws IOException { - PacketSessionStartShell sm; - - synchronized (c) { - if (c.state != Channel.STATE_OPEN) { - throw c.getReasonClosed(); - } - - sm = new PacketSessionStartShell(c.remoteID, true); - c.successCounter = c.failedCounter = 0; - } - - synchronized (c.channelSendLock) { - if (c.closeMessageSent) { - throw c.getReasonClosed(); - } - - tm.sendMessage(sm.getPayload()); - } - - try { - waitForChannelSuccessOrFailure(c); - } - catch (IOException e) { - throw new IOException("The shell request failed.", e); - } - } - - public void msgChannelExtendedData(byte[] msg) throws IOException { - if (msg.length <= 13) { - throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong size (%d)", msg.length)); - } - - int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - int dataType = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); - int len = ((msg[9] & 0xff) << 24) | ((msg[10] & 0xff) << 16) | ((msg[11] & 0xff) << 8) | (msg[12] & 0xff); - Channel c = getChannel(id); - - if (c == null) { - throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_EXTENDED_DATA message for non-existent channel " + id); - } - - if (dataType != Packets.SSH_EXTENDED_DATA_STDERR) { - throw new PacketFormatException("SSH_MSG_CHANNEL_EXTENDED_DATA message has unknown type (" + dataType + ")"); - } - - if (len != (msg.length - 13)) { - throw new PacketFormatException("SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong len (calculated " + (msg.length - 13) - + ", got " + len + ")"); - } - - log.debug("Got SSH_MSG_CHANNEL_EXTENDED_DATA (channel " + id + ", " + len + ")"); - - synchronized (c) { - if (c.state == Channel.STATE_CLOSED) { - return; // ignore - } - - if (c.state != Channel.STATE_OPEN) { - throw new PacketTypeException("Got SSH_MSG_CHANNEL_EXTENDED_DATA, but channel is not in correct state (" - + c.state + ")"); - } - - if (c.localWindow < len) { - throw new PacketFormatException("Remote sent too much data, does not fit into window."); - } - - c.localWindow -= len; - System.arraycopy(msg, 13, c.stderrBuffer, c.stderrWritepos, len); - c.stderrWritepos += len; - c.notifyAll(); - } - } - - /** - * Wait until for a condition. - * - * @param c Channel - * @param timeout in ms, 0 means no timeout. - * @param condition_mask minimum event mask (at least one of the conditions must be fulfilled) - * @return all current events - */ - public int waitForCondition(Channel c, long timeout, int condition_mask) throws IOException { - long end_time = 0; - boolean end_time_set = false; - - synchronized (c) { - while (true) { - int current_cond = 0; - int stdoutAvail = c.stdoutWritepos - c.stdoutReadpos; - int stderrAvail = c.stderrWritepos - c.stderrReadpos; - - if (stdoutAvail > 0) { - current_cond = current_cond | ChannelCondition.STDOUT_DATA; - } - - if (stderrAvail > 0) { - current_cond = current_cond | ChannelCondition.STDERR_DATA; - } - - if (c.EOF) { - current_cond = current_cond | ChannelCondition.EOF; - } - - if (c.getExitStatus() != null) { - current_cond = current_cond | ChannelCondition.EXIT_STATUS; - } - - if (c.getExitSignal() != null) { - current_cond = current_cond | ChannelCondition.EXIT_SIGNAL; - } - - if (c.state == Channel.STATE_CLOSED) { - return current_cond | ChannelCondition.CLOSED | ChannelCondition.EOF; - } - - if ((current_cond & condition_mask) != 0) { - return current_cond; - } - - if (timeout > 0) { - if (!end_time_set) { - end_time = System.currentTimeMillis() + timeout; - end_time_set = true; - } - else { - timeout = end_time - System.currentTimeMillis(); - - if (timeout <= 0) { - return current_cond | ChannelCondition.TIMEOUT; - } - } - } - - try { - if (timeout > 0) { - c.wait(timeout); - } - else { - c.wait(); - } - } - catch (InterruptedException e) { - throw new InterruptedIOException(e.getMessage()); - } - } - } - } - - public int getAvailable(Channel c, boolean extended) throws IOException { - synchronized (c) { - int avail; - - if (extended) { - avail = c.stderrWritepos - c.stderrReadpos; - } - else { - avail = c.stdoutWritepos - c.stdoutReadpos; - } - - return ((avail > 0) ? avail : (c.EOF ? -1 : 0)); - } - } - - public int getChannelData(Channel c, boolean extended, byte[] target, int off, int len) throws IOException { - int copylen = 0; - int increment = 0; - int remoteID = 0; - int localID = 0; - - synchronized (c) { - int stdoutAvail = 0; - int stderrAvail = 0; - - while (true) { - /* - * Data available? We have to return remaining data even if the - * channel is already closed. - */ - stdoutAvail = c.stdoutWritepos - c.stdoutReadpos; - stderrAvail = c.stderrWritepos - c.stderrReadpos; - - if ((!extended) && (stdoutAvail != 0)) { - break; - } - - if ((extended) && (stderrAvail != 0)) { - break; - } - - /* Do not wait if more data will never arrive (EOF or CLOSED) */ - - if ((c.EOF) || (c.state != Channel.STATE_OPEN)) { - return -1; - } - - try { - c.wait(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(e.getMessage()); - } - } - - /* OK, there is some data. Return it. */ - - if (!extended) { - copylen = (stdoutAvail > len) ? len : stdoutAvail; - System.arraycopy(c.stdoutBuffer, c.stdoutReadpos, target, off, copylen); - c.stdoutReadpos += copylen; - - if (c.stdoutReadpos != c.stdoutWritepos) { - System.arraycopy(c.stdoutBuffer, c.stdoutReadpos, c.stdoutBuffer, 0, c.stdoutWritepos - - c.stdoutReadpos); - } - - c.stdoutWritepos -= c.stdoutReadpos; - c.stdoutReadpos = 0; - } - else { - copylen = (stderrAvail > len) ? len : stderrAvail; - System.arraycopy(c.stderrBuffer, c.stderrReadpos, target, off, copylen); - c.stderrReadpos += copylen; - - if (c.stderrReadpos != c.stderrWritepos) { - System.arraycopy(c.stderrBuffer, c.stderrReadpos, c.stderrBuffer, 0, c.stderrWritepos - - c.stderrReadpos); - } - - c.stderrWritepos -= c.stderrReadpos; - c.stderrReadpos = 0; - } - - if (c.state != Channel.STATE_OPEN) { - return copylen; - } - - if (c.localWindow < ((Channel.CHANNEL_BUFFER_SIZE + 1) / 2)) { - int minFreeSpace = Math.min(Channel.CHANNEL_BUFFER_SIZE - c.stdoutWritepos, - Channel.CHANNEL_BUFFER_SIZE - c.stderrWritepos); - increment = minFreeSpace - c.localWindow; - c.localWindow = minFreeSpace; - } - - remoteID = c.remoteID; /* read while holding the lock */ - localID = c.localID; /* read while holding the lock */ - } - - /* - * If a consumer reads stdout and stdin in parallel, we may end up with - * sending two msgWindowAdjust messages. Luckily, it - * does not matter in which order they arrive at the server. - */ - - if (increment > 0) { - log.debug("Sending SSH_MSG_CHANNEL_WINDOW_ADJUST (channel " + localID + ", " + increment + ")"); - - synchronized (c.channelSendLock) { - byte[] msg = c.msgWindowAdjust; - msg[0] = Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST; - msg[1] = (byte)(remoteID >> 24); - msg[2] = (byte)(remoteID >> 16); - msg[3] = (byte)(remoteID >> 8); - msg[4] = (byte)(remoteID); - msg[5] = (byte)(increment >> 24); - msg[6] = (byte)(increment >> 16); - msg[7] = (byte)(increment >> 8); - msg[8] = (byte)(increment); - - if (!c.closeMessageSent) { - tm.sendMessage(msg); - } - } - } - - return copylen; - } - - public void msgChannelData(byte[] msg) throws IOException { - if (msg.length <= 9) { - throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_DATA message has wrong size (%d)", msg.length)); - } - - int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - int len = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); - Channel c = getChannel(id); - - if (c == null) { - throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_DATA message for non-existent channel " + id); - } - - if (len != (msg.length - 9)) { - throw new PacketFormatException("SSH_MSG_CHANNEL_DATA message has wrong len (calculated " + (msg.length - 9) + ", got " - + len + ")"); - } - - log.debug("Got SSH_MSG_CHANNEL_DATA (channel " + id + ", " + len + ")"); - - synchronized (c) { - if (c.state == Channel.STATE_CLOSED) { - return; // ignore - } - - if (c.state != Channel.STATE_OPEN) { - throw new PacketTypeException("Got SSH_MSG_CHANNEL_DATA, but channel is not in correct state (" + c.state + ")"); - } - - if (c.localWindow < len) { - throw new IOException("Remote sent too much data, does not fit into window."); - } - - c.localWindow -= len; - System.arraycopy(msg, 9, c.stdoutBuffer, c.stdoutWritepos, len); - c.stdoutWritepos += len; - c.notifyAll(); - } - } - - public void msgChannelWindowAdjust(byte[] msg) throws IOException { - if (msg.length != 9) { - throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_WINDOW_ADJUST message has wrong size (%d)", msg.length)); - } - - int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - int windowChange = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); - Channel c = getChannel(id); - - if (c == null) { - throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_WINDOW_ADJUST message for non-existent channel " + id); - } - - synchronized (c) { - final long huge = 0xFFFFffffL; /* 2^32 - 1 */ - c.remoteWindow += (windowChange & huge); /* avoid sign extension */ - - /* TODO - is this a good heuristic? */ - - if ((c.remoteWindow > huge)) { - c.remoteWindow = huge; - } - - c.notifyAll(); - } - - log.debug("Got SSH_MSG_CHANNEL_WINDOW_ADJUST (channel " + id + ", " + windowChange + ")"); - } - - public void msgChannelOpen(byte[] msg) throws IOException { - TypesReader tr = new TypesReader(msg); - tr.readByte(); // skip packet type - String channelType = tr.readString(); - int remoteID = tr.readUINT32(); /* sender channel */ - int remoteWindow = tr.readUINT32(); /* initial window size */ - int remoteMaxPacketSize = tr.readUINT32(); /* maximum packet size */ - - if ("x11".equals(channelType)) { - synchronized (x11_magic_cookies) { - /* If we did not request X11 forwarding, then simply ignore this bogus request. */ - if (x11_magic_cookies.size() == 0) { - PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, - Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "X11 forwarding not activated", ""); - tm.sendAsynchronousMessage(pcof.getPayload()); - log.warning("Unexpected X11 request, denying it!"); - return; - } - } - - String remoteOriginatorAddress = tr.readString(); - int remoteOriginatorPort = tr.readUINT32(); - Channel c = new Channel(this); - - synchronized (c) { - c.remoteID = remoteID; - c.remoteWindow = remoteWindow & 0xFFFFffffL; /* properly convert UINT32 to long */ - c.remoteMaxPacketSize = remoteMaxPacketSize; - c.localID = addChannel(c); - } - - /* - * The open confirmation message will be sent from another thread - */ - RemoteX11AcceptThread rxat = new RemoteX11AcceptThread(c, remoteOriginatorAddress, remoteOriginatorPort); - rxat.setDaemon(true); - rxat.start(); - return; - } - - if ("forwarded-tcpip".equals(channelType)) { - String remoteConnectedAddress = tr.readString(); /* address that was connected */ - int remoteConnectedPort = tr.readUINT32(); /* port that was connected */ - String remoteOriginatorAddress = tr.readString(); /* originator IP address */ - int remoteOriginatorPort = tr.readUINT32(); /* originator port */ - RemoteForwardingData rfd; - - synchronized (remoteForwardings) { - rfd = remoteForwardings.get(remoteConnectedPort); - } - - if (rfd == null) { - PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, - Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, - "No thanks, unknown port in forwarded-tcpip request", ""); - /* Always try to be polite. */ - tm.sendAsynchronousMessage(pcof.getPayload()); - log.debug("Unexpected forwarded-tcpip request, denying it!"); - return; - } - - Channel c = new Channel(this); - - synchronized (c) { - c.remoteID = remoteID; - c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */ - c.remoteMaxPacketSize = remoteMaxPacketSize; - c.localID = addChannel(c); - } - - /* - * The open confirmation message will be sent from another thread. - */ - RemoteAcceptThread rat = new RemoteAcceptThread(c, remoteConnectedAddress, remoteConnectedPort, - remoteOriginatorAddress, remoteOriginatorPort, rfd.targetAddress, rfd.targetPort); - rat.setDaemon(true); - rat.start(); - return; - } - - if ((server_state != null) && ("session".equals(channelType))) { - ServerConnectionCallback cb; - - synchronized (server_state) { - cb = server_state.cb_conn; - } - - if (cb == null) { - tm.sendAsynchronousMessage(new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, - "Sessions are currently not enabled", "en").getPayload()); - return; - } - - final Channel c = new Channel(this); - - synchronized (c) { - c.remoteID = remoteID; - c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */ - c.remoteMaxPacketSize = remoteMaxPacketSize; - c.localID = addChannel(c); - c.state = Channel.STATE_OPEN; - c.ss = new ServerSessionImpl(c); - } - - PacketChannelOpenConfirmation pcoc = new PacketChannelOpenConfirmation(c.remoteID, c.localID, - c.localWindow, c.localMaxPacketSize); - tm.sendAsynchronousMessage(pcoc.getPayload()); - c.ss.sscb = cb.acceptSession(c.ss); - return; - } - - /* Tell the server that we have no idea what it is talking about */ - PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_UNKNOWN_CHANNEL_TYPE, - "Unknown channel type", ""); - tm.sendAsynchronousMessage(pcof.getPayload()); - log.warning("The peer tried to open an unsupported channel type (" + channelType + ")"); - } - - /* Starts the given runnable in a foreground (non-daemon) thread */ - private void runAsync(Runnable r) { - Thread t = new Thread(r); - t.start(); - } - - public void msgChannelRequest(byte[] msg) throws IOException { - TypesReader tr = new TypesReader(msg); - tr.readByte(); // skip packet type - int id = tr.readUINT32(); - Channel c = getChannel(id); - - if (c == null) { - throw new IOException("Unexpected SSH_MSG_CHANNEL_REQUEST message for non-existent channel " + id); - } - - ServerSessionImpl server_session = null; - - if (server_state != null) { - synchronized (c) { - server_session = c.ss; - } - } - - String type = tr.readString("US-ASCII"); - boolean wantReply = tr.readBoolean(); - log.debug("Got SSH_MSG_CHANNEL_REQUEST (channel " + id + ", '" + type + "')"); - - if (type.equals("exit-status")) { - if (wantReply) { - throw new IOException( - "Badly formatted SSH_MSG_CHANNEL_REQUEST exit-status message, 'want reply' is true"); - } - - int exit_status = tr.readUINT32(); - - if (tr.remain() != 0) { - throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); - } - - synchronized (c) { - c.exit_status = exit_status; - c.notifyAll(); - } - - log.debug("Got EXIT STATUS (channel " + id + ", status " + exit_status + ")"); - return; - } - - if ((server_state == null) && (type.equals("exit-signal"))) { - if (wantReply) { - throw new IOException( - "Badly formatted SSH_MSG_CHANNEL_REQUEST exit-signal message, 'want reply' is true"); - } - - String signame = tr.readString("US-ASCII"); - tr.readBoolean(); - tr.readString(); - tr.readString(); - - if (tr.remain() != 0) { - throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); - } - - synchronized (c) { - c.exit_signal = signame; - c.notifyAll(); - } - - log.debug("Got EXIT SIGNAL (channel " + id + ", signal " + signame + ")"); - return; - } - - if ((server_session != null) && (type.equals("pty-req"))) { - PtySettings pty = new PtySettings(); - pty.term = tr.readString(); - pty.term_width_characters = tr.readUINT32(); - pty.term_height_characters = tr.readUINT32(); - pty.term_width_pixels = tr.readUINT32(); - pty.term_height_pixels = tr.readUINT32(); - pty.terminal_modes = tr.readByteString(); - - if (tr.remain() != 0) { - throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); - } - - Runnable run_after_sending_success = null; - ServerSessionCallback sscb = server_session.getServerSessionCallback(); - - if (sscb != null) { - run_after_sending_success = sscb.requestPtyReq(server_session, pty); - } - - if (wantReply) { - if (run_after_sending_success != null) { - tm.sendAsynchronousMessage(new PacketChannelSuccess(c.remoteID).getPayload()); - } - else { - tm.sendAsynchronousMessage(new PacketChannelFailure(c.remoteID).getPayload()); - } - } - - if (run_after_sending_success != null) { - runAsync(run_after_sending_success); - } - - return; - } - - if ((server_session != null) && (type.equals("shell"))) { - if (tr.remain() != 0) { - throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); - } - - Runnable run_after_sending_success = null; - ServerSessionCallback sscb = server_session.getServerSessionCallback(); - - if (sscb != null) { - run_after_sending_success = sscb.requestShell(server_session); - } - - if (wantReply) { - if (run_after_sending_success != null) { - tm.sendAsynchronousMessage(new PacketChannelSuccess(c.remoteID).getPayload()); - } - else { - tm.sendAsynchronousMessage(new PacketChannelFailure(c.remoteID).getPayload()); - } - } - - if (run_after_sending_success != null) { - runAsync(run_after_sending_success); - } - - return; - } - - if ((server_session != null) && (type.equals("exec"))) { - String command = tr.readString(); - - if (tr.remain() != 0) { - throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); - } - - Runnable run_after_sending_success = null; - ServerSessionCallback sscb = server_session.getServerSessionCallback(); - - if (sscb != null) { - run_after_sending_success = sscb.requestExec(server_session, command); - } - - if (wantReply) { - if (run_after_sending_success != null) { - tm.sendAsynchronousMessage(new PacketChannelSuccess(c.remoteID).getPayload()); - } - else { - tm.sendAsynchronousMessage(new PacketChannelFailure(c.remoteID).getPayload()); - } - } - - if (run_after_sending_success != null) { - runAsync(run_after_sending_success); - } - - return; - } - - /* We simply ignore unknown channel requests, however, if the server wants a reply, - * then we signal that we have no idea what it is about. - */ - - if (wantReply) { - tm.sendAsynchronousMessage(new PacketChannelFailure(c.remoteID).getPayload()); - } - - log.debug("Channel request '" + type + "' is not known, ignoring it"); - } - - public void msgChannelEOF(byte[] msg) throws IOException { - if (msg.length != 5) { - throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_EOF message has wrong size (%d)", msg.length)); - } - - int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - Channel c = getChannel(id); - - if (c == null) { - throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_EOF message for non-existent channel " + id); - } - - synchronized (c) { - c.EOF = true; - c.notifyAll(); - } - - log.debug("Got SSH_MSG_CHANNEL_EOF (channel " + id + ")"); - } - - public void msgChannelClose(byte[] msg) throws IOException { - if (msg.length != 5) { - throw new PacketFormatException("SSH_MSG_CHANNEL_CLOSE message has wrong size (" + msg.length + ")"); - } - - int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - Channel c = getChannel(id); - - if (c == null) { - throw new IOException("Unexpected SSH_MSG_CHANNEL_CLOSE message for non-existent channel " + id); - } - - synchronized (c) { - c.EOF = true; - c.state = Channel.STATE_CLOSED; - c.setReasonClosed(new ChannelClosedException("Close requested by remote")); - c.closeMessageRecv = true; - removeChannel(c.localID); - c.notifyAll(); - } - - log.debug("Got SSH_MSG_CHANNEL_CLOSE (channel " + id + ")"); - } - - public void msgChannelSuccess(byte[] msg) throws IOException { - if (msg.length != 5) { - throw new PacketFormatException("SSH_MSG_CHANNEL_SUCCESS message has wrong size (" + msg.length + ")"); - } - - int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - Channel c = getChannel(id); - - if (c == null) { - throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_SUCCESS message for non-existent channel " + id); - } - - synchronized (c) { - c.successCounter++; - c.notifyAll(); - } - - log.debug("Got SSH_MSG_CHANNEL_SUCCESS (channel " + id + ")"); - } - - public void msgChannelFailure(byte[] msg) throws IOException { - if (msg.length != 5) { - throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_FAILURE message has wrong size (%d)", msg.length)); - } - - int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - Channel c = getChannel(id); - - if (c == null) { - throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_FAILURE message for non-existent channel " + id); - } - - synchronized (c) { - c.failedCounter++; - c.notifyAll(); - } - - log.debug("Got SSH_MSG_CHANNEL_FAILURE (channel " + id + ")"); - } - - public void msgChannelOpenConfirmation(byte[] msg) throws IOException { - PacketChannelOpenConfirmation sm = new PacketChannelOpenConfirmation(msg); - Channel c = getChannel(sm.getRecipientChannelID()); - - if (c == null) { - throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for non-existent channel " - + sm.getRecipientChannelID()); - } - - synchronized (c) { - if (c.state != Channel.STATE_OPENING) { - throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for channel " - + sm.getRecipientChannelID()); - } - - c.remoteID = sm.getSenderChannelID(); - c.remoteWindow = sm.getInitialWindowSize() & 0xFFFFffffL; /* convert UINT32 to long */ - c.remoteMaxPacketSize = sm.getMaxPacketSize(); - c.state = Channel.STATE_OPEN; - c.notifyAll(); - } - - log.debug("Got SSH_MSG_CHANNEL_OPEN_CONFIRMATION (channel " + sm.getRecipientChannelID() + " / remote: " - + sm.getSenderChannelID() + ")"); - } - - public void msgChannelOpenFailure(byte[] msg) throws IOException { - if (msg.length < 5) { - throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_OPEN_FAILURE message has wrong size (%d)", msg.length)); - } - - TypesReader tr = new TypesReader(msg); - tr.readByte(); // skip packet type - int id = tr.readUINT32(); /* sender channel */ - Channel c = getChannel(id); - - if (c == null) { - throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE message for non-existent channel " + id); - } - - int reasonCode = tr.readUINT32(); - String description = tr.readString("UTF-8"); - String reasonCodeSymbolicName; - - switch (reasonCode) { - case 1: - reasonCodeSymbolicName = "SSH_OPEN_ADMINISTRATIVELY_PROHIBITED"; - break; - - case 2: - reasonCodeSymbolicName = "SSH_OPEN_CONNECT_FAILED"; - break; - - case 3: - reasonCodeSymbolicName = "SSH_OPEN_UNKNOWN_CHANNEL_TYPE"; - break; - - case 4: - reasonCodeSymbolicName = "SSH_OPEN_RESOURCE_SHORTAGE"; - break; - - default: - reasonCodeSymbolicName = "UNKNOWN REASON CODE (" + reasonCode + ")"; - } - - StringBuilder descriptionBuffer = new StringBuilder(); - descriptionBuffer.append(description); - - for (int i = 0; i < descriptionBuffer.length(); i++) { - char cc = descriptionBuffer.charAt(i); - - if ((cc >= 32) && (cc <= 126)) { - continue; - } - - descriptionBuffer.setCharAt(i, '\uFFFD'); - } - - synchronized (c) { - c.EOF = true; - c.state = Channel.STATE_CLOSED; - c.setReasonClosed(new ChannelClosedException(String.format("The server refused to open the channel (%s, '%s')", - reasonCodeSymbolicName, descriptionBuffer.toString()))); - c.notifyAll(); - } - - log.debug("Got SSH_MSG_CHANNEL_OPEN_FAILURE (channel " + id + ")"); - } - - public void msgGlobalRequest(byte[] msg) throws IOException { - /* Currently we do not support any kind of global request */ - TypesReader tr = new TypesReader(msg); - tr.readByte(); // skip packet type - String requestName = tr.readString(); - boolean wantReply = tr.readBoolean(); - - if (wantReply) { - byte[] reply_failure = new byte[1]; - reply_failure[0] = Packets.SSH_MSG_REQUEST_FAILURE; - tm.sendAsynchronousMessage(reply_failure); - } - - /* We do not clean up the requestName String - that is OK for debug */ - log.debug("Got SSH_MSG_GLOBAL_REQUEST (" + requestName + ")"); - } - - public void msgGlobalSuccess() throws IOException { - synchronized (channels) { - globalSuccessCounter++; - channels.notifyAll(); - } - - log.debug("Got SSH_MSG_REQUEST_SUCCESS"); - } - - public void msgGlobalFailure() throws IOException { - synchronized (channels) { - globalFailedCounter++; - channels.notifyAll(); - } - - log.debug("Got SSH_MSG_REQUEST_FAILURE"); - } - - public void handleFailure(final IOException failure) { - log.debug("HandleMessage: got shutdown"); - - synchronized (listenerThreads) { - for (IChannelWorkerThread lat : listenerThreads) { - lat.stopWorking(); - } - - listenerThreadsAllowed = false; - } - - synchronized (channels) { - shutdown = true; - - for (Channel c : channels) { - synchronized (c) { - c.EOF = true; - c.state = Channel.STATE_CLOSED; - c.setReasonClosed(failure); - c.closeMessageRecv = true; - c.notifyAll(); - } - } - - channels.clear(); - channels.notifyAll(); /* Notify global response waiters */ - } - } - - public void handleMessage(byte[] msg) throws IOException { - switch (msg[0]) { - case Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: - msgChannelOpenConfirmation(msg); - break; - - case Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST: - msgChannelWindowAdjust(msg); - break; - - case Packets.SSH_MSG_CHANNEL_DATA: - msgChannelData(msg); - break; - - case Packets.SSH_MSG_CHANNEL_EXTENDED_DATA: - msgChannelExtendedData(msg); - break; - - case Packets.SSH_MSG_CHANNEL_REQUEST: - msgChannelRequest(msg); - break; - - case Packets.SSH_MSG_CHANNEL_EOF: - msgChannelEOF(msg); - break; - - case Packets.SSH_MSG_CHANNEL_OPEN: - msgChannelOpen(msg); - break; - - case Packets.SSH_MSG_CHANNEL_CLOSE: - msgChannelClose(msg); - break; - - case Packets.SSH_MSG_CHANNEL_SUCCESS: - msgChannelSuccess(msg); - break; - - case Packets.SSH_MSG_CHANNEL_FAILURE: - msgChannelFailure(msg); - break; - - case Packets.SSH_MSG_CHANNEL_OPEN_FAILURE: - msgChannelOpenFailure(msg); - break; - - case Packets.SSH_MSG_GLOBAL_REQUEST: - msgGlobalRequest(msg); - break; - - case Packets.SSH_MSG_REQUEST_SUCCESS: - msgGlobalSuccess(); - break; - - case Packets.SSH_MSG_REQUEST_FAILURE: - msgGlobalFailure(); - break; - - default: - throw new PacketTypeException(msg[0]); - } - } -}
--- a/src/ch/ethz/ssh2/channel/ChannelOutputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * ChannelOutputStream. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class ChannelOutputStream extends OutputStream { - Channel c; - - boolean isClosed = false; - - ChannelOutputStream(Channel c) { - this.c = c; - } - - @Override - public void write(int b) throws IOException { - byte[] buff = new byte[1]; - buff[0] = (byte) b; - write(buff, 0, 1); - } - - @Override - public void close() throws IOException { - if (isClosed == false) { - isClosed = true; - c.cm.sendEOF(c); - } - } - - @Override - public void flush() throws IOException { - if (isClosed) - throw new IOException("This OutputStream is closed."); - - /* This is a no-op, since this stream is unbuffered */ - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - if (isClosed) - throw new IOException("This OutputStream is closed."); - - if (b == null) - throw new NullPointerException(); - - if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) - throw new IndexOutOfBoundsException(); - - if (len == 0) - return; - - c.cm.sendData(c, b, off, len); - } - - @Override - public void write(byte[] b) throws IOException { - write(b, 0, b.length); - } -}
--- a/src/ch/ethz/ssh2/channel/DynamicAcceptThread.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,295 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; -import java.io.OutputStream; -import java.io.PushbackInputStream; -import java.net.ConnectException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.NoRouteToHostException; -import java.net.ServerSocket; -import java.net.Socket; - -import net.sourceforge.jsocks.CProxy; -import net.sourceforge.jsocks.ProxyMessage; -import net.sourceforge.jsocks.Socks4Message; -import net.sourceforge.jsocks.Socks5Message; -import net.sourceforge.jsocks.SocksException; -import net.sourceforge.jsocks.server.ServerAuthenticator; -import net.sourceforge.jsocks.server.ServerAuthenticatorNone; - -/** - * DynamicAcceptThread. - * - * @author Kenny Root - * @version $Id$ - */ -public class DynamicAcceptThread extends Thread implements IChannelWorkerThread { - private ChannelManager cm; - private ServerSocket ss; - - class DynamicAcceptRunnable implements Runnable { - private static final int idleTimeout = 180000; //3 minutes - - private ServerAuthenticator auth; - private Socket sock; - private InputStream in; - private OutputStream out; - private ProxyMessage msg; - - public DynamicAcceptRunnable(ServerAuthenticator auth, Socket sock) { - this.auth = auth; - this.sock = sock; - setName("DynamicAcceptRunnable"); - } - - public void run() { - try { - startSession(); - } - catch (IOException ioe) { - int error_code = CProxy.SOCKS_FAILURE; - - if (ioe instanceof SocksException) - error_code = ((SocksException) ioe).errCode; - else if (ioe instanceof NoRouteToHostException) - error_code = CProxy.SOCKS_HOST_UNREACHABLE; - else if (ioe instanceof ConnectException) - error_code = CProxy.SOCKS_CONNECTION_REFUSED; - else if (ioe instanceof InterruptedIOException) - error_code = CProxy.SOCKS_TTL_EXPIRE; - - if (error_code > CProxy.SOCKS_ADDR_NOT_SUPPORTED - || error_code < 0) { - error_code = CProxy.SOCKS_FAILURE; - } - - sendErrorMessage(error_code); - } - finally { - if (auth != null) - auth.endSession(); - } - } - - private ProxyMessage readMsg(InputStream in) throws IOException { - PushbackInputStream push_in; - - if (in instanceof PushbackInputStream) - push_in = (PushbackInputStream) in; - else - push_in = new PushbackInputStream(in); - - int version = push_in.read(); - push_in.unread(version); - ProxyMessage msg; - - if (version == 5) { - msg = new Socks5Message(push_in, false); - } - else if (version == 4) { - msg = new Socks4Message(push_in, false); - } - else { - throw new SocksException(CProxy.SOCKS_FAILURE); - } - - return msg; - } - - private void sendErrorMessage(int error_code) { - ProxyMessage err_msg; - - if (msg instanceof Socks4Message) - err_msg = new Socks4Message(Socks4Message.REPLY_REJECTED); - else - err_msg = new Socks5Message(error_code); - - try { - err_msg.write(out); - } - catch (IOException ioe) { - } - } - - private void handleRequest(ProxyMessage msg) throws IOException { - if (!auth.checkRequest(msg)) - throw new SocksException(CProxy.SOCKS_FAILURE); - - switch (msg.command) { - case CProxy.SOCKS_CMD_CONNECT: - onConnect(msg); - break; - - default: - throw new SocksException(CProxy.SOCKS_CMD_NOT_SUPPORTED); - } - } - - private void startSession() throws IOException { - sock.setSoTimeout(idleTimeout); - - try { - auth = auth.startSession(sock); - } - catch (IOException ioe) { - System.out.println("Could not start SOCKS session"); - ioe.printStackTrace(); - auth = null; - return; - } - - if (auth == null) { // Authentication failed - System.out.println("SOCKS auth failed"); - return; - } - - in = auth.getInputStream(); - out = auth.getOutputStream(); - msg = readMsg(in); - handleRequest(msg); - } - - private void onConnect(ProxyMessage msg) throws IOException { - ProxyMessage response = null; - Channel cn = null; - StreamForwarder r2l = null; - StreamForwarder l2r = null; - - if (msg instanceof Socks5Message) { - response = new Socks5Message(CProxy.SOCKS_SUCCESS, (InetAddress)null, 0); - } - else { - response = new Socks4Message(Socks4Message.REPLY_OK, (InetAddress)null, 0); - } - - response.write(out); - String destHost = msg.host; - - if (msg.ip != null) - destHost = msg.ip.getHostAddress(); - - try { - /* - * This may fail, e.g., if the remote port is closed (in - * optimistic terms: not open yet) - */ - cn = cm.openDirectTCPIPChannel(destHost, msg.port, - "127.0.0.1", 0); - } - catch (IOException e) { - /* - * Simply close the local socket and wait for the next incoming - * connection - */ - try { - sock.close(); - } - catch (IOException ignore) { - } - - return; - } - - try { - r2l = new StreamForwarder(cn, null, sock, cn.stdoutStream, out, "RemoteToLocal"); - l2r = new StreamForwarder(cn, r2l, sock, in, cn.stdinStream, "LocalToRemote"); - } - catch (IOException e) { - try { - /* - * This message is only visible during debugging, since we - * discard the channel immediatelly - */ - cn.cm.closeChannel(cn, - "Weird error during creation of StreamForwarder (" - + e.getMessage() + ")", true); - } - catch (IOException ignore) { - } - - return; - } - - r2l.setDaemon(true); - l2r.setDaemon(true); - r2l.start(); - l2r.start(); - } - } - - public DynamicAcceptThread(ChannelManager cm, int local_port) - throws IOException { - this.cm = cm; - setName("DynamicAcceptThread"); - ss = new ServerSocket(local_port); - } - - public DynamicAcceptThread(ChannelManager cm, InetSocketAddress localAddress) - throws IOException { - this.cm = cm; - ss = new ServerSocket(); - ss.bind(localAddress); - } - - @Override - public void run() { - try { - cm.registerThread(this); - } - catch (IOException e) { - stopWorking(); - return; - } - - while (true) { - Socket sock = null; - - try { - sock = ss.accept(); - } - catch (IOException e) { - stopWorking(); - return; - } - - DynamicAcceptRunnable dar = new DynamicAcceptRunnable(new ServerAuthenticatorNone(), sock); - Thread t = new Thread(dar); - t.setDaemon(true); - t.start(); - } - } - - /* - * (non-Javadoc) - * - * @see ch.ethz.ssh2.channel.IChannelWorkerThread#stopWorking() - */ - public void stopWorking() { - try { - /* This will lead to an IOException in the ss.accept() call */ - ss.close(); - } - catch (IOException e) { - } - } -}
--- a/src/ch/ethz/ssh2/channel/IChannelWorkerThread.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -/** - * IChannelWorkerThread. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -interface IChannelWorkerThread { - public void stopWorking(); -}
--- a/src/ch/ethz/ssh2/channel/LocalAcceptThread.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; - -/** - * LocalAcceptThread. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class LocalAcceptThread extends Thread implements IChannelWorkerThread { - ChannelManager cm; - String host_to_connect; - int port_to_connect; - - final ServerSocket ss; - - public LocalAcceptThread(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) - throws IOException { - this.cm = cm; - this.host_to_connect = host_to_connect; - this.port_to_connect = port_to_connect; - ss = new ServerSocket(local_port); - } - - public LocalAcceptThread(ChannelManager cm, InetSocketAddress localAddress, String host_to_connect, - int port_to_connect) throws IOException { - this.cm = cm; - this.host_to_connect = host_to_connect; - this.port_to_connect = port_to_connect; - ss = new ServerSocket(); - ss.bind(localAddress); - } - - public ServerSocket getServerSocket() { - return ss; - } - - @Override - public void run() { - try { - cm.registerThread(this); - } - catch (IOException e) { - stopWorking(); - return; - } - - while (true) { - Socket s = null; - - try { - s = ss.accept(); - } - catch (IOException e) { - stopWorking(); - return; - } - - Channel cn = null; - StreamForwarder r2l = null; - StreamForwarder l2r = null; - - try { - /* This may fail, e.g., if the remote port is closed (in optimistic terms: not open yet) */ - cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, s.getInetAddress().getHostAddress(), s - .getPort()); - } - catch (IOException e) { - /* Simply close the local socket and wait for the next incoming connection */ - try { - s.close(); - } - catch (IOException ignore) { - } - - continue; - } - - try { - r2l = new StreamForwarder(cn, null, null, cn.stdoutStream, s.getOutputStream(), "RemoteToLocal"); - l2r = new StreamForwarder(cn, r2l, s, s.getInputStream(), cn.stdinStream, "LocalToRemote"); - } - catch (IOException e) { - try { - /* This message is only visible during debugging, since we discard the channel immediatelly */ - cn.cm.closeChannel(cn, e, true); - } - catch (IOException ignore) { - } - - continue; - } - - r2l.setDaemon(true); - l2r.setDaemon(true); - r2l.start(); - l2r.start(); - } - } - - public void stopWorking() { - try { - /* This will lead to an IOException in the ss.accept() call */ - ss.close(); - } - catch (IOException ignored) { - } - } -}
--- a/src/ch/ethz/ssh2/channel/RemoteAcceptThread.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.net.Socket; - -import ch.ethz.ssh2.log.Logger; - -/** - * RemoteAcceptThread. - * - * @author Christian Plattner - * @version $Id: RemoteAcceptThread.java 119 2014-04-12 20:30:58Z dkocher@sudo.ch $ - */ -public class RemoteAcceptThread extends Thread { - private static final Logger log = Logger.getLogger(RemoteAcceptThread.class); - - Channel c; - - String remoteConnectedAddress; - int remoteConnectedPort; - String remoteOriginatorAddress; - int remoteOriginatorPort; - String targetAddress; - int targetPort; - - Socket s; - - public RemoteAcceptThread(Channel c, String remoteConnectedAddress, int remoteConnectedPort, - String remoteOriginatorAddress, int remoteOriginatorPort, String targetAddress, int targetPort) { - this.c = c; - this.remoteConnectedAddress = remoteConnectedAddress; - this.remoteConnectedPort = remoteConnectedPort; - this.remoteOriginatorAddress = remoteOriginatorAddress; - this.remoteOriginatorPort = remoteOriginatorPort; - this.targetAddress = targetAddress; - this.targetPort = targetPort; - log.debug("RemoteAcceptThread: " + remoteConnectedAddress + "/" + remoteConnectedPort + ", R: " - + remoteOriginatorAddress + "/" + remoteOriginatorPort); - } - - @Override - public void run() { - try { - c.cm.sendOpenConfirmation(c); - s = new Socket(targetAddress, targetPort); - StreamForwarder r2l = new StreamForwarder(c, null, null, c.getStdoutStream(), s.getOutputStream(), - "RemoteToLocal"); - StreamForwarder l2r = new StreamForwarder(c, null, null, s.getInputStream(), c.getStdinStream(), - "LocalToRemote"); - /* No need to start two threads, one can be executed in the current thread */ - r2l.setDaemon(true); - r2l.start(); - l2r.run(); - - while (r2l.isAlive()) { - try { - r2l.join(); - } - catch (InterruptedException ignored) { - } - } - - /* If the channel is already closed, then this is a no-op */ - c.cm.closeChannel(c, "EOF on both streams reached.", true); - s.close(); - } - catch (IOException e) { - log.warning("IOException in proxy code: " + e.getMessage()); - - try { - c.cm.closeChannel(c, e, true); - } - catch (IOException ignored) { - } - - try { - if (s != null) - s.close(); - } - catch (IOException ignored) { - } - } - } -}
--- a/src/ch/ethz/ssh2/channel/RemoteForwardingData.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -/** - * RemoteForwardingData. Data about a requested remote forwarding. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class RemoteForwardingData { - public String bindAddress; - public int bindPort; - - String targetAddress; - int targetPort; -}
--- a/src/ch/ethz/ssh2/channel/RemoteX11AcceptThread.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; - -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.util.StringEncoder; - -/** - * RemoteX11AcceptThread. - * - * @author Christian Plattner - * @version $Id: RemoteX11AcceptThread.java 119 2014-04-12 20:30:58Z dkocher@sudo.ch $ - */ -public class RemoteX11AcceptThread extends Thread { - private static final Logger log = Logger.getLogger(RemoteX11AcceptThread.class); - - Channel c; - - String remoteOriginatorAddress; - int remoteOriginatorPort; - - Socket s; - - public RemoteX11AcceptThread(Channel c, String remoteOriginatorAddress, int remoteOriginatorPort) { - this.c = c; - this.remoteOriginatorAddress = remoteOriginatorAddress; - this.remoteOriginatorPort = remoteOriginatorPort; - } - - @Override - public void run() { - try { - /* Send Open Confirmation */ - c.cm.sendOpenConfirmation(c); - /* Read startup packet from client */ - OutputStream remote_os = c.getStdinStream(); - InputStream remote_is = c.getStdoutStream(); - /* The following code is based on the protocol description given in: - * Scheifler/Gettys, - * X Windows System: Core and Extension Protocols: - * X Version 11, Releases 6 and 6.1 ISBN 1-55558-148-X - * (from the ETH library - after being here for almost ten - * years one of the few books I borrowed... sad but true =) - */ - /* - * Client startup: - * - * 1 0X42 MSB first/0x6c lSB first - byteorder - * 1 - unused - * 2 card16 - protocol-major-version - * 2 card16 - protocol-minor-version - * 2 n - lenght of authorization-protocol-name - * 2 d - lenght of authorization-protocol-data - * 2 - unused - * string8 - authorization-protocol-name - * p - unused, p=pad(n) - * string8 - authorization-protocol-data - * q - unused, q=pad(d) - * - * pad(X) = (4 - (X mod 4)) mod 4 - * - * Server response: - * - * 1 (0 failed, 2 authenticate, 1 success) - * ... - * - */ - /* Later on we will simply forward the first 6 header bytes to the "real" X11 server */ - byte[] header = new byte[6]; - - if (remote_is.read(header) != 6) - throw new IOException("Unexpected EOF on X11 startup!"); - - if ((header[0] != 0x42) && (header[0] != 0x6c)) // 0x42 MSB first, 0x6C LSB first - throw new IOException("Unknown endian format in X11 message!"); - - /* Yes, I came up with this myself - shall I file an application for a patent? =) */ - int idxMSB = (header[0] == 0x42) ? 0 : 1; - /* Read authorization data header */ - byte[] auth_buff = new byte[6]; - - if (remote_is.read(auth_buff) != 6) - throw new IOException("Unexpected EOF on X11 startup!"); - - int authProtocolNameLength = ((auth_buff[idxMSB] & 0xff) << 8) | (auth_buff[1 - idxMSB] & 0xff); - int authProtocolDataLength = ((auth_buff[2 + idxMSB] & 0xff) << 8) | (auth_buff[3 - idxMSB] & 0xff); - - if ((authProtocolNameLength > 256) || (authProtocolDataLength > 256)) - throw new IOException("Buggy X11 authorization data"); - - int authProtocolNamePadding = ((4 - (authProtocolNameLength % 4)) % 4); - int authProtocolDataPadding = ((4 - (authProtocolDataLength % 4)) % 4); - byte[] authProtocolName = new byte[authProtocolNameLength]; - byte[] authProtocolData = new byte[authProtocolDataLength]; - byte[] paddingBuffer = new byte[4]; - - if (remote_is.read(authProtocolName) != authProtocolNameLength) - throw new IOException("Unexpected EOF on X11 startup! (authProtocolName)"); - - if (remote_is.read(paddingBuffer, 0, authProtocolNamePadding) != authProtocolNamePadding) - throw new IOException("Unexpected EOF on X11 startup! (authProtocolNamePadding)"); - - if (remote_is.read(authProtocolData) != authProtocolDataLength) - throw new IOException("Unexpected EOF on X11 startup! (authProtocolData)"); - - if (remote_is.read(paddingBuffer, 0, authProtocolDataPadding) != authProtocolDataPadding) - throw new IOException("Unexpected EOF on X11 startup! (authProtocolDataPadding)"); - - if ("MIT-MAGIC-COOKIE-1".equals(StringEncoder.GetString(authProtocolName)) == false) - throw new IOException("Unknown X11 authorization protocol!"); - - if (authProtocolDataLength != 16) - throw new IOException("Wrong data length for X11 authorization data!"); - - StringBuilder tmp = new StringBuilder(32); - - for (int i = 0; i < authProtocolData.length; i++) { - String digit2 = Integer.toHexString(authProtocolData[i] & 0xff); - tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2); - } - - String hexEncodedFakeCookie = tmp.toString(); - - /* Order is very important here - it may be that a certain x11 forwarding - * gets disabled right in the moment when we check and register our connection - * */ - - synchronized (c) { - /* Please read the comment in Channel.java */ - c.hexX11FakeCookie = hexEncodedFakeCookie; - } - - /* Now check our fake cookie directory to see if we produced this cookie */ - X11ServerData sd = c.cm.checkX11Cookie(hexEncodedFakeCookie); - - if (sd == null) - throw new IOException("Invalid X11 cookie received."); - - /* If the session which corresponds to this cookie is closed then we will - * detect this: the session's close code will close all channels - * with the session's assigned x11 fake cookie. - */ - s = new Socket(sd.hostname, sd.port); - OutputStream x11_os = s.getOutputStream(); - InputStream x11_is = s.getInputStream(); - /* Now we are sending the startup packet to the real X11 server */ - x11_os.write(header); - - if (sd.x11_magic_cookie == null) { - byte[] emptyAuthData = new byte[6]; - /* empty auth data, hopefully you are connecting to localhost =) */ - x11_os.write(emptyAuthData); - } - else { - if (sd.x11_magic_cookie.length != 16) - throw new IOException("The real X11 cookie has an invalid length!"); - - /* send X11 cookie specified by client */ - x11_os.write(auth_buff); - x11_os.write(authProtocolName); /* re-use */ - x11_os.write(paddingBuffer, 0, authProtocolNamePadding); - x11_os.write(sd.x11_magic_cookie); - x11_os.write(paddingBuffer, 0, authProtocolDataPadding); - } - - x11_os.flush(); - /* Start forwarding traffic */ - StreamForwarder r2l = new StreamForwarder(c, null, null, remote_is, x11_os, "RemoteToX11"); - StreamForwarder l2r = new StreamForwarder(c, null, null, x11_is, remote_os, "X11ToRemote"); - /* No need to start two threads, one can be executed in the current thread */ - r2l.setDaemon(true); - r2l.start(); - l2r.run(); - - while (r2l.isAlive()) { - try { - r2l.join(); - } - catch (InterruptedException ignored) { - } - } - - /* If the channel is already closed, then this is a no-op */ - c.cm.closeChannel(c, "EOF on both X11 streams reached.", true); - s.close(); - } - catch (IOException e) { - log.warning("IOException in X11 proxy code: " + e.getMessage()); - - try { - c.cm.closeChannel(c, e, true); - } - catch (IOException ignored) { - } - - try { - if (s != null) - s.close(); - } - catch (IOException ignored) { - } - } - } -}
--- a/src/ch/ethz/ssh2/channel/ServerSessionImpl.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ - -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import ch.ethz.ssh2.ServerSession; -import ch.ethz.ssh2.ServerSessionCallback; - -public class ServerSessionImpl implements ServerSession { - Channel c; - public ServerSessionCallback sscb; - - public ServerSessionImpl(Channel c) { - this.c = c; - } - - public int getState() { - return c.getState(); - } - - public InputStream getStdout() { - return c.getStdoutStream(); - } - - public InputStream getStderr() { - return c.getStderrStream(); - } - - public OutputStream getStdin() { - return c.getStdinStream(); - } - - public void close() { - try { - c.cm.closeChannel(c, "Closed due to server request", true); - } - catch (IOException ignored) { - } - } - - public synchronized ServerSessionCallback getServerSessionCallback() { - return sscb; - } - - public synchronized void setServerSessionCallback(ServerSessionCallback sscb) { - this.sscb = sscb; - } -}
--- a/src/ch/ethz/ssh2/channel/StreamForwarder.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; - -/** - * A StreamForwarder forwards data between two given streams. - * If two StreamForwarder threads are used (one for each direction) - * then one can be configured to shutdown the underlying channel/socket - * if both threads have finished forwarding (EOF). - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class StreamForwarder extends Thread { - OutputStream os; - InputStream is; - byte[] buffer = new byte[Channel.CHANNEL_BUFFER_SIZE]; - Channel c; - StreamForwarder sibling; - Socket s; - String mode; - - StreamForwarder(Channel c, StreamForwarder sibling, Socket s, InputStream is, OutputStream os, String mode) - throws IOException { - this.is = is; - this.os = os; - this.mode = mode; - this.c = c; - this.sibling = sibling; - this.s = s; - } - - @Override - public void run() { - try { - while (true) { - int len = is.read(buffer); - - if (len <= 0) - break; - - os.write(buffer, 0, len); - os.flush(); - } - } - catch (IOException e) { - try { - c.cm.closeChannel(c, e, true); - } - catch (IOException ignored) { - } - } - finally { - try { - os.close(); - } - catch (IOException ignored) { - } - - try { - is.close(); - } - catch (IOException ignored) { - } - - if (sibling != null) { - while (sibling.isAlive()) { - try { - sibling.join(); - } - catch (InterruptedException ignored) { - } - } - - try { - c.cm.closeChannel(c, "StreamForwarder (" + mode + ") is cleaning up the connection", true); - } - catch (IOException ignored) { - } - - try { - if (s != null) - s.close(); - } - catch (IOException ignored) { - } - } - } - } -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/channel/X11ServerData.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.channel; - -/** - * X11ServerData. Data regarding an x11 forwarding target. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - * - */ -public class X11ServerData { - public String hostname; - public int port; - public byte[] x11_magic_cookie; /* not the remote (fake) one, the local (real) one */ -}
--- a/src/ch/ethz/ssh2/compression/CompressionFactory.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.ethz.ssh2.compression; - -import java.util.Vector; - -/** - * @author Kenny Root - * - */ -public class CompressionFactory { - static class CompressorEntry { - String type; - String compressorClass; - - public CompressorEntry(String type, String compressorClass) { - this.type = type; - this.compressorClass = compressorClass; - } - } - - static Vector<CompressorEntry> compressors = new Vector<CompressorEntry>(); - - static { - /* Higher Priority First */ - compressors.addElement(new CompressorEntry("zlib", "ch.ethz.ssh2.compression.Zlib")); - compressors.addElement(new CompressorEntry("zlib@openssh.com", "ch.ethz.ssh2.compression.ZlibOpenSSH")); - compressors.addElement(new CompressorEntry("none", "")); - } - - public static String[] getDefaultCompressorList() { - String list[] = new String[compressors.size()]; - - for (int i = 0; i < compressors.size(); i++) { - CompressorEntry ce = compressors.elementAt(i); - list[i] = new String(ce.type); - } - - return list; - } - - public static void checkCompressorList(String[] compressorCandidates) { - for (int i = 0; i < compressorCandidates.length; i++) - getEntry(compressorCandidates[i]); - } - - public static Compressor createCompressor(String type) { - try { - CompressorEntry ce = getEntry(type); - - if ("".equals(ce.compressorClass)) - return null; - - Class<?> cc = Class.forName(ce.compressorClass); - Compressor cmp = (Compressor) cc.newInstance(); - return cmp; - } - catch (Exception e) { - throw new IllegalArgumentException("Cannot instantiate " + type); - } - } - - private static CompressorEntry getEntry(String type) { - for (int i = 0; i < compressors.size(); i++) { - CompressorEntry ce = compressors.elementAt(i); - - if (ce.type.equals(type)) - return ce; - } - - throw new IllegalArgumentException("Unkown algorithm " + type); - } -}
--- a/src/ch/ethz/ssh2/compression/Compressor.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.ethz.ssh2.compression; - -/** - * @author Kenny Root - * - */ -public interface Compressor { - int getBufferSize(); - - int compress(byte[] buf, int start, int len, byte[] output); - - byte[] uncompress(byte[] buf, int start, int[] len); - - boolean canCompressPreauth(); -}
--- a/src/ch/ethz/ssh2/compression/Zlib.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.ethz.ssh2.compression; - -import com.jcraft.jzlib.JZlib; -import com.jcraft.jzlib.ZStream; - -/** - * @author Kenny Root - * - */ -public class Zlib implements Compressor { - static private final int DEFAULT_BUF_SIZE = 4096; - static private final int LEVEL = 5; - - private ZStream deflate; - private byte[] deflate_tmpbuf; - - private ZStream inflate; - private byte[] inflate_tmpbuf; - private byte[] inflated_buf; - - public Zlib() { - deflate = new ZStream(); - inflate = new ZStream(); - deflate.deflateInit(LEVEL); - inflate.inflateInit(); - deflate_tmpbuf = new byte[DEFAULT_BUF_SIZE]; - inflate_tmpbuf = new byte[DEFAULT_BUF_SIZE]; - inflated_buf = new byte[DEFAULT_BUF_SIZE]; - } - - public boolean canCompressPreauth() { - return true; - } - - public int getBufferSize() { - return DEFAULT_BUF_SIZE; - } - - public int compress(byte[] buf, int start, int len, byte[] output) { - deflate.next_in = buf; - deflate.next_in_index = start; - deflate.avail_in = len - start; - - if ((buf.length + 1024) > deflate_tmpbuf.length) { - deflate_tmpbuf = new byte[buf.length + 1024]; - } - - deflate.next_out = deflate_tmpbuf; - deflate.next_out_index = 0; - deflate.avail_out = output.length; - - if (deflate.deflate(JZlib.Z_PARTIAL_FLUSH) != JZlib.Z_OK) { - System.err.println("compress: compression failure"); - } - - if (deflate.avail_in > 0) { - System.err.println("compress: deflated data too large"); - } - - int outputlen = output.length - deflate.avail_out; - System.arraycopy(deflate_tmpbuf, 0, output, 0, outputlen); - return outputlen; - } - - public byte[] uncompress(byte[] buffer, int start, int[] length) { - int inflated_end = 0; - inflate.next_in = buffer; - inflate.next_in_index = start; - inflate.avail_in = length[0]; - - while (true) { - inflate.next_out = inflate_tmpbuf; - inflate.next_out_index = 0; - inflate.avail_out = DEFAULT_BUF_SIZE; - int status = inflate.inflate(JZlib.Z_PARTIAL_FLUSH); - - switch (status) { - case JZlib.Z_OK: - if (inflated_buf.length < inflated_end + DEFAULT_BUF_SIZE - - inflate.avail_out) { - byte[] foo = new byte[inflated_end + DEFAULT_BUF_SIZE - - inflate.avail_out]; - System.arraycopy(inflated_buf, 0, foo, 0, inflated_end); - inflated_buf = foo; - } - - System.arraycopy(inflate_tmpbuf, 0, inflated_buf, inflated_end, - DEFAULT_BUF_SIZE - inflate.avail_out); - inflated_end += (DEFAULT_BUF_SIZE - inflate.avail_out); - length[0] = inflated_end; - break; - - case JZlib.Z_BUF_ERROR: - if (inflated_end > buffer.length - start) { - byte[] foo = new byte[inflated_end + start]; - System.arraycopy(buffer, 0, foo, 0, start); - System.arraycopy(inflated_buf, 0, foo, start, inflated_end); - buffer = foo; - } - else { - System.arraycopy(inflated_buf, 0, buffer, start, - inflated_end); - } - - length[0] = inflated_end; - return buffer; - - default: - System.err.println("uncompress: inflate returnd " + status); - return null; - } - } - } -}
--- a/src/ch/ethz/ssh2/compression/ZlibOpenSSH.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.ethz.ssh2.compression; - -/** - * Defines how zlib@openssh.org compression works. - * See - * http://www.openssh.org/txt/draft-miller-secsh-compression-delayed-00.txt - * compression is disabled until userauth has occurred. - * - * @author Matt Johnston - * - */ -public class ZlibOpenSSH extends Zlib { - - public boolean canCompressPreauth() { - return false; - } - -}
--- a/src/ch/ethz/ssh2/crypto/Base64.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto; - -import java.io.CharArrayWriter; -import java.io.IOException; - -/** - * Basic Base64 Support. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class Base64 { - static final char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); - - public static char[] encode(byte[] content) { - CharArrayWriter cw = new CharArrayWriter((4 * content.length) / 3); - int idx = 0; - int x = 0; - - for (int i = 0; i < content.length; i++) { - if (idx == 0) - x = (content[i] & 0xff) << 16; - else if (idx == 1) - x = x | ((content[i] & 0xff) << 8); - else - x = x | (content[i] & 0xff); - - idx++; - - if (idx == 3) { - cw.write(alphabet[x >> 18]); - cw.write(alphabet[(x >> 12) & 0x3f]); - cw.write(alphabet[(x >> 6) & 0x3f]); - cw.write(alphabet[x & 0x3f]); - idx = 0; - } - } - - if (idx == 1) { - cw.write(alphabet[x >> 18]); - cw.write(alphabet[(x >> 12) & 0x3f]); - cw.write('='); - cw.write('='); - } - - if (idx == 2) { - cw.write(alphabet[x >> 18]); - cw.write(alphabet[(x >> 12) & 0x3f]); - cw.write(alphabet[(x >> 6) & 0x3f]); - cw.write('='); - } - - return cw.toCharArray(); - } - - public static byte[] decode(char[] message) throws IOException { - byte buff[] = new byte[4]; - byte dest[] = new byte[message.length]; - int bpos = 0; - int destpos = 0; - - for (int i = 0; i < message.length; i++) { - int c = message[i]; - - if ((c == '\n') || (c == '\r') || (c == ' ') || (c == '\t')) - continue; - - if ((c >= 'A') && (c <= 'Z')) { - buff[bpos++] = (byte)(c - 'A'); - } - else if ((c >= 'a') && (c <= 'z')) { - buff[bpos++] = (byte)((c - 'a') + 26); - } - else if ((c >= '0') && (c <= '9')) { - buff[bpos++] = (byte)((c - '0') + 52); - } - else if (c == '+') { - buff[bpos++] = 62; - } - else if (c == '/') { - buff[bpos++] = 63; - } - else if (c == '=') { - buff[bpos++] = 64; - } - else { - throw new IOException("Illegal char in base64 code."); - } - - if (bpos == 4) { - bpos = 0; - - if (buff[0] == 64) - break; - - if (buff[1] == 64) - throw new IOException("Unexpected '=' in base64 code."); - - if (buff[2] == 64) { - int v = (((buff[0] & 0x3f) << 6) | ((buff[1] & 0x3f))); - dest[destpos++] = (byte)(v >> 4); - break; - } - else if (buff[3] == 64) { - int v = (((buff[0] & 0x3f) << 12) | ((buff[1] & 0x3f) << 6) | ((buff[2] & 0x3f))); - dest[destpos++] = (byte)(v >> 10); - dest[destpos++] = (byte)(v >> 2); - break; - } - else { - int v = (((buff[0] & 0x3f) << 18) | ((buff[1] & 0x3f) << 12) | ((buff[2] & 0x3f) << 6) | ((buff[3] & 0x3f))); - dest[destpos++] = (byte)(v >> 16); - dest[destpos++] = (byte)(v >> 8); - dest[destpos++] = (byte)(v); - } - } - } - - byte[] res = new byte[destpos]; - System.arraycopy(dest, 0, res, 0, destpos); - return res; - } -}
--- a/src/ch/ethz/ssh2/crypto/CryptoWishList.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto; - -import ch.ethz.ssh2.compression.CompressionFactory; -import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; -import ch.ethz.ssh2.crypto.digest.MAC; -import ch.ethz.ssh2.transport.KexManager; - -/** - * CryptoWishList. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class CryptoWishList { - public String[] kexAlgorithms = KexManager.getDefaultClientKexAlgorithmList(); - public String[] serverHostKeyAlgorithms = KexManager.getDefaultServerHostkeyAlgorithmList(); - public String[] c2s_enc_algos = BlockCipherFactory.getDefaultCipherList(); - public String[] s2c_enc_algos = BlockCipherFactory.getDefaultCipherList(); - public String[] c2s_mac_algos = MAC.getMacList(); - public String[] s2c_mac_algos = MAC.getMacList(); - public String[] c2s_comp_algos = CompressionFactory.getDefaultCompressorList(); - public String[] s2c_comp_algos = CompressionFactory.getDefaultCompressorList(); - - public static CryptoWishList forServer() { - CryptoWishList cwl = new CryptoWishList(); - cwl.kexAlgorithms = KexManager.getDefaultServerKexAlgorithmList(); - return cwl; - } -}
--- a/src/ch/ethz/ssh2/crypto/KeyMaterial.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto; - -import java.io.IOException; -import java.math.BigInteger; - -import ch.ethz.ssh2.crypto.digest.HashForSSH2Types; - -/** - * Establishes key material for iv/key/mac (both directions). - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class KeyMaterial { - public byte[] initial_iv_client_to_server; - public byte[] initial_iv_server_to_client; - public byte[] enc_key_client_to_server; - public byte[] enc_key_server_to_client; - public byte[] integrity_key_client_to_server; - public byte[] integrity_key_server_to_client; - - private static byte[] calculateKey(HashForSSH2Types sh, BigInteger K, byte[] H, byte type, byte[] SessionID, - int keyLength) throws IOException { - byte[] res = new byte[keyLength]; - int dglen = sh.getDigestLength(); - int numRounds = (keyLength + dglen - 1) / dglen; - byte[][] tmp = new byte[numRounds][]; - sh.reset(); - sh.updateBigInt(K); - sh.updateBytes(H); - sh.updateByte(type); - sh.updateBytes(SessionID); - tmp[0] = sh.getDigest(); - int off = 0; - int produced = Math.min(dglen, keyLength); - System.arraycopy(tmp[0], 0, res, off, produced); - keyLength -= produced; - off += produced; - - for (int i = 1; i < numRounds; i++) { - sh.updateBigInt(K); - sh.updateBytes(H); - - for (int j = 0; j < i; j++) { - sh.updateBytes(tmp[j]); - } - - tmp[i] = sh.getDigest(); - produced = Math.min(dglen, keyLength); - System.arraycopy(tmp[i], 0, res, off, produced); - keyLength -= produced; - off += produced; - } - - return res; - } - - public static KeyMaterial create(String hashType, byte[] H, BigInteger K, byte[] SessionID, int keyLengthCS, - int blockSizeCS, int macLengthCS, int keyLengthSC, int blockSizeSC, int macLengthSC) - throws IOException { - KeyMaterial km = new KeyMaterial(); - HashForSSH2Types sh = new HashForSSH2Types(hashType); - km.initial_iv_client_to_server = calculateKey(sh, K, H, (byte) 'A', SessionID, blockSizeCS); - km.initial_iv_server_to_client = calculateKey(sh, K, H, (byte) 'B', SessionID, blockSizeSC); - km.enc_key_client_to_server = calculateKey(sh, K, H, (byte) 'C', SessionID, keyLengthCS); - km.enc_key_server_to_client = calculateKey(sh, K, H, (byte) 'D', SessionID, keyLengthSC); - km.integrity_key_client_to_server = calculateKey(sh, K, H, (byte) 'E', SessionID, macLengthCS); - km.integrity_key_server_to_client = calculateKey(sh, K, H, (byte) 'F', SessionID, macLengthSC); - return km; - } -}
--- a/src/ch/ethz/ssh2/crypto/PEMDecoder.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,444 +0,0 @@ - -package ch.ethz.ssh2.crypto; - -import java.io.BufferedReader; -import java.io.CharArrayReader; -import java.io.IOException; -import java.math.BigInteger; -import java.security.DigestException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.spec.DSAPrivateKeySpec; -import java.security.spec.DSAPublicKeySpec; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.ECPrivateKeySpec; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import java.security.spec.RSAPrivateCrtKeySpec; -import java.security.spec.RSAPrivateKeySpec; -import java.security.spec.RSAPublicKeySpec; - -import ch.ethz.ssh2.crypto.cipher.AES; -import ch.ethz.ssh2.crypto.cipher.BlockCipher; -import ch.ethz.ssh2.crypto.cipher.CBCMode; -import ch.ethz.ssh2.crypto.cipher.DES; -import ch.ethz.ssh2.crypto.cipher.DESede; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; - -/** - * PEM Support. - * - * @author Christian Plattner, plattner@trilead.com - * @version $Id: PEMDecoder.java,v 1.2 2008/04/01 12:38:09 cplattne Exp $ - */ -public class PEMDecoder { - public static final int PEM_RSA_PRIVATE_KEY = 1; - public static final int PEM_DSA_PRIVATE_KEY = 2; - public static final int PEM_EC_PRIVATE_KEY = 3; - - private static final int hexToInt(char c) { - if ((c >= 'a') && (c <= 'f')) { - return (c - 'a') + 10; - } - - if ((c >= 'A') && (c <= 'F')) { - return (c - 'A') + 10; - } - - if ((c >= '0') && (c <= '9')) { - return (c - '0'); - } - - throw new IllegalArgumentException("Need hex char"); - } - - private static byte[] hexToByteArray(String hex) { - if (hex == null) - throw new IllegalArgumentException("null argument"); - - if ((hex.length() % 2) != 0) - throw new IllegalArgumentException("Uneven string length in hex encoding."); - - byte decoded[] = new byte[hex.length() / 2]; - - for (int i = 0; i < decoded.length; i++) { - int hi = hexToInt(hex.charAt(i * 2)); - int lo = hexToInt(hex.charAt((i * 2) + 1)); - decoded[i] = (byte)(hi * 16 + lo); - } - - return decoded; - } - - private static byte[] generateKeyFromPasswordSaltWithMD5(byte[] password, byte[] salt, int keyLen) - throws IOException { - if (salt.length < 8) - throw new IllegalArgumentException("Salt needs to be at least 8 bytes for key generation."); - - MessageDigest md5; - - try { - md5 = MessageDigest.getInstance("MD5"); - } - catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("VM does not support MD5", e); - } - - byte[] key = new byte[keyLen]; - byte[] tmp = new byte[md5.getDigestLength()]; - - while (true) { - md5.update(password, 0, password.length); - md5.update(salt, 0, 8); // ARGH we only use the first 8 bytes of the - // salt in this step. - // This took me two hours until I got AES-xxx running. - int copy = (keyLen < tmp.length) ? keyLen : tmp.length; - - try { - md5.digest(tmp, 0, tmp.length); - } - catch (DigestException e) { - IOException ex = new IOException("could not digest password"); - ex.initCause(e); - throw ex; - } - - System.arraycopy(tmp, 0, key, key.length - keyLen, copy); - keyLen -= copy; - - if (keyLen == 0) - return key; - - md5.update(tmp, 0, tmp.length); - } - } - - private static byte[] removePadding(byte[] buff, int blockSize) throws IOException { - /* Removes RFC 1423/PKCS #7 padding */ - int rfc_1423_padding = buff[buff.length - 1] & 0xff; - - if ((rfc_1423_padding < 1) || (rfc_1423_padding > blockSize)) - throw new IOException("Decrypted PEM has wrong padding, did you specify the correct password?"); - - for (int i = 2; i <= rfc_1423_padding; i++) { - if (buff[buff.length - i] != rfc_1423_padding) - throw new IOException("Decrypted PEM has wrong padding, did you specify the correct password?"); - } - - byte[] tmp = new byte[buff.length - rfc_1423_padding]; - System.arraycopy(buff, 0, tmp, 0, buff.length - rfc_1423_padding); - return tmp; - } - - public static final PEMStructure parsePEM(char[] pem) throws IOException { - PEMStructure ps = new PEMStructure(); - String line = null; - BufferedReader br = new BufferedReader(new CharArrayReader(pem)); - String endLine = null; - - while (true) { - line = br.readLine(); - - if (line == null) - throw new IOException("Invalid PEM structure, '-----BEGIN...' missing"); - - line = line.trim(); - - if (line.startsWith("-----BEGIN DSA PRIVATE KEY-----")) { - endLine = "-----END DSA PRIVATE KEY-----"; - ps.pemType = PEM_DSA_PRIVATE_KEY; - break; - } - - if (line.startsWith("-----BEGIN RSA PRIVATE KEY-----")) { - endLine = "-----END RSA PRIVATE KEY-----"; - ps.pemType = PEM_RSA_PRIVATE_KEY; - break; - } - - if (line.startsWith("-----BEGIN EC PRIVATE KEY-----")) { - endLine = "-----END EC PRIVATE KEY-----"; - ps.pemType = PEM_EC_PRIVATE_KEY; - break; - } - } - - while (true) { - line = br.readLine(); - - if (line == null) - throw new IOException("Invalid PEM structure, " + endLine + " missing"); - - line = line.trim(); - int sem_idx = line.indexOf(':'); - - if (sem_idx == -1) - break; - - String name = line.substring(0, sem_idx + 1); - String value = line.substring(sem_idx + 1); - String values[] = value.split(","); - - for (int i = 0; i < values.length; i++) - values[i] = values[i].trim(); - - // Proc-Type: 4,ENCRYPTED - // DEK-Info: DES-EDE3-CBC,579B6BE3E5C60483 - - if ("Proc-Type:".equals(name)) { - ps.procType = values; - continue; - } - - if ("DEK-Info:".equals(name)) { - ps.dekInfo = values; - continue; - } - - /* Ignore line */ - } - - StringBuffer keyData = new StringBuffer(); - - while (true) { - if (line == null) - throw new IOException("Invalid PEM structure, " + endLine + " missing"); - - line = line.trim(); - - if (line.startsWith(endLine)) - break; - - keyData.append(line); - line = br.readLine(); - } - - char[] pem_chars = new char[keyData.length()]; - keyData.getChars(0, pem_chars.length, pem_chars, 0); - ps.data = Base64.decode(pem_chars); - - if (ps.data.length == 0) - throw new IOException("Invalid PEM structure, no data available"); - - return ps; - } - - private static final void decryptPEM(PEMStructure ps, byte[] pw) throws IOException { - if (ps.dekInfo == null) - throw new IOException("Broken PEM, no mode and salt given, but encryption enabled"); - - if (ps.dekInfo.length != 2) - throw new IOException("Broken PEM, DEK-Info is incomplete!"); - - String algo = ps.dekInfo[0]; - byte[] salt = hexToByteArray(ps.dekInfo[1]); - BlockCipher bc = null; - - if (algo.equals("DES-EDE3-CBC")) { - DESede des3 = new DESede(); - des3.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 24)); - bc = new CBCMode(des3, salt, false); - } - else if (algo.equals("DES-CBC")) { - DES des = new DES(); - des.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 8)); - bc = new CBCMode(des, salt, false); - } - else if (algo.equals("AES-128-CBC")) { - AES aes = new AES(); - aes.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 16)); - bc = new CBCMode(aes, salt, false); - } - else if (algo.equals("AES-192-CBC")) { - AES aes = new AES(); - aes.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 24)); - bc = new CBCMode(aes, salt, false); - } - else if (algo.equals("AES-256-CBC")) { - AES aes = new AES(); - aes.init(false, generateKeyFromPasswordSaltWithMD5(pw, salt, 32)); - bc = new CBCMode(aes, salt, false); - } - else { - throw new IOException("Cannot decrypt PEM structure, unknown cipher " + algo); - } - - if ((ps.data.length % bc.getBlockSize()) != 0) - throw new IOException("Invalid PEM structure, size of encrypted block is not a multiple of " - + bc.getBlockSize()); - - /* Now decrypt the content */ - byte[] dz = new byte[ps.data.length]; - - for (int i = 0; i < ps.data.length / bc.getBlockSize(); i++) { - bc.transformBlock(ps.data, i * bc.getBlockSize(), dz, i * bc.getBlockSize()); - } - - /* Now check and remove RFC 1423/PKCS #7 padding */ - dz = removePadding(dz, bc.getBlockSize()); - ps.data = dz; - ps.dekInfo = null; - ps.procType = null; - } - - public static final boolean isPEMEncrypted(PEMStructure ps) throws IOException { - if (ps.procType == null) - return false; - - if (ps.procType.length != 2) - throw new IOException("Unknown Proc-Type field."); - - if ("4".equals(ps.procType[0]) == false) - throw new IOException("Unknown Proc-Type field (" + ps.procType[0] + ")"); - - if ("ENCRYPTED".equals(ps.procType[1])) - return true; - - return false; - } - - public static KeyPair decode(char[] pem, String password) throws IOException { - PEMStructure ps = parsePEM(pem); - return decode(ps, password); - } - - public static KeyPair decode(PEMStructure ps, String password) throws IOException { - if (isPEMEncrypted(ps)) { - if (password == null) - throw new IOException("PEM is encrypted, but no password was specified"); - - decryptPEM(ps, password.getBytes("ISO-8859-1")); - } - - if (ps.pemType == PEM_DSA_PRIVATE_KEY) { - SimpleDERReader dr = new SimpleDERReader(ps.data); - byte[] seq = dr.readSequenceAsByteArray(); - - if (dr.available() != 0) - throw new IOException("Padding in DSA PRIVATE KEY DER stream."); - - dr.resetInput(seq); - BigInteger version = dr.readInt(); - - if (version.compareTo(BigInteger.ZERO) != 0) - throw new IOException("Wrong version (" + version + ") in DSA PRIVATE KEY DER stream."); - - BigInteger p = dr.readInt(); - BigInteger q = dr.readInt(); - BigInteger g = dr.readInt(); - BigInteger y = dr.readInt(); - BigInteger x = dr.readInt(); - - if (dr.available() != 0) - throw new IOException("Padding in DSA PRIVATE KEY DER stream."); - - DSAPrivateKeySpec privSpec = new DSAPrivateKeySpec(x, p, q, g); - DSAPublicKeySpec pubSpec = new DSAPublicKeySpec(y, p, q, g); - return generateKeyPair("DSA", privSpec, pubSpec); - } - - if (ps.pemType == PEM_RSA_PRIVATE_KEY) { - SimpleDERReader dr = new SimpleDERReader(ps.data); - byte[] seq = dr.readSequenceAsByteArray(); - - if (dr.available() != 0) - throw new IOException("Padding in RSA PRIVATE KEY DER stream."); - - dr.resetInput(seq); - BigInteger version = dr.readInt(); - - if ((version.compareTo(BigInteger.ZERO) != 0) && (version.compareTo(BigInteger.ONE) != 0)) - throw new IOException("Wrong version (" + version + ") in RSA PRIVATE KEY DER stream."); - - BigInteger n = dr.readInt(); - BigInteger e = dr.readInt(); - BigInteger d = dr.readInt(); - // TODO: is this right? - BigInteger primeP = dr.readInt(); - BigInteger primeQ = dr.readInt(); - BigInteger expP = dr.readInt(); - BigInteger expQ = dr.readInt(); - BigInteger coeff = dr.readInt(); - RSAPrivateKeySpec privSpec = new RSAPrivateCrtKeySpec(n, e, d, primeP, primeQ, expP, expQ, coeff); - RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(n, e); - return generateKeyPair("RSA", privSpec, pubSpec); - } - - if (ps.pemType == PEM_EC_PRIVATE_KEY) { - SimpleDERReader dr = new SimpleDERReader(ps.data); - byte[] seq = dr.readSequenceAsByteArray(); - - if (dr.available() != 0) - throw new IOException("Padding in EC PRIVATE KEY DER stream."); - - dr.resetInput(seq); - BigInteger version = dr.readInt(); - - if ((version.compareTo(BigInteger.ONE) != 0)) - throw new IOException("Wrong version (" + version + ") in EC PRIVATE KEY DER stream."); - - byte[] privateBytes = dr.readOctetString(); - String curveOid = null; - byte[] publicBytes = null; - - while (dr.available() > 0) { - int type = dr.readConstructedType(); - SimpleDERReader cr = dr.readConstructed(); - - switch (type) { - case 0: - curveOid = cr.readOid(); - break; - - case 1: - publicBytes = cr.readOctetString(); - break; - } - } - - ECParameterSpec params = ECDSASHA2Verify.getCurveForOID(curveOid); - - if (params == null) - throw new IOException("invalid OID"); - - BigInteger s = new BigInteger(privateBytes); - byte[] publicBytesSlice = new byte[publicBytes.length - 1]; - System.arraycopy(publicBytes, 1, publicBytesSlice, 0, publicBytesSlice.length); - ECPoint w = ECDSASHA2Verify.decodeECPoint(publicBytesSlice, params.getCurve()); - ECPrivateKeySpec privSpec = new ECPrivateKeySpec(s, params); - ECPublicKeySpec pubSpec = new ECPublicKeySpec(w, params); - return generateKeyPair("EC", privSpec, pubSpec); - } - - throw new IOException("PEM problem: it is of unknown type"); - } - - /** - * Generate a {@code KeyPair} given an {@code algorithm} and {@code KeySpec}. - */ - private static KeyPair generateKeyPair(String algorithm, KeySpec privSpec, KeySpec pubSpec) - throws IOException { - try { - final KeyFactory kf = KeyFactory.getInstance(algorithm); - final PublicKey pubKey = kf.generatePublic(pubSpec); - final PrivateKey privKey = kf.generatePrivate(privSpec); - return new KeyPair(pubKey, privKey); - } - catch (NoSuchAlgorithmException ex) { - IOException ioex = new IOException(); - ioex.initCause(ex); - throw ioex; - } - catch (InvalidKeySpecException ex) { - IOException ioex = new IOException("invalid keyspec"); - ioex.initCause(ex); - throw ioex; - } - } -}
--- a/src/ch/ethz/ssh2/crypto/PEMDecryptException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2006-2014 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto; - -import java.io.IOException; - -/** - * @version $Id: PEMDecryptException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class PEMDecryptException extends IOException { - /** - * - */ - private static final long serialVersionUID = 1L; - - public PEMDecryptException(String message) { - super(message); - } -}
--- a/src/ch/ethz/ssh2/crypto/PEMStructure.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto; - -/** - * Parsed PEM structure. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ - -public class PEMStructure { - public int pemType; - String dekInfo[]; - String procType[]; - byte[] data; -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/crypto/SecureRandomFix.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -// -// Copyright (C) 2014 by 510 Software Group -// licensed under the GPLv3 or later - -package ch.ethz.ssh2.crypto; - -import android.os.Build; -import android.os.Process; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.SecureRandom; - - -public class SecureRandomFix extends SecureRandom { - - // http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html - - private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18; - private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL = - getBuildFingerprintAndDeviceSerial(); - - private static byte[] generateReasonableSeed() { - try { - ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream(); - DataOutputStream seedBufferOut = - new DataOutputStream(seedBuffer); - seedBufferOut.writeLong(System.currentTimeMillis()); - seedBufferOut.writeLong(System.nanoTime()); - seedBufferOut.writeInt(Process.myPid()); - seedBufferOut.writeInt(Process.myUid()); - seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL); - seedBufferOut.close(); - return seedBuffer.toByteArray(); - } catch (IOException e) { - throw new SecurityException("Failed to generate seed", e); - } - } - - /** - * Gets the hardware serial number of this device. - * - * @return serial number or {@code null} if not available. - */ - private static String getDeviceSerialNumber() { - // We're using the Reflection API because Build.SERIAL is only available - // since API Level 9 (Gingerbread, Android 2.3). - try { - return (String) Build.class.getField("SERIAL").get(null); - } catch (Exception ignored) { - return null; - } - } - - private static byte[] getBuildFingerprintAndDeviceSerial() { - StringBuilder result = new StringBuilder(); - String fingerprint = Build.FINGERPRINT; - if (fingerprint != null) { - result.append(fingerprint); - } - String serial = getDeviceSerialNumber(); - if (serial != null) { - result.append(serial); - } - try { - return result.toString().getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("UTF-8 encoding not supported"); - } - } - - public SecureRandomFix() { - super(); - if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) { - // No need to apply the fix - return; - } - setSeed(generateReasonableSeed()); - } -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/crypto/SimpleDERReader.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -package ch.ethz.ssh2.crypto; - -import java.io.IOException; - -import java.math.BigInteger; - -/** - * SimpleDERReader. - * - * @author Christian Plattner, plattner@trilead.com - * @version $Id: SimpleDERReader.java,v 1.1 2007/10/15 12:49:56 cplattne Exp $ - */ -public class SimpleDERReader { - private static final int CONSTRUCTED = 0x20; - - byte[] buffer; - int pos; - int count; - - public SimpleDERReader(byte[] b) { - resetInput(b); - } - - public SimpleDERReader(byte[] b, int off, int len) { - resetInput(b, off, len); - } - - public void resetInput(byte[] b) { - resetInput(b, 0, b.length); - } - - public void resetInput(byte[] b, int off, int len) { - buffer = b; - pos = off; - count = len; - } - - private byte readByte() throws IOException { - if (count <= 0) - throw new IOException("DER byte array: out of data"); - - count--; - return buffer[pos++]; - } - - private byte[] readBytes(int len) throws IOException { - if (len > count) - throw new IOException("DER byte array: out of data"); - - byte[] b = new byte[len]; - System.arraycopy(buffer, pos, b, 0, len); - pos += len; - count -= len; - return b; - } - - public int available() { - return count; - } - - private int readLength() throws IOException { - int len = readByte() & 0xff; - - if ((len & 0x80) == 0) - return len; - - int remain = len & 0x7F; - - if (remain == 0) - return -1; - - len = 0; - - while (remain > 0) { - len = len << 8; - len = len | (readByte() & 0xff); - remain--; - } - - return len; - } - - public int ignoreNextObject() throws IOException { - int type = readByte() & 0xff; - int len = readLength(); - - if ((len < 0) || len > available()) - throw new IOException("Illegal len in DER object (" + len + ")"); - - readBytes(len); - return type; - } - - public BigInteger readInt() throws IOException { - int type = readByte() & 0xff; - - if (type != 0x02) - throw new IOException("Expected DER Integer, but found type " + type); - - int len = readLength(); - - if ((len < 0) || len > available()) - throw new IOException("Illegal len in DER object (" + len + ")"); - - byte[] b = readBytes(len); - BigInteger bi = new BigInteger(b); - return bi; - } - - public int readConstructedType() throws IOException { - int type = readByte() & 0xff; - - if ((type & CONSTRUCTED) != CONSTRUCTED) - throw new IOException("Expected constructed type, but was " + type); - - return type & 0x1f; - } - - public SimpleDERReader readConstructed() throws IOException { - int len = readLength(); - - if ((len < 0) || len > available()) - throw new IOException("Illegal len in DER object (" + len + ")"); - - SimpleDERReader cr = new SimpleDERReader(buffer, pos, len); - pos += len; - count -= len; - return cr; - } - - public byte[] readSequenceAsByteArray() throws IOException { - int type = readByte() & 0xff; - - if (type != 0x30) - throw new IOException("Expected DER Sequence, but found type " + type); - - int len = readLength(); - - if ((len < 0) || len > available()) - throw new IOException("Illegal len in DER object (" + len + ")"); - - byte[] b = readBytes(len); - return b; - } - - public String readOid() throws IOException { - int type = readByte() & 0xff; - - if (type != 0x06) - throw new IOException("Expected DER OID, but found type " + type); - - int len = readLength(); - - if ((len < 1) || len > available()) - throw new IOException("Illegal len in DER object (" + len + ")"); - - byte[] b = readBytes(len); - long value = 0; - StringBuilder sb = new StringBuilder(64); - - switch (b[0] / 40) { - case 0: - sb.append('0'); - break; - - case 1: - sb.append('1'); - b[0] -= 40; - break; - - default: - sb.append('2'); - b[0] -= 80; - break; - } - - for (int i = 0; i < len; i++) { - value = (value << 7) + (b[i] & 0x7F); - - if ((b[i] & 0x80) == 0) { - sb.append('.'); - sb.append(value); - value = 0; - } - } - - return sb.toString(); - } - - public byte[] readOctetString() throws IOException { - int type = readByte() & 0xff; - - if (type != 0x04 && type != 0x03) - throw new IOException("Expected DER Octetstring, but found type " + type); - - int len = readLength(); - - if ((len < 0) || len > available()) - throw new IOException("Illegal len in DER object (" + len + ")"); - - byte[] b = readBytes(len); - return b; - } - -}
--- a/src/ch/ethz/ssh2/crypto/cipher/AES.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,661 +0,0 @@ -package ch.ethz.ssh2.crypto.cipher; - -/* - This file was shamelessly taken from the Bouncy Castle Crypto package. - Their licence file states the following: - - Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle - (http://www.bouncycastle.org) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -/** - * An implementation of the AES (Rijndael), from FIPS-197. - * <p> - * For further details see: <a - * href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/ - * </a>. - * - * This implementation is based on optimizations from Dr. Brian Gladman's paper - * and C code at <a - * href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/ - * </a> - * - * There are three levels of tradeoff of speed vs memory Because java has no - * preprocessor, they are written as three separate classes from which to choose - * - * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 - * 256 word tables for encryption and 4 for decryption. - * - * The middle performance version uses only one 256 word table for each, for a - * total of 2Kbytes, adding 12 rotate operations per round to compute the values - * contained in the other tables from the contents of the first - * - * The slowest version uses no static tables at all and computes the values in - * each round - * <p> - * This file contains the fast version with 8Kbytes of static tables for round - * precomputation - * - * @author See comments in the source file - * @version 2.50, 03/15/10 - */ -public class AES implements BlockCipher { - // The S box - private static final byte[] S = { (byte) 99, (byte) 124, (byte) 119, (byte) 123, (byte) 242, (byte) 107, - (byte) 111, (byte) 197, (byte) 48, (byte) 1, (byte) 103, (byte) 43, (byte) 254, (byte) 215, (byte) 171, - (byte) 118, (byte) 202, (byte) 130, (byte) 201, (byte) 125, (byte) 250, (byte) 89, (byte) 71, (byte) 240, - (byte) 173, (byte) 212, (byte) 162, (byte) 175, (byte) 156, (byte) 164, (byte) 114, (byte) 192, (byte) 183, - (byte) 253, (byte) 147, (byte) 38, (byte) 54, (byte) 63, (byte) 247, (byte) 204, (byte) 52, (byte) 165, - (byte) 229, (byte) 241, (byte) 113, (byte) 216, (byte) 49, (byte) 21, (byte) 4, (byte) 199, (byte) 35, - (byte) 195, (byte) 24, (byte) 150, (byte) 5, (byte) 154, (byte) 7, (byte) 18, (byte) 128, (byte) 226, - (byte) 235, (byte) 39, (byte) 178, (byte) 117, (byte) 9, (byte) 131, (byte) 44, (byte) 26, (byte) 27, - (byte) 110, (byte) 90, (byte) 160, (byte) 82, (byte) 59, (byte) 214, (byte) 179, (byte) 41, (byte) 227, - (byte) 47, (byte) 132, (byte) 83, (byte) 209, (byte) 0, (byte) 237, (byte) 32, (byte) 252, (byte) 177, - (byte) 91, (byte) 106, (byte) 203, (byte) 190, (byte) 57, (byte) 74, (byte) 76, (byte) 88, (byte) 207, - (byte) 208, (byte) 239, (byte) 170, (byte) 251, (byte) 67, (byte) 77, (byte) 51, (byte) 133, (byte) 69, - (byte) 249, (byte) 2, (byte) 127, (byte) 80, (byte) 60, (byte) 159, (byte) 168, (byte) 81, (byte) 163, - (byte) 64, (byte) 143, (byte) 146, (byte) 157, (byte) 56, (byte) 245, (byte) 188, (byte) 182, (byte) 218, - (byte) 33, (byte) 16, (byte) 255, (byte) 243, (byte) 210, (byte) 205, (byte) 12, (byte) 19, (byte) 236, - (byte) 95, (byte) 151, (byte) 68, (byte) 23, (byte) 196, (byte) 167, (byte) 126, (byte) 61, (byte) 100, - (byte) 93, (byte) 25, (byte) 115, (byte) 96, (byte) 129, (byte) 79, (byte) 220, (byte) 34, (byte) 42, - (byte) 144, (byte) 136, (byte) 70, (byte) 238, (byte) 184, (byte) 20, (byte) 222, (byte) 94, (byte) 11, - (byte) 219, (byte) 224, (byte) 50, (byte) 58, (byte) 10, (byte) 73, (byte) 6, (byte) 36, (byte) 92, - (byte) 194, (byte) 211, (byte) 172, (byte) 98, (byte) 145, (byte) 149, (byte) 228, (byte) 121, (byte) 231, - (byte) 200, (byte) 55, (byte) 109, (byte) 141, (byte) 213, (byte) 78, (byte) 169, (byte) 108, (byte) 86, - (byte) 244, (byte) 234, (byte) 101, (byte) 122, (byte) 174, (byte) 8, (byte) 186, (byte) 120, (byte) 37, - (byte) 46, (byte) 28, (byte) 166, (byte) 180, (byte) 198, (byte) 232, (byte) 221, (byte) 116, (byte) 31, - (byte) 75, (byte) 189, (byte) 139, (byte) 138, (byte) 112, (byte) 62, (byte) 181, (byte) 102, (byte) 72, - (byte) 3, (byte) 246, (byte) 14, (byte) 97, (byte) 53, (byte) 87, (byte) 185, (byte) 134, (byte) 193, - (byte) 29, (byte) 158, (byte) 225, (byte) 248, (byte) 152, (byte) 17, (byte) 105, (byte) 217, (byte) 142, - (byte) 148, (byte) 155, (byte) 30, (byte) 135, (byte) 233, (byte) 206, (byte) 85, (byte) 40, (byte) 223, - (byte) 140, (byte) 161, (byte) 137, (byte) 13, (byte) 191, (byte) 230, (byte) 66, (byte) 104, (byte) 65, - (byte) 153, (byte) 45, (byte) 15, (byte) 176, (byte) 84, (byte) 187, (byte) 22, - }; - - // The inverse S-box - private static final byte[] Si = { (byte) 82, (byte) 9, (byte) 106, (byte) 213, (byte) 48, (byte) 54, (byte) 165, - (byte) 56, (byte) 191, (byte) 64, (byte) 163, (byte) 158, (byte) 129, (byte) 243, (byte) 215, (byte) 251, - (byte) 124, (byte) 227, (byte) 57, (byte) 130, (byte) 155, (byte) 47, (byte) 255, (byte) 135, (byte) 52, - (byte) 142, (byte) 67, (byte) 68, (byte) 196, (byte) 222, (byte) 233, (byte) 203, (byte) 84, (byte) 123, - (byte) 148, (byte) 50, (byte) 166, (byte) 194, (byte) 35, (byte) 61, (byte) 238, (byte) 76, (byte) 149, - (byte) 11, (byte) 66, (byte) 250, (byte) 195, (byte) 78, (byte) 8, (byte) 46, (byte) 161, (byte) 102, - (byte) 40, (byte) 217, (byte) 36, (byte) 178, (byte) 118, (byte) 91, (byte) 162, (byte) 73, (byte) 109, - (byte) 139, (byte) 209, (byte) 37, (byte) 114, (byte) 248, (byte) 246, (byte) 100, (byte) 134, (byte) 104, - (byte) 152, (byte) 22, (byte) 212, (byte) 164, (byte) 92, (byte) 204, (byte) 93, (byte) 101, (byte) 182, - (byte) 146, (byte) 108, (byte) 112, (byte) 72, (byte) 80, (byte) 253, (byte) 237, (byte) 185, (byte) 218, - (byte) 94, (byte) 21, (byte) 70, (byte) 87, (byte) 167, (byte) 141, (byte) 157, (byte) 132, (byte) 144, - (byte) 216, (byte) 171, (byte) 0, (byte) 140, (byte) 188, (byte) 211, (byte) 10, (byte) 247, (byte) 228, - (byte) 88, (byte) 5, (byte) 184, (byte) 179, (byte) 69, (byte) 6, (byte) 208, (byte) 44, (byte) 30, - (byte) 143, (byte) 202, (byte) 63, (byte) 15, (byte) 2, (byte) 193, (byte) 175, (byte) 189, (byte) 3, - (byte) 1, (byte) 19, (byte) 138, (byte) 107, (byte) 58, (byte) 145, (byte) 17, (byte) 65, (byte) 79, - (byte) 103, (byte) 220, (byte) 234, (byte) 151, (byte) 242, (byte) 207, (byte) 206, (byte) 240, (byte) 180, - (byte) 230, (byte) 115, (byte) 150, (byte) 172, (byte) 116, (byte) 34, (byte) 231, (byte) 173, (byte) 53, - (byte) 133, (byte) 226, (byte) 249, (byte) 55, (byte) 232, (byte) 28, (byte) 117, (byte) 223, (byte) 110, - (byte) 71, (byte) 241, (byte) 26, (byte) 113, (byte) 29, (byte) 41, (byte) 197, (byte) 137, (byte) 111, - (byte) 183, (byte) 98, (byte) 14, (byte) 170, (byte) 24, (byte) 190, (byte) 27, (byte) 252, (byte) 86, - (byte) 62, (byte) 75, (byte) 198, (byte) 210, (byte) 121, (byte) 32, (byte) 154, (byte) 219, (byte) 192, - (byte) 254, (byte) 120, (byte) 205, (byte) 90, (byte) 244, (byte) 31, (byte) 221, (byte) 168, (byte) 51, - (byte) 136, (byte) 7, (byte) 199, (byte) 49, (byte) 177, (byte) 18, (byte) 16, (byte) 89, (byte) 39, - (byte) 128, (byte) 236, (byte) 95, (byte) 96, (byte) 81, (byte) 127, (byte) 169, (byte) 25, (byte) 181, - (byte) 74, (byte) 13, (byte) 45, (byte) 229, (byte) 122, (byte) 159, (byte) 147, (byte) 201, (byte) 156, - (byte) 239, (byte) 160, (byte) 224, (byte) 59, (byte) 77, (byte) 174, (byte) 42, (byte) 245, (byte) 176, - (byte) 200, (byte) 235, (byte) 187, (byte) 60, (byte) 131, (byte) 83, (byte) 153, (byte) 97, (byte) 23, - (byte) 43, (byte) 4, (byte) 126, (byte) 186, (byte) 119, (byte) 214, (byte) 38, (byte) 225, (byte) 105, - (byte) 20, (byte) 99, (byte) 85, (byte) 33, (byte) 12, (byte) 125, - }; - - // vector used in calculating key schedule (powers of x in GF(256)) - private static final int[] rcon = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, - 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 - }; - - // precomputation tables of calculations for rounds - private static final int[] T0 = { 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, - 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, - 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, - 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, 0xc2b7b775, - 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551, - 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795, 0x65232346, - 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, - 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, - 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, - 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, - 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, - 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a, - 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, - 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, - 0x63212142, 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, - 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, - 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, - 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, - 0x76dbdbad, 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, - 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, - 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac, - 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a, - 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, - 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, - 0x05030306, 0x01f6f6f7, 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, - 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, - 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, - 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, - 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c - }; - - private static final int[] T1 = { 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, - 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, - 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, - 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, 0xb7b775c2, - 0xfdfde11c, 0x93933dae, 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, 0x3434685c, 0xa5a551f4, - 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552, 0x23234665, - 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, - 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, - 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, - 0x2f2f5e71, 0x84841397, 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060, 0xfcfce31f, 0xb1b179c8, - 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, - 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf, - 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, - 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, - 0x21214263, 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f, - 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, - 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e, - 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, - 0xdbdbad76, 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4, - 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, 0xe7e7d532, - 0xc8c88b43, 0x37376e59, 0x6d6ddab7, 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, 0x5656acfa, - 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f, - 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, - 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, 0x484890d8, - 0x03030605, 0xf6f6f701, 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958, - 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, - 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, - 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, - 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a - }; - - private static final int[] T2 = { 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, - 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, - 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, - 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, 0xb775c2b7, - 0xfde11cfd, 0x933dae93, 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, 0x34685c34, 0xa551f4a5, - 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7, 0x23466523, - 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, - 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, - 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, - 0x2f5e712f, 0x84139784, 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020, 0xfce31ffc, 0xb179c8b1, - 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, - 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45, - 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, - 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, - 0x21426321, 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec, - 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, 0x64c8ac64, - 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a, - 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, - 0xdbad76db, 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c, - 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, 0xe7d532e7, - 0xc88b43c8, 0x376e5937, 0x6ddab76d, 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, 0x56acfa56, - 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25, - 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, - 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, 0x4890d848, - 0x03060503, 0xf6f701f6, 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1, - 0x1d3a271d, 0x9e27b99e, 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9, 0x8e07898e, - 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, - 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, - 0x9929b099, 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16 - }; - - private static final int[] T3 = { 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, - 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, - 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, - 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, - 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, 0x685c3434, 0x51f4a5a5, - 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7, 0x46652323, - 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, - 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, - 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, - 0x5e712f2f, 0x13978484, 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020, 0xe31ffcfc, 0x79c8b1b1, - 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, - 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545, - 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, - 0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, - 0x42632121, 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, - 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, - 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a, - 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, - 0xad76dbdb, 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c, - 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, 0xd532e7e7, - 0x8b43c8c8, 0x6e593737, 0xdab76d6d, 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, 0xacfa5656, - 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525, - 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, - 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, 0x90d84848, - 0x06050303, 0xf701f6f6, 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1, - 0x3a271d1d, 0x27b99e9e, 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9, 0x07898e8e, - 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, - 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, - 0x29b09999, 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616 - }; - - private static final int[] Tinv0 = { 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, - 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, - 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, - 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, 0x6a89c275, - 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5, - 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f, 0x876cde94, - 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3, - 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, - 0xd5be0506, 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, - 0x069f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x055dc471, 0x6fd40604, - 0xff155060, 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, - 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd, - 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, - 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, - 0x1d171b12, 0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, - 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, - 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, - 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, - 0xef903322, 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, - 0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, 0xbe805d9f, - 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd, 0xf418596e, - 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea, - 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, - 0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, - 0x1b886a4c, 0xb81f2cc1, 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, - 0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, - 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, - 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, - 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0 - }; - - private static final int[] Tinv1 = { 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb, 0x459d1ff1, - 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680, - 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1, 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, - 0x5f8f03e7, 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3, 0x69e04929, 0xc8c98e44, 0x89c2756a, - 0x798ef478, 0x3e58996b, 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4, 0x4adf6318, 0x311ae582, - 0x33519760, 0x7f536245, 0x7764b1e0, 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19, 0x6cde9487, - 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357, 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5, - 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b, 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, - 0xbe0506d5, 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532, 0xebf6a475, 0xec830b39, 0xef6040aa, - 0x9f715e06, 0x106ebd51, 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5, 0x5dc47105, 0xd406046f, - 0x155060ff, 0xfb981924, 0xe9bdd697, 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738, 0xeec879db, - 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000, 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb, - 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821, 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, - 0x96eeb4d2, 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16, 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, - 0x171b121d, 0x0d090e0b, 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c, 0xdd99eebb, 0x607fa3fd, - 0x2601f79f, 0xf5725cbc, 0x3b6644c5, 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863, 0xdc31d7ca, - 0x85634210, 0x22971340, 0x11c68420, 0x244a857d, 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3, - 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa, 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, - 0x903322ef, 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf, 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, - 0x9d3a2ce4, 0x9278500d, 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e, 0xafc382f5, 0x805d9fbe, - 0x93d0697c, 0x2dd56fa9, 0x1225cfb3, 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09, 0x18596ef4, - 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e, 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4, - 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0, 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, - 0x9804f14a, 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d, 0x4daacc54, 0x0496e4df, 0xb5d19ee3, - 0x886a4c1b, 0x1f2cc1b8, 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e, 0x1d67b35a, 0xd2db9252, - 0x5610e933, 0x47d66d13, 0x61d79a8c, 0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735, 0xe51ce1ed, - 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879, 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886, - 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, - 0xb30c08de, 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042 - }; - - private static final int[] Tinv2 = { 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b, 0x9d1ff145, - 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d, 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044, - 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0, 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, - 0x8f03e75f, 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321, 0xe0492969, 0xc98e44c8, 0xc2756a89, - 0x8ef47879, 0x58996b3e, 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a, 0xdf63184a, 0x1ae58231, - 0x51976033, 0x5362457f, 0x64b1e077, 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd, 0xde94876c, - 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f, 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508, - 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c, 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, - 0x0506d5be, 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1, 0xf6a475eb, 0x830b39ec, 0x6040aaef, - 0x715e069f, 0x6ebd5110, 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d, 0xc471055d, 0x06046fd4, - 0x5060ff15, 0x981924fb, 0xbdd697e9, 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b, 0xc879dbee, - 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000, 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff, - 0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6, 0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, - 0xeeb4d296, 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a, 0x93e20aba, 0xa0c0e52a, 0x223c43e0, - 0x1b121d17, 0x090e0b0d, 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07, 0x99eebbdd, 0x7fa3fd60, - 0x01f79f26, 0x725cbcf5, 0x6644c53b, 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1, 0x31d7cadc, - 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24, 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330, - 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48, 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, - 0x3322ef90, 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81, 0x7aa528de, 0xb7da268e, 0xad3fa4bf, - 0x3a2ce49d, 0x78500d92, 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7, 0xc382f5af, 0x5d9fbe80, - 0xd0697c93, 0xd56fa92d, 0x25cfb312, 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978, 0x596ef418, - 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6, 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409, - 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066, 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, - 0x04f14a98, 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0, 0xaacc544d, 0x96e4df04, 0xd19ee3b5, - 0x6a4c1b88, 0x2cc1b81f, 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41, 0x67b35a1d, 0xdb9252d2, - 0x10e93356, 0xd66d1347, 0xd79a8c61, 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9, 0x1ce1ede5, - 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce, 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db, - 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, - 0x0c08deb3, 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257 - }; - - private static final int[] Tinv3 = { 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab, 0x1ff1459d, - 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, - 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe, 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, - 0x03e75f8f, 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174, 0x492969e0, 0x8e44c8c9, 0x756a89c2, - 0xf478798e, 0x996b3e58, 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace, 0x63184adf, 0xe582311a, - 0x97603351, 0x62457f53, 0xb1e07764, 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45, 0x94876cde, - 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f, 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837, - 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf, 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, - 0x06d5be05, 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a, 0xa475ebf6, 0x0b39ec83, 0x40aaef60, - 0x5e069f71, 0xbd51106e, 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54, 0x71055dc4, 0x046fd406, - 0x60ff1550, 0x1924fb98, 0xd697e9bd, 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19, 0x79dbeec8, - 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000, 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e, - 0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c, 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, - 0xb4d296ee, 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12, 0xe20aba93, 0xc0e52aa0, 0x3c43e022, - 0x121d171b, 0x0e0b0d09, 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775, 0xeebbdd99, 0xa3fd607f, - 0xf79f2601, 0x5cbcf572, 0x44c53b66, 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4, 0xd7cadc31, - 0x42108563, 0x13402297, 0x842011c6, 0x857d244a, 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2, - 0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894, 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, - 0x22ef9033, 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5, 0xa528de7a, 0xda268eb7, 0x3fa4bfad, - 0x2ce49d3a, 0x500d9278, 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739, 0x82f5afc3, 0x9fbe805d, - 0x697c93d0, 0x6fa92dd5, 0xcfb31225, 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826, 0x6ef41859, - 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff, 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f, - 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2, 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, - 0xf14a9804, 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef, 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, - 0x4c1b886a, 0xc1b81f2c, 0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b, 0xb35a1d67, 0x9252d2db, - 0xe9335610, 0x6d1347d6, 0x9a8c61d7, 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961, 0xe1ede51c, - 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14, 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44, - 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d, 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, - 0x08deb30c, 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8 - }; - - private int shift(int r, int shift) { - return (((r >>> shift) | (r << (32 - shift)))); - } - - /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ - - private static final int m1 = 0x80808080; - private static final int m2 = 0x7f7f7f7f; - private static final int m3 = 0x0000001b; - - private int FFmulX(int x) { - return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3)); - } - - /* - * The following defines provide alternative definitions of FFmulX that - * might give improved performance if a fast 32-bit multiply is not - * available. - * - * private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & - * m2) < < 1) ^ ((u >>> 3) | (u >>> 6)); } private static final int m4 = - * 0x1b1b1b1b; private int FFmulX(int x) { int u = x & m1; return ((x & m2) < < - * 1) ^ ((u - (u >>> 7)) & m4); } - * - */ - - private int inv_mcol(int x) { - int f2 = FFmulX(x); - int f4 = FFmulX(f2); - int f8 = FFmulX(f4); - int f9 = x ^ f8; - return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24); - } - - private int subWord(int x) { - return (S[x & 255] & 255 | ((S[(x >> 8) & 255] & 255) << 8) | ((S[(x >> 16) & 255] & 255) << 16) | S[(x >> 24) & 255] << 24); - } - - /** - * Calculate the necessary round keys The number of calculations depends on - * key size and block size AES specified a fixed block size of 128 bits and - * key sizes 128/192/256 bits This code is written assuming those are the - * only possible values - */ - private int[][] generateWorkingKey(byte[] key, boolean forEncryption) { - int KC = key.length / 4; // key length in words - int t; - - if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length)) { - throw new IllegalArgumentException("Key length not 128/192/256 bits."); - } - - ROUNDS = KC + 6; // This is not always true for the generalized - // Rijndael that allows larger block sizes - int[][] W = new int[ROUNDS + 1][4]; // 4 words in a block - // - // copy the key into the round key array - // - t = 0; - - for (int i = 0; i < key.length; t++) { - W[t >> 2][t & 3] = (key[i] & 0xff) | ((key[i + 1] & 0xff) << 8) | ((key[i + 2] & 0xff) << 16) - | (key[i + 3] << 24); - i += 4; - } - - // - // while not enough round key material calculated - // calculate new values - // - int k = (ROUNDS + 1) << 2; - - for (int i = KC; (i < k); i++) { - int temp = W[(i - 1) >> 2][(i - 1) & 3]; - - if ((i % KC) == 0) { - temp = subWord(shift(temp, 8)) ^ rcon[(i / KC) - 1]; - } - else if ((KC > 6) && ((i % KC) == 4)) { - temp = subWord(temp); - } - - W[i >> 2][i & 3] = W[(i - KC) >> 2][(i - KC) & 3] ^ temp; - } - - if (!forEncryption) { - for (int j = 1; j < ROUNDS; j++) { - for (int i = 0; i < 4; i++) { - W[j][i] = inv_mcol(W[j][i]); - } - } - } - - return W; - } - - private int ROUNDS; - private int[][] WorkingKey = null; - private int C0, C1, C2, C3; - private boolean doEncrypt; - - private static final int BLOCK_SIZE = 16; - - /** - * default constructor - 128 bit block size. - */ - public AES() { - } - - /** - * initialise an AES cipher. - * - * @param forEncryption - * whether or not we are for encryption. - * @param key - * the key required to set up the cipher. - * @exception IllegalArgumentException - * if the params argument is inappropriate. - */ - - public final void init(boolean forEncryption, byte[] key) { - WorkingKey = generateWorkingKey(key, forEncryption); - this.doEncrypt = forEncryption; - } - - public final String getAlgorithmName() { - return "AES"; - } - - public final int getBlockSize() { - return BLOCK_SIZE; - } - - public final int processBlock(byte[] in, int inOff, byte[] out, int outOff) { - if (WorkingKey == null) { - throw new IllegalStateException("AES engine not initialised"); - } - - if ((inOff + (32 / 2)) > in.length) { - throw new IllegalArgumentException("input buffer too short"); - } - - if ((outOff + (32 / 2)) > out.length) { - throw new IllegalArgumentException("output buffer too short"); - } - - if (doEncrypt) { - unpackBlock(in, inOff); - encryptBlock(WorkingKey); - packBlock(out, outOff); - } - else { - unpackBlock(in, inOff); - decryptBlock(WorkingKey); - packBlock(out, outOff); - } - - return BLOCK_SIZE; - } - - public final void reset() { - } - - private void unpackBlock(byte[] bytes, int off) { - int index = off; - C0 = (bytes[index++] & 0xff); - C0 |= (bytes[index++] & 0xff) << 8; - C0 |= (bytes[index++] & 0xff) << 16; - C0 |= bytes[index++] << 24; - C1 = (bytes[index++] & 0xff); - C1 |= (bytes[index++] & 0xff) << 8; - C1 |= (bytes[index++] & 0xff) << 16; - C1 |= bytes[index++] << 24; - C2 = (bytes[index++] & 0xff); - C2 |= (bytes[index++] & 0xff) << 8; - C2 |= (bytes[index++] & 0xff) << 16; - C2 |= bytes[index++] << 24; - C3 = (bytes[index++] & 0xff); - C3 |= (bytes[index++] & 0xff) << 8; - C3 |= (bytes[index++] & 0xff) << 16; - C3 |= bytes[index++] << 24; - } - - private void packBlock(byte[] bytes, int off) { - int index = off; - bytes[index++] = (byte) C0; - bytes[index++] = (byte)(C0 >> 8); - bytes[index++] = (byte)(C0 >> 16); - bytes[index++] = (byte)(C0 >> 24); - bytes[index++] = (byte) C1; - bytes[index++] = (byte)(C1 >> 8); - bytes[index++] = (byte)(C1 >> 16); - bytes[index++] = (byte)(C1 >> 24); - bytes[index++] = (byte) C2; - bytes[index++] = (byte)(C2 >> 8); - bytes[index++] = (byte)(C2 >> 16); - bytes[index++] = (byte)(C2 >> 24); - bytes[index++] = (byte) C3; - bytes[index++] = (byte)(C3 >> 8); - bytes[index++] = (byte)(C3 >> 16); - bytes[index++] = (byte)(C3 >> 24); - } - - private void encryptBlock(int[][] KW) { - int r, r0, r1, r2, r3; - C0 ^= KW[0][0]; - C1 ^= KW[0][1]; - C2 ^= KW[0][2]; - C3 ^= KW[0][3]; - - for (r = 1; r < ROUNDS - 1;) { - r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[(C3 >> 24) & 255] ^ KW[r][0]; - r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[(C0 >> 24) & 255] ^ KW[r][1]; - r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[(C1 >> 24) & 255] ^ KW[r][2]; - r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[(C2 >> 24) & 255] ^ KW[r++][3]; - C0 = T0[r0 & 255] ^ T1[(r1 >> 8) & 255] ^ T2[(r2 >> 16) & 255] ^ T3[(r3 >> 24) & 255] ^ KW[r][0]; - C1 = T0[r1 & 255] ^ T1[(r2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[(r0 >> 24) & 255] ^ KW[r][1]; - C2 = T0[r2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(r0 >> 16) & 255] ^ T3[(r1 >> 24) & 255] ^ KW[r][2]; - C3 = T0[r3 & 255] ^ T1[(r0 >> 8) & 255] ^ T2[(r1 >> 16) & 255] ^ T3[(r2 >> 24) & 255] ^ KW[r++][3]; - } - - r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[(C3 >> 24) & 255] ^ KW[r][0]; - r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[(C0 >> 24) & 255] ^ KW[r][1]; - r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[(C1 >> 24) & 255] ^ KW[r][2]; - r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[(C2 >> 24) & 255] ^ KW[r++][3]; - // the final round's table is a simple function of S so we don't use a - // whole other four tables for it - C0 = (S[r0 & 255] & 255) ^ ((S[(r1 >> 8) & 255] & 255) << 8) ^ ((S[(r2 >> 16) & 255] & 255) << 16) - ^ (S[(r3 >> 24) & 255] << 24) ^ KW[r][0]; - C1 = (S[r1 & 255] & 255) ^ ((S[(r2 >> 8) & 255] & 255) << 8) ^ ((S[(r3 >> 16) & 255] & 255) << 16) - ^ (S[(r0 >> 24) & 255] << 24) ^ KW[r][1]; - C2 = (S[r2 & 255] & 255) ^ ((S[(r3 >> 8) & 255] & 255) << 8) ^ ((S[(r0 >> 16) & 255] & 255) << 16) - ^ (S[(r1 >> 24) & 255] << 24) ^ KW[r][2]; - C3 = (S[r3 & 255] & 255) ^ ((S[(r0 >> 8) & 255] & 255) << 8) ^ ((S[(r1 >> 16) & 255] & 255) << 16) - ^ (S[(r2 >> 24) & 255] << 24) ^ KW[r][3]; - } - - private void decryptBlock(int[][] KW) { - int r, r0, r1, r2, r3; - C0 ^= KW[ROUNDS][0]; - C1 ^= KW[ROUNDS][1]; - C2 ^= KW[ROUNDS][2]; - C3 ^= KW[ROUNDS][3]; - - for (r = ROUNDS - 1; r > 1;) { - r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[(C1 >> 24) & 255] - ^ KW[r][0]; - r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[(C2 >> 24) & 255] - ^ KW[r][1]; - r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[(C3 >> 24) & 255] - ^ KW[r][2]; - r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[(C0 >> 24) & 255] - ^ KW[r--][3]; - C0 = Tinv0[r0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(r2 >> 16) & 255] ^ Tinv3[(r1 >> 24) & 255] - ^ KW[r][0]; - C1 = Tinv0[r1 & 255] ^ Tinv1[(r0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[(r2 >> 24) & 255] - ^ KW[r][1]; - C2 = Tinv0[r2 & 255] ^ Tinv1[(r1 >> 8) & 255] ^ Tinv2[(r0 >> 16) & 255] ^ Tinv3[(r3 >> 24) & 255] - ^ KW[r][2]; - C3 = Tinv0[r3 & 255] ^ Tinv1[(r2 >> 8) & 255] ^ Tinv2[(r1 >> 16) & 255] ^ Tinv3[(r0 >> 24) & 255] - ^ KW[r--][3]; - } - - r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[(C1 >> 24) & 255] ^ KW[r][0]; - r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[(C2 >> 24) & 255] ^ KW[r][1]; - r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[(C3 >> 24) & 255] ^ KW[r][2]; - r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[(C0 >> 24) & 255] ^ KW[r--][3]; - // the final round's table is a simple function of Si so we don't use a - // whole other four tables for it - C0 = (Si[r0 & 255] & 255) ^ ((Si[(r3 >> 8) & 255] & 255) << 8) ^ ((Si[(r2 >> 16) & 255] & 255) << 16) - ^ (Si[(r1 >> 24) & 255] << 24) ^ KW[0][0]; - C1 = (Si[r1 & 255] & 255) ^ ((Si[(r0 >> 8) & 255] & 255) << 8) ^ ((Si[(r3 >> 16) & 255] & 255) << 16) - ^ (Si[(r2 >> 24) & 255] << 24) ^ KW[0][1]; - C2 = (Si[r2 & 255] & 255) ^ ((Si[(r1 >> 8) & 255] & 255) << 8) ^ ((Si[(r0 >> 16) & 255] & 255) << 16) - ^ (Si[(r3 >> 24) & 255] << 24) ^ KW[0][2]; - C3 = (Si[r3 & 255] & 255) ^ ((Si[(r2 >> 8) & 255] & 255) << 8) ^ ((Si[(r1 >> 16) & 255] & 255) << 16) - ^ (Si[(r0 >> 24) & 255] << 24) ^ KW[0][3]; - } - - public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { - processBlock(src, srcoff, dst, dstoff); - } -}
--- a/src/ch/ethz/ssh2/crypto/cipher/BlockCipher.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.cipher; - -/** - * BlockCipher. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public interface BlockCipher { - public void init(boolean forEncryption, byte[] key); - - public int getBlockSize(); - - public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff); -}
--- a/src/ch/ethz/ssh2/crypto/cipher/BlockCipherFactory.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.cipher; - -import java.util.ArrayList; -import java.util.List; -import java.util.Vector; - -/** - * BlockCipherFactory. - * - * @author Christian Plattner - * @version $Id: BlockCipherFactory.java 86 2014-04-07 14:15:18Z dkocher@sudo.ch $ - */ -public class BlockCipherFactory { - private static final class CipherEntry { - String type; - int blocksize; - int keysize; - String cipherClass; - - public CipherEntry(String type, int blockSize, int keySize, String cipherClass) { - this.type = type; - this.blocksize = blockSize; - this.keysize = keySize; - this.cipherClass = cipherClass; - } - } - - private static final List<CipherEntry> ciphers = new ArrayList<CipherEntry>(); - - static { - // Higher priority (stronger) first - ciphers.add(new CipherEntry("aes256-ctr", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("aes192-ctr", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("aes128-ctr", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("blowfish-ctr", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); - ciphers.add(new CipherEntry("aes256-cbc", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("aes192-cbc", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("aes128-cbc", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("blowfish-cbc", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); - ciphers.add(new CipherEntry("3des-ctr", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); - ciphers.add(new CipherEntry("3des-cbc", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); - } - - public static String[] getDefaultCipherList() { - List<String> list = new ArrayList<String>(ciphers.size()); - - for (CipherEntry ce : ciphers) { - list.add(ce.type); - } - - return list.toArray(new String[ciphers.size()]); - } - - public static void checkCipherList(String[] cipherCandidates) { - for (String cipherCandidate : cipherCandidates) { - getEntry(cipherCandidate); - } - } - - // @SuppressWarnings("rawtypes") - public static BlockCipher createCipher(String type, boolean encrypt, byte[] key, byte[] iv) { - try { - CipherEntry ce = getEntry(type); - Class<?> cc = Class.forName(ce.cipherClass); - BlockCipher bc = (BlockCipher) cc.newInstance(); - - if (type.endsWith("-cbc")) { - bc.init(encrypt, key); - return new CBCMode(bc, iv, encrypt); - } - else if (type.endsWith("-ctr")) { - bc.init(true, key); - return new CTRMode(bc, iv, encrypt); - } - - throw new IllegalArgumentException("Cannot instantiate " + type); - } - catch (ClassNotFoundException e) { - throw new IllegalArgumentException("Cannot instantiate " + type, e); - } - catch (InstantiationException e) { - throw new IllegalArgumentException("Cannot instantiate " + type, e); - } - catch (IllegalAccessException e) { - throw new IllegalArgumentException("Cannot instantiate " + type, e); - } - } - - private static CipherEntry getEntry(String type) { - for (CipherEntry ce : ciphers) { - if (ce.type.equals(type)) { - return ce; - } - } - - throw new IllegalArgumentException("Unkown algorithm " + type); - } - - public static int getBlockSize(String type) { - CipherEntry ce = getEntry(type); - return ce.blocksize; - } - - public static int getKeySize(String type) { - CipherEntry ce = getEntry(type); - return ce.keysize; - } -}
--- a/src/ch/ethz/ssh2/crypto/cipher/BlowFish.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,376 +0,0 @@ -package ch.ethz.ssh2.crypto.cipher; - -/* - This file was shamelessly taken from the Bouncy Castle Crypto package. - Their licence file states the following: - - Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle - (http://www.bouncycastle.org) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -/** - * A class that provides Blowfish key encryption operations, such as encoding - * data and generating keys. All the algorithms herein are from Applied - * Cryptography and implement a simplified cryptography interface. - * - * @author See comments in the source file - * @version 2.50, 03/15/10 - */ -public class BlowFish implements BlockCipher { - - private final static int[] KP = { 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, - 0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, - 0xB5470917, 0x9216D5D9, 0x8979FB1B - }, - - KS0 = { 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, 0x24A19947, - 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658, - 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918, - 0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, - 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, - 0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C, - 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60, - 0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, - 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, 0x6A51A0D2, - 0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176, - 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, 0x401A449F, - 0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, - 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6, - 0x409F60C4, 0x5E5C9EC2, 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C, - 0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, 0x45C8740F, 0xD20B5F39, - 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, - 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, 0x9E5C57BB, - 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, 0xBBCA58C8, - 0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, 0x9A53E479, 0xB6F84565, 0xD28E49BC, - 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, - 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB, - 0xF2122B64, 0x8888B812, 0x900DF01C, 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777, - 0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, - 0xD2ADA8D9, 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, - 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, 0x2464369B, - 0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9, - 0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, - 0x81E67400, 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, - 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A - }, - - KS1 = { 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, - 0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65, - 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6, - 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, - 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A, - 0x3CB574B2, 0x25837A58, 0xDC0921BD, 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC, - 0xC8B57634, 0x9AF3DDA7, 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, - 0x183EB331, 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, - 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, 0x7A584718, - 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908, - 0xDD433B37, 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55, 0x81AC77D6, - 0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, - 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6, - 0x5266C825, 0x2E4CC978, 0x9C10B36A, 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D, - 0x1939260F, 0x19C27960, 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883, 0xB17F37D1, - 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, - 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90, - 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA, - 0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099, 0x95F7997E, - 0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, - 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF, - 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA, - 0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A, - 0x3D816250, 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, - 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, 0x3372F092, - 0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E, - 0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484, 0xFDD56705, - 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, - 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 - }, - - KS2 = { 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, 0xD4082471, - 0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF, - 0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6, - 0xABCA0A9A, 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, - 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, 0x20FE9E35, - 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332, - 0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7, - 0xD096954B, 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, - 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, 0x07F9C9EE, - 0x41041F0F, 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60, - 0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, 0x3B240B62, - 0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, - 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60, - 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3, - 0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, 0x7B9479BF, - 0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, - 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659, - 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, 0xF0F7C086, - 0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, 0xB0804187, - 0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, - 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E, - 0x20B45770, 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, 0xE0A9DC09, - 0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, - 0x2868F169, 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, - 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, 0x11E69ED7, - 0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, 0x4B7C0188, - 0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, 0xD83D7CD3, - 0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, - 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 - }, - - KS3 = { 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, 0xD5118E9D, - 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79, - 0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, - 0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, - 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, 0xC72FEFD3, - 0xF752F7DA, 0x3F046F69, 0x77FA0A59, 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797, - 0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, - 0x5A88F54C, 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, - 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, 0xC3EB9E15, - 0x3C9057A2, 0x97271AEC, 0xA93A072A, 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5, - 0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, 0x4DE81751, 0x3830DC8E, 0x379D5862, - 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, - 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, - 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB, - 0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, 0x740E0D8D, 0xE75B1357, 0xF8721671, - 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, - 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1, - 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A, - 0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, - 0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, - 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532, - 0xE0D392DF, 0xD3A0342B, 0x8971F21E, 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E, - 0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5, - 0xF6FB2299, 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, - 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, 0xC9AA53FD, - 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3, - 0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, - 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, - 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 - }; - - // ==================================== - // Useful constants - // ==================================== - - private static final int ROUNDS = 16; - private static final int BLOCK_SIZE = 8; // bytes = 64 bits - private static final int SBOX_SK = 256; - private static final int P_SZ = ROUNDS + 2; - - private final int[] S0, S1, S2, S3; // the s-boxes - private final int[] P; // the p-array - - private boolean doEncrypt = false; - - private byte[] workingKey = null; - - public BlowFish() { - S0 = new int[SBOX_SK]; - S1 = new int[SBOX_SK]; - S2 = new int[SBOX_SK]; - S3 = new int[SBOX_SK]; - P = new int[P_SZ]; - } - - /** - * initialise a Blowfish cipher. - * - * @param encrypting - * whether or not we are for encryption. - * @param key - * the key required to set up the cipher. - * @exception IllegalArgumentException - * if the params argument is inappropriate. - */ - public void init(boolean encrypting, byte[] key) { - this.doEncrypt = encrypting; - this.workingKey = key; - setKey(this.workingKey); - } - - public String getAlgorithmName() { - return "Blowfish"; - } - - public final void transformBlock(byte[] in, int inOff, byte[] out, int outOff) { - if (workingKey == null) { - throw new IllegalStateException("Blowfish not initialised"); - } - - if (doEncrypt) { - encryptBlock(in, inOff, out, outOff); - } - else { - decryptBlock(in, inOff, out, outOff); - } - } - - public void reset() { - } - - public int getBlockSize() { - return BLOCK_SIZE; - } - - // ================================== - // Private Implementation - // ================================== - - private int F(int x) { - return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff]) ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]); - } - - /** - * apply the encryption cycle to each value pair in the table. - */ - private void processTable(int xl, int xr, int[] table) { - int size = table.length; - - for (int s = 0; s < size; s += 2) { - xl ^= P[0]; - - for (int i = 1; i < ROUNDS; i += 2) { - xr ^= F(xl) ^ P[i]; - xl ^= F(xr) ^ P[i + 1]; - } - - xr ^= P[ROUNDS + 1]; - table[s] = xr; - table[s + 1] = xl; - xr = xl; // end of cycle swap - xl = table[s]; - } - } - - private void setKey(byte[] key) { - /* - * - comments are from _Applied Crypto_, Schneier, p338 please be - * careful comparing the two, AC numbers the arrays from 1, the enclosed - * code from 0. - * - * (1) Initialise the S-boxes and the P-array, with a fixed string This - * string contains the hexadecimal digits of pi (3.141...) - */ - System.arraycopy(KS0, 0, S0, 0, SBOX_SK); - System.arraycopy(KS1, 0, S1, 0, SBOX_SK); - System.arraycopy(KS2, 0, S2, 0, SBOX_SK); - System.arraycopy(KS3, 0, S3, 0, SBOX_SK); - System.arraycopy(KP, 0, P, 0, P_SZ); - /* - * (2) Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with - * the second 32-bits of the key, and so on for all bits of the key (up - * to P[17]). Repeatedly cycle through the key bits until the entire - * P-array has been XOR-ed with the key bits - */ - int keyLength = key.length; - int keyIndex = 0; - - for (int i = 0; i < P_SZ; i++) { - // get the 32 bits of the key, in 4 * 8 bit chunks - int data = 0x0000000; - - for (int j = 0; j < 4; j++) { - // create a 32 bit block - data = (data << 8) | (key[keyIndex++] & 0xff); - - // wrap when we get to the end of the key - if (keyIndex >= keyLength) { - keyIndex = 0; - } - } - - // XOR the newly created 32 bit chunk onto the P-array - P[i] ^= data; - } - - /* - * (3) Encrypt the all-zero string with the Blowfish algorithm, using - * the subkeys described in (1) and (2) - * - * (4) Replace P1 and P2 with the output of step (3) - * - * (5) Encrypt the output of step(3) using the Blowfish algorithm, with - * the modified subkeys. - * - * (6) Replace P3 and P4 with the output of step (5) - * - * (7) Continue the process, replacing all elements of the P-array and - * then all four S-boxes in order, with the output of the continuously - * changing Blowfish algorithm - */ - processTable(0, 0, P); - processTable(P[P_SZ - 2], P[P_SZ - 1], S0); - processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1); - processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2); - processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3); - } - - /** - * Encrypt the given input starting at the given offset and place the result - * in the provided buffer starting at the given offset. The input will be an - * exact multiple of our blocksize. - */ - private void encryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) { - int xl = BytesTo32bits(src, srcIndex); - int xr = BytesTo32bits(src, srcIndex + 4); - xl ^= P[0]; - - for (int i = 1; i < ROUNDS; i += 2) { - xr ^= F(xl) ^ P[i]; - xl ^= F(xr) ^ P[i + 1]; - } - - xr ^= P[ROUNDS + 1]; - Bits32ToBytes(xr, dst, dstIndex); - Bits32ToBytes(xl, dst, dstIndex + 4); - } - - /** - * Decrypt the given input starting at the given offset and place the result - * in the provided buffer starting at the given offset. The input will be an - * exact multiple of our blocksize. - */ - private void decryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) { - int xl = BytesTo32bits(src, srcIndex); - int xr = BytesTo32bits(src, srcIndex + 4); - xl ^= P[ROUNDS + 1]; - - for (int i = ROUNDS; i > 0; i -= 2) { - xr ^= F(xl) ^ P[i]; - xl ^= F(xr) ^ P[i - 1]; - } - - xr ^= P[0]; - Bits32ToBytes(xr, dst, dstIndex); - Bits32ToBytes(xl, dst, dstIndex + 4); - } - - private int BytesTo32bits(byte[] b, int i) { - return ((b[i] & 0xff) << 24) | ((b[i + 1] & 0xff) << 16) | ((b[i + 2] & 0xff) << 8) | ((b[i + 3] & 0xff)); - } - - private void Bits32ToBytes(int in, byte[] b, int offset) { - b[offset + 3] = (byte) in; - b[offset + 2] = (byte)(in >> 8); - b[offset + 1] = (byte)(in >> 16); - b[offset] = (byte)(in >> 24); - } - -}
--- a/src/ch/ethz/ssh2/crypto/cipher/CBCMode.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.cipher; - -/** - * CBCMode. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class CBCMode implements BlockCipher { - BlockCipher tc; - int blockSize; - boolean doEncrypt; - - byte[] cbc_vector; - byte[] tmp_vector; - - public void init(boolean forEncryption, byte[] key) { - } - - public CBCMode(BlockCipher tc, byte[] iv, boolean doEncrypt) - throws IllegalArgumentException { - this.tc = tc; - this.blockSize = tc.getBlockSize(); - this.doEncrypt = doEncrypt; - - if (this.blockSize != iv.length) - throw new IllegalArgumentException("IV must be " + blockSize - + " bytes long! (currently " + iv.length + ")"); - - this.cbc_vector = new byte[blockSize]; - this.tmp_vector = new byte[blockSize]; - System.arraycopy(iv, 0, cbc_vector, 0, blockSize); - } - - public int getBlockSize() { - return blockSize; - } - - private void encryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { - for (int i = 0; i < blockSize; i++) - cbc_vector[i] ^= src[srcoff + i]; - - tc.transformBlock(cbc_vector, 0, dst, dstoff); - System.arraycopy(dst, dstoff, cbc_vector, 0, blockSize); - } - - private void decryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { - /* Assume the worst, src and dst are overlapping... */ - System.arraycopy(src, srcoff, tmp_vector, 0, blockSize); - tc.transformBlock(src, srcoff, dst, dstoff); - - for (int i = 0; i < blockSize; i++) - dst[dstoff + i] ^= cbc_vector[i]; - - /* ...that is why we need a tmp buffer. */ - byte[] swap = cbc_vector; - cbc_vector = tmp_vector; - tmp_vector = swap; - } - - public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { - if (doEncrypt) - encryptBlock(src, srcoff, dst, dstoff); - else - decryptBlock(src, srcoff, dst, dstoff); - } -}
--- a/src/ch/ethz/ssh2/crypto/cipher/CTRMode.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.cipher; - -/** - * This is CTR mode as described in draft-ietf-secsh-newmodes-XY.txt - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class CTRMode implements BlockCipher { - byte[] X; - byte[] Xenc; - - BlockCipher bc; - int blockSize; - boolean doEncrypt; - - int count = 0; - - public void init(boolean forEncryption, byte[] key) { - } - - public CTRMode(BlockCipher tc, byte[] iv, boolean doEnc) throws IllegalArgumentException { - bc = tc; - blockSize = bc.getBlockSize(); - doEncrypt = doEnc; - - if (blockSize != iv.length) - throw new IllegalArgumentException("IV must be " + blockSize + " bytes long! (currently " + iv.length + ")"); - - X = new byte[blockSize]; - Xenc = new byte[blockSize]; - System.arraycopy(iv, 0, X, 0, blockSize); - } - - public final int getBlockSize() { - return blockSize; - } - - public final void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { - bc.transformBlock(X, 0, Xenc, 0); - - for (int i = 0; i < blockSize; i++) { - dst[dstoff + i] = (byte)(src[srcoff + i] ^ Xenc[i]); - } - - for (int i = (blockSize - 1); i >= 0; i--) { - X[i]++; - - if (X[i] != 0) - break; - } - } -}
--- a/src/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.cipher; - -import java.io.IOException; -import java.io.InputStream; - -/** - * CipherInputStream. - * - * @author Christian Plattner - * @version $Id: CipherInputStream.java 11 2011-05-27 14:14:06Z dkocher@sudo.ch $ - */ -public class CipherInputStream { - BlockCipher currentCipher; - InputStream bi; - byte[] buffer; - byte[] enc; - int blockSize; - int pos; - - /* - * We cannot use java.io.BufferedInputStream, since that is not available in - * J2ME. Everything could be improved alot here. - */ - - private static final int BUFF_SIZE = 8192; - byte[] input_buffer = new byte[BUFF_SIZE]; - int input_buffer_pos = 0; - int input_buffer_size = 0; - - public CipherInputStream(BlockCipher tc, InputStream bi) { - this.bi = bi; - changeCipher(tc); - } - - private int fill_buffer() throws IOException { - input_buffer_pos = 0; - input_buffer_size = 0; - input_buffer_size = bi.read(input_buffer, 0, BUFF_SIZE); - return input_buffer_size; - } - - private int internal_read(byte[] b, int off, int len) throws IOException { - if (input_buffer_size < 0) { - return -1; - } - - if (input_buffer_pos >= input_buffer_size) { - if (fill_buffer() <= 0) { - return -1; - } - } - - int avail = input_buffer_size - input_buffer_pos; - int thiscopy = (len > avail) ? avail : len; - System.arraycopy(input_buffer, input_buffer_pos, b, off, thiscopy); - input_buffer_pos += thiscopy; - return thiscopy; - } - - public void changeCipher(BlockCipher bc) { - this.currentCipher = bc; - blockSize = bc.getBlockSize(); - buffer = new byte[blockSize]; - enc = new byte[blockSize]; - pos = blockSize; - } - - private void getBlock() throws IOException { - int n = 0; - - while (n < blockSize) { - int len = internal_read(enc, n, blockSize - n); - - if (len < 0) { - throw new IOException("Cannot read full block, EOF reached."); - } - - n += len; - } - - try { - currentCipher.transformBlock(enc, 0, buffer, 0); - } - catch (Exception e) { - throw new IOException("Error while decrypting block."); - } - - pos = 0; - } - - public int read(byte[] dst) throws IOException { - return read(dst, 0, dst.length); - } - - public int read(byte[] dst, int off, int len) throws IOException { - int count = 0; - - while (len > 0) { - if (pos >= blockSize) { - getBlock(); - } - - int avail = blockSize - pos; - int copy = Math.min(avail, len); - System.arraycopy(buffer, pos, dst, off, copy); - pos += copy; - off += copy; - len -= copy; - count += copy; - } - - return count; - } - - public int read() throws IOException { - if (pos >= blockSize) { - getBlock(); - } - - return buffer[pos++] & 0xff; - } - - public int readPlain(byte[] b, int off, int len) throws IOException { - if (pos != blockSize) { - throw new IOException("Cannot read plain since crypto buffer is not aligned."); - } - - int n = 0; - - while (n < len) { - int cnt = internal_read(b, off + n, len - n); - - if (cnt < 0) { - throw new IOException("Cannot fill buffer, EOF reached."); - } - - n += cnt; - } - - return n; - } -}
--- a/src/ch/ethz/ssh2/crypto/cipher/CipherOutputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.cipher; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * CipherOutputStream. - * - * @author Christian Plattner - * @version $Id: CipherOutputStream.java 85 2014-04-07 14:05:09Z dkocher@sudo.ch $ - */ -public class CipherOutputStream { - BlockCipher currentCipher; - OutputStream bo; - byte[] buffer; - byte[] enc; - int blockSize; - int pos; - - /* - * We cannot use java.io.BufferedOutputStream, since that is not available - * in J2ME. Everything could be improved here alot. - */ - - private static final int BUFF_SIZE = 8192; - byte[] out_buffer = new byte[BUFF_SIZE]; - int out_buffer_pos = 0; - - public CipherOutputStream(BlockCipher tc, OutputStream bo) { - this.bo = bo; - changeCipher(tc); - } - - private void internal_write(byte[] src, int off, int len) throws IOException { - while (len > 0) { - int space = BUFF_SIZE - out_buffer_pos; - int copy = (len > space) ? space : len; - System.arraycopy(src, off, out_buffer, out_buffer_pos, copy); - off += copy; - out_buffer_pos += copy; - len -= copy; - - if (out_buffer_pos >= BUFF_SIZE) { - bo.write(out_buffer, 0, BUFF_SIZE); - out_buffer_pos = 0; - } - } - } - - private void internal_write(int b) throws IOException { - out_buffer[out_buffer_pos++] = (byte) b; - - if (out_buffer_pos >= BUFF_SIZE) { - bo.write(out_buffer, 0, BUFF_SIZE); - out_buffer_pos = 0; - } - } - - public void flush() throws IOException { - if (pos != 0) { - throw new IOException("FATAL: cannot flush since crypto buffer is not aligned."); - } - - if (out_buffer_pos > 0) { - bo.write(out_buffer, 0, out_buffer_pos); - out_buffer_pos = 0; - } - - bo.flush(); - } - - public void changeCipher(BlockCipher bc) { - this.currentCipher = bc; - blockSize = bc.getBlockSize(); - buffer = new byte[blockSize]; - enc = new byte[blockSize]; - pos = 0; - } - - private void writeBlock() throws IOException { - try { - currentCipher.transformBlock(buffer, 0, enc, 0); - } - catch (Exception e) { - throw new IOException("Error while decrypting block.", e); - } - - internal_write(enc, 0, blockSize); - pos = 0; - } - - public void write(byte[] src, int off, int len) throws IOException { - while (len > 0) { - int avail = blockSize - pos; - int copy = Math.min(avail, len); - System.arraycopy(src, off, buffer, pos, copy); - pos += copy; - off += copy; - len -= copy; - - if (pos >= blockSize) { - writeBlock(); - } - } - } - - public void write(int b) throws IOException { - buffer[pos++] = (byte) b; - - if (pos >= blockSize) { - writeBlock(); - } - } - - public void writePlain(int b) throws IOException { - if (pos != 0) { - throw new IOException("Cannot write plain since crypto buffer is not aligned."); - } - - internal_write(b); - } - - public void writePlain(byte[] b, int off, int len) throws IOException { - if (pos != 0) { - throw new IOException("Cannot write plain since crypto buffer is not aligned."); - } - - internal_write(b, off, len); - } -}
--- a/src/ch/ethz/ssh2/crypto/cipher/DES.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,352 +0,0 @@ -package ch.ethz.ssh2.crypto.cipher; - -/* - This file is based on the 3DES implementation from the Bouncy Castle Crypto package. - Their licence file states the following: - - Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle - (http://www.bouncycastle.org) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -/** - * DES. - * - * @author See comments in the source file - * @version 2.50, 03/15/10 - * - */ -public class DES implements BlockCipher { - private int[] workingKey = null; - - /** - * standard constructor. - */ - public DES() { - } - - /** - * initialise a DES cipher. - * - * @param encrypting - * whether or not we are for encryption. - * @param key - * the parameters required to set up the cipher. - * @exception IllegalArgumentException - * if the params argument is inappropriate. - */ - public void init(boolean encrypting, byte[] key) { - this.workingKey = generateWorkingKey(encrypting, key, 0); - } - - public String getAlgorithmName() { - return "DES"; - } - - public int getBlockSize() { - return 8; - } - - public void transformBlock(byte[] in, int inOff, byte[] out, int outOff) { - if (workingKey == null) { - throw new IllegalStateException("DES engine not initialised!"); - } - - desFunc(workingKey, in, inOff, out, outOff); - } - - public void reset() { - } - - /** - * what follows is mainly taken from "Applied Cryptography", by Bruce - * Schneier, however it also bears great resemblance to Richard - * Outerbridge's D3DES... - */ - - static short[] Df_Key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, - 0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 - }; - - static short[] bytebit = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; - - static int[] bigbyte = { 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000, - 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 - }; - - /* - * Use the key schedule specified in the Standard (ANSI X3.92-1981). - */ - - static byte[] pc1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, - 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, - 4, 27, 19, 11, 3 - }; - - static byte[] totrot = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 }; - - static byte[] pc2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, - 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 - }; - - static int[] SP1 = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, - 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, - 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, - 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, - 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, - 0x00010400, 0x00000000, 0x01010004 - }; - - static int[] SP2 = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, - 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, - 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, - 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, - 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, - 0x80100020, 0x80108020, 0x00108000 - }; - - static int[] SP3 = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, - 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, - 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, - 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, - 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, - 0x00000008, 0x08020008, 0x00020200 - }; - - static int[] SP4 = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, - 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, - 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, - 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, - 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, - 0x00800000, 0x00002000, 0x00802080 - }; - - static int[] SP5 = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, - 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, - 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, - 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, - 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, - 0x40080000, 0x02080100, 0x40000100 - }; - - static int[] SP6 = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, - 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, - 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, - 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, - 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, - 0x20000000, 0x00400010, 0x20004010 - }; - - static int[] SP7 = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, - 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, - 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, - 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, - 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, - 0x04000800, 0x00000800, 0x00200002 - }; - - static int[] SP8 = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, - 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, - 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, - 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, - 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, - 0x00040040, 0x10000000, 0x10041000 - }; - - /** - * generate an integer based working key based on our secret key and what we - * processing we are planning to do. - * - * Acknowledgements for this routine go to James Gillogly & Phil Karn. - * (whoever, and wherever they are!). - */ - protected int[] generateWorkingKey(boolean encrypting, byte[] key, int off) { - int[] newKey = new int[32]; - boolean[] pc1m = new boolean[56], pcr = new boolean[56]; - - for (int j = 0; j < 56; j++) { - int l = pc1[j]; - pc1m[j] = ((key[off + (l >>> 3)] & bytebit[l & 07]) != 0); - } - - for (int i = 0; i < 16; i++) { - int l, m, n; - - if (encrypting) { - m = i << 1; - } - else { - m = (15 - i) << 1; - } - - n = m + 1; - newKey[m] = newKey[n] = 0; - - for (int j = 0; j < 28; j++) { - l = j + totrot[i]; - - if (l < 28) { - pcr[j] = pc1m[l]; - } - else { - pcr[j] = pc1m[l - 28]; - } - } - - for (int j = 28; j < 56; j++) { - l = j + totrot[i]; - - if (l < 56) { - pcr[j] = pc1m[l]; - } - else { - pcr[j] = pc1m[l - 28]; - } - } - - for (int j = 0; j < 24; j++) { - if (pcr[pc2[j]]) { - newKey[m] |= bigbyte[j]; - } - - if (pcr[pc2[j + 24]]) { - newKey[n] |= bigbyte[j]; - } - } - } - - // - // store the processed key - // - for (int i = 0; i != 32; i += 2) { - int i1, i2; - i1 = newKey[i]; - i2 = newKey[i + 1]; - newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10) | ((i2 & 0x00fc0000) >>> 10) - | ((i2 & 0x00000fc0) >>> 6); - newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16) | ((i2 & 0x0003f000) >>> 4) - | (i2 & 0x0000003f); - } - - return newKey; - } - - /** - * the DES engine. - */ - protected void desFunc(int[] wKey, byte[] in, int inOff, byte[] out, int outOff) { - int work, right, left; - left = (in[inOff + 0] & 0xff) << 24; - left |= (in[inOff + 1] & 0xff) << 16; - left |= (in[inOff + 2] & 0xff) << 8; - left |= (in[inOff + 3] & 0xff); - right = (in[inOff + 4] & 0xff) << 24; - right |= (in[inOff + 5] & 0xff) << 16; - right |= (in[inOff + 6] & 0xff) << 8; - right |= (in[inOff + 7] & 0xff); - work = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= work; - left ^= (work << 4); - work = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= work; - left ^= (work << 16); - work = ((right >>> 2) ^ left) & 0x33333333; - left ^= work; - right ^= (work << 2); - work = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= work; - right ^= (work << 8); - right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff; - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff; - - for (int round = 0; round < 8; round++) { - int fval; - work = (right << 28) | (right >>> 4); - work ^= wKey[round * 4 + 0]; - fval = SP7[work & 0x3f]; - fval |= SP5[(work >>> 8) & 0x3f]; - fval |= SP3[(work >>> 16) & 0x3f]; - fval |= SP1[(work >>> 24) & 0x3f]; - work = right ^ wKey[round * 4 + 1]; - fval |= SP8[work & 0x3f]; - fval |= SP6[(work >>> 8) & 0x3f]; - fval |= SP4[(work >>> 16) & 0x3f]; - fval |= SP2[(work >>> 24) & 0x3f]; - left ^= fval; - work = (left << 28) | (left >>> 4); - work ^= wKey[round * 4 + 2]; - fval = SP7[work & 0x3f]; - fval |= SP5[(work >>> 8) & 0x3f]; - fval |= SP3[(work >>> 16) & 0x3f]; - fval |= SP1[(work >>> 24) & 0x3f]; - work = left ^ wKey[round * 4 + 3]; - fval |= SP8[work & 0x3f]; - fval |= SP6[(work >>> 8) & 0x3f]; - fval |= SP4[(work >>> 16) & 0x3f]; - fval |= SP2[(work >>> 24) & 0x3f]; - right ^= fval; - } - - right = (right << 31) | (right >>> 1); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left << 31) | (left >>> 1); - work = ((left >>> 8) ^ right) & 0x00ff00ff; - right ^= work; - left ^= (work << 8); - work = ((left >>> 2) ^ right) & 0x33333333; - right ^= work; - left ^= (work << 2); - work = ((right >>> 16) ^ left) & 0x0000ffff; - left ^= work; - right ^= (work << 16); - work = ((right >>> 4) ^ left) & 0x0f0f0f0f; - left ^= work; - right ^= (work << 4); - out[outOff + 0] = (byte)((right >>> 24) & 0xff); - out[outOff + 1] = (byte)((right >>> 16) & 0xff); - out[outOff + 2] = (byte)((right >>> 8) & 0xff); - out[outOff + 3] = (byte)(right & 0xff); - out[outOff + 4] = (byte)((left >>> 24) & 0xff); - out[outOff + 5] = (byte)((left >>> 16) & 0xff); - out[outOff + 6] = (byte)((left >>> 8) & 0xff); - out[outOff + 7] = (byte)(left & 0xff); - } -}
--- a/src/ch/ethz/ssh2/crypto/cipher/DESede.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -package ch.ethz.ssh2.crypto.cipher; - -/* - This file was shamelessly taken (and modified) from the Bouncy Castle Crypto package. - Their licence file states the following: - - Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle - (http://www.bouncycastle.org) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ - -/** - * DESede. - * - * @author See comments in the source file - * @version 2.50, 03/15/10 - * - */ -public class DESede extends DES { - private int[] key1 = null; - private int[] key2 = null; - private int[] key3 = null; - - private boolean encrypt; - - /** - * standard constructor. - */ - public DESede() { - } - - /** - * initialise a DES cipher. - * - * @param encrypting - * whether or not we are for encryption. - * @param key - * the parameters required to set up the cipher. - * @exception IllegalArgumentException - * if the params argument is inappropriate. - */ - @Override - public void init(boolean encrypting, byte[] key) { - key1 = generateWorkingKey(encrypting, key, 0); - key2 = generateWorkingKey(!encrypting, key, 8); - key3 = generateWorkingKey(encrypting, key, 16); - encrypt = encrypting; - } - - @Override - public String getAlgorithmName() { - return "DESede"; - } - - @Override - public int getBlockSize() { - return 8; - } - - @Override - public void transformBlock(byte[] in, int inOff, byte[] out, int outOff) { - if (key1 == null) { - throw new IllegalStateException("DESede engine not initialised!"); - } - - if (encrypt) { - desFunc(key1, in, inOff, out, outOff); - desFunc(key2, out, outOff, out, outOff); - desFunc(key3, out, outOff, out, outOff); - } - else { - desFunc(key3, in, inOff, out, outOff); - desFunc(key2, out, outOff, out, outOff); - desFunc(key1, out, outOff, out, outOff); - } - } - - @Override - public void reset() { - } -}
--- a/src/ch/ethz/ssh2/crypto/cipher/NullCipher.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.cipher; - -/** - * NullCipher. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class NullCipher implements BlockCipher { - private int blockSize = 8; - - public NullCipher() { - } - - public NullCipher(int blockSize) { - this.blockSize = blockSize; - } - - public void init(boolean forEncryption, byte[] key) { - } - - public int getBlockSize() { - return blockSize; - } - - public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { - System.arraycopy(src, srcoff, dst, dstoff, blockSize); - } -}
--- a/src/ch/ethz/ssh2/crypto/dh/DhExchange.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -/** - * - */ -package ch.ethz.ssh2.crypto.dh; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.spec.InvalidKeySpecException; - -import javax.crypto.KeyAgreement; -import javax.crypto.interfaces.DHPrivateKey; -import javax.crypto.interfaces.DHPublicKey; -import javax.crypto.spec.DHParameterSpec; -import javax.crypto.spec.DHPublicKeySpec; - -/** - * @author kenny - * - */ -public class DhExchange extends GenericDhExchange { - - /* Given by the standard */ - - private static final BigInteger P1 = new BigInteger( - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" - + "FFFFFFFFFFFFFFFF", 16); - - private static final BigInteger P14 = new BigInteger( - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16); - - private static final BigInteger G = BigInteger.valueOf(2); - - /* Client public and private */ - - private DHPrivateKey clientPrivate; - private DHPublicKey clientPublic; - - /* Server public */ - - private DHPublicKey serverPublic; - private byte[] f; - - @Override - public void init(String name) throws IOException { - final DHParameterSpec spec; - - if ("diffie-hellman-group1-sha1".equals(name)) { - spec = new DHParameterSpec(P1, G); - } - else if ("diffie-hellman-group14-sha1".equals(name)) { - spec = new DHParameterSpec(P14, G); - } - else { - throw new IllegalArgumentException("Unknown DH group " + name); - } - - try { - KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH"); - kpg.initialize(spec); - KeyPair pair = kpg.generateKeyPair(); - clientPrivate = (DHPrivateKey) pair.getPrivate(); - clientPublic = (DHPublicKey) pair.getPublic(); - } - catch (NoSuchAlgorithmException e) { - throw(IOException) new IOException("No DH keypair generator").initCause(e); - } - catch (InvalidAlgorithmParameterException e) { - throw(IOException) new IOException("Invalid DH parameters").initCause(e); - } - } - - @Override - public byte[] getE() { - if (clientPublic == null) - throw new IllegalStateException("DhExchange not initialized!"); - - return clientPublic.getY().toByteArray(); - } - - @Override - protected byte[] getServerE() { - if (serverPublic == null) - throw new IllegalStateException("DhExchange not initialized!"); - - return serverPublic.getY().toByteArray(); - } - - @Override - public byte[] getF() { - return f; - } - - @Override - public void setF(byte[] f) throws IOException { - if (clientPublic == null) - throw new IllegalStateException("DhExchange not initialized!"); - - final KeyAgreement ka; - - try { - KeyFactory kf = KeyFactory.getInstance("DH"); - DHParameterSpec params = clientPublic.getParams(); - this.f = f; - this.serverPublic = (DHPublicKey) kf.generatePublic(new DHPublicKeySpec( - new BigInteger(f), params.getP(), params.getG())); - ka = KeyAgreement.getInstance("DH"); - ka.init(clientPrivate); - ka.doPhase(serverPublic, true); - } - catch (NoSuchAlgorithmException e) { - throw(IOException) new IOException("No DH key agreement method").initCause(e); - } - catch (InvalidKeyException e) { - throw(IOException) new IOException("Invalid DH key").initCause(e); - } - catch (InvalidKeySpecException e) { - throw(IOException) new IOException("Invalid DH key").initCause(e); - } - - sharedSecret = new BigInteger(ka.generateSecret()); - } - - @Override - public String getHashAlgo() { - return "SHA1"; - } -}
--- a/src/ch/ethz/ssh2/crypto/dh/DhGroupExchange.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ - -package ch.ethz.ssh2.crypto.dh; - -import java.math.BigInteger; -import java.security.SecureRandom; -import java.io.IOException; - -import ch.ethz.ssh2.DHGexParameters; -import ch.ethz.ssh2.crypto.digest.HashForSSH2Types; - - -/** - * DhGroupExchange. - * - * @author Christian Plattner, plattner@trilead.com - * @version $Id: DhGroupExchange.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $ - */ -public class DhGroupExchange { - /* Given by the standard */ - - private BigInteger p; - private BigInteger g; - - /* Client public and private */ - - private BigInteger e; - private BigInteger x; - - /* Server public */ - - private BigInteger f; - - /* Shared secret */ - - private BigInteger k; - - public DhGroupExchange(BigInteger p, BigInteger g) { - this.p = p; - this.g = g; - } - - public void init(SecureRandom rnd) { - k = null; - x = new BigInteger(p.bitLength() - 1, rnd); - e = g.modPow(x, p); - } - - /** - * @return Returns the e. - */ - public BigInteger getE() { - if (e == null) - throw new IllegalStateException("Not initialized!"); - - return e; - } - - /** - * @return Returns the shared secret k. - */ - public BigInteger getK() { - if (k == null) - throw new IllegalStateException("Shared secret not yet known, need f first!"); - - return k; - } - - /** - * Sets f and calculates the shared secret. - */ - public void setF(BigInteger f) { - if (e == null) - throw new IllegalStateException("Not initialized!"); - - BigInteger zero = BigInteger.valueOf(0); - - if (zero.compareTo(f) >= 0 || p.compareTo(f) <= 0) - throw new IllegalArgumentException("Invalid f specified!"); - - this.f = f; - this.k = f.modPow(x, p); - } - - public byte[] calculateH(String hashAlgo, byte[] clientversion, byte[] serverversion, - byte[] clientKexPayload, byte[] serverKexPayload, byte[] hostKey, DHGexParameters para) throws IOException { - HashForSSH2Types hash = new HashForSSH2Types(hashAlgo); - hash.updateByteString(clientversion); - hash.updateByteString(serverversion); - hash.updateByteString(clientKexPayload); - hash.updateByteString(serverKexPayload); - hash.updateByteString(hostKey); - - if (para.getMin_group_len() > 0) - hash.updateUINT32(para.getMin_group_len()); - - hash.updateUINT32(para.getPref_group_len()); - - if (para.getMax_group_len() > 0) - hash.updateUINT32(para.getMax_group_len()); - - hash.updateBigInt(p); - hash.updateBigInt(g); - hash.updateBigInt(e); - hash.updateBigInt(f); - hash.updateBigInt(k); - return hash.getDigest(); - } -}
--- a/src/ch/ethz/ssh2/crypto/dh/EcDhExchange.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/** - * - */ -package ch.ethz.ssh2.crypto.dh; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.InvalidKeySpecException; - -import javax.crypto.KeyAgreement; - -import ch.ethz.ssh2.signature.ECDSASHA2Verify; - -/** - * @author kenny - * - */ -public class EcDhExchange extends GenericDhExchange { - - /* Client public and private */ - - private ECPrivateKey clientPrivate; - private ECPublicKey clientPublic; - - /* Server public */ - - private ECPublicKey serverPublic; - private byte[] f; - - @Override - public void init(String name) throws IOException { - final ECParameterSpec spec; - - if ("ecdh-sha2-nistp256".equals(name)) { - spec = ECDSASHA2Verify.EllipticCurves.nistp256; - } - else if ("ecdh-sha2-nistp384".equals(name)) { - spec = ECDSASHA2Verify.EllipticCurves.nistp384; - } - else if ("ecdh-sha2-nistp521".equals(name)) { - spec = ECDSASHA2Verify.EllipticCurves.nistp521; - } - else { - throw new IllegalArgumentException("Unknown EC curve " + name); - } - - KeyPairGenerator kpg; - - try { - kpg = KeyPairGenerator.getInstance("EC"); - kpg.initialize(spec); - KeyPair pair = kpg.generateKeyPair(); - clientPrivate = (ECPrivateKey) pair.getPrivate(); - clientPublic = (ECPublicKey) pair.getPublic(); - } - catch (NoSuchAlgorithmException e) { - throw(IOException) new IOException("No DH keypair generator").initCause(e); - } - catch (InvalidAlgorithmParameterException e) { - throw(IOException) new IOException("Invalid DH parameters").initCause(e); - } - } - - @Override - public byte[] getE() { - return ECDSASHA2Verify.encodeECPoint(clientPublic.getW(), clientPublic.getParams() - .getCurve()); - } - - @Override - protected byte[] getServerE() { - return ECDSASHA2Verify.encodeECPoint(serverPublic.getW(), serverPublic.getParams() - .getCurve()); - } - - @Override - public byte[] getF() { - return f; - } - - @Override - public void setF(byte[] f) throws IOException { - if (clientPublic == null) - throw new IllegalStateException("DhDsaExchange not initialized!"); - - final KeyAgreement ka; - - try { - KeyFactory kf = KeyFactory.getInstance("EC"); - ECParameterSpec params = clientPublic.getParams(); - ECPoint serverPoint = ECDSASHA2Verify.decodeECPoint(f, params.getCurve()); - this.f = f; - this.serverPublic = (ECPublicKey) kf.generatePublic(new ECPublicKeySpec(serverPoint, - params)); - ka = KeyAgreement.getInstance("ECDH"); - ka.init(clientPrivate); - ka.doPhase(serverPublic, true); - } - catch (NoSuchAlgorithmException e) { - throw(IOException) new IOException("No ECDH key agreement method").initCause(e); - } - catch (InvalidKeyException e) { - throw(IOException) new IOException("Invalid ECDH key").initCause(e); - } - catch (InvalidKeySpecException e) { - throw(IOException) new IOException("Invalid ECDH key").initCause(e); - } - - sharedSecret = new BigInteger(ka.generateSecret()); - } - - @Override - public String getHashAlgo() { - return ECDSASHA2Verify.getDigestAlgorithmForParams(clientPublic.getParams()); - } -}
--- a/src/ch/ethz/ssh2/crypto/dh/GenericDhExchange.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ - -package ch.ethz.ssh2.crypto.dh; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; - -import ch.ethz.ssh2.crypto.digest.HashForSSH2Types; -import ch.ethz.ssh2.log.Logger; - - -/** - * DhExchange. - * - * @author Christian Plattner, plattner@trilead.com - * @version $Id: DhExchange.java,v 1.2 2008/04/01 12:38:09 cplattne Exp $ - */ -public abstract class GenericDhExchange { - private static final Logger log = Logger.getLogger(GenericDhExchange.class); - - /* Shared secret */ - - BigInteger sharedSecret; - - protected GenericDhExchange() { - } - - public static GenericDhExchange getInstance(String algo) { - if (algo.startsWith("ecdh-sha2-")) { - return new EcDhExchange(); - } - else { - return new DhExchange(); - } - } - - public abstract void init(String name) throws IOException; - - /** - * @return Returns the e (public value) - * @throws IllegalStateException - */ - public abstract byte[] getE(); - - public void setE(BigInteger e) throws IOException { - throw new IOException(); - } - - /** - * @return Returns the server's e (public value) - * @throws IllegalStateException - */ - protected abstract byte[] getServerE(); - - /** - * @return Returns the shared secret k. - * @throws IllegalStateException - */ - public BigInteger getK() { - if (sharedSecret == null) - throw new IllegalStateException("Shared secret not yet known, need f first!"); - - return sharedSecret; - } - - /** - * @param f - */ - public void setF(BigInteger f) throws IOException { - setF(f.toByteArray()); - } - - public abstract byte[] getF(); - - public abstract void setF(byte[] f) throws IOException; - - public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload, - byte[] serverKexPayload, byte[] hostKey) throws UnsupportedEncodingException, IOException { - HashForSSH2Types hash = new HashForSSH2Types(getHashAlgo()); - log.debug("Client: '" + new String(clientversion, "ISO-8859-1") + "'"); - log.debug("Server: '" + new String(serverversion, "ISO-8859-1") + "'"); - hash.updateByteString(clientversion); - hash.updateByteString(serverversion); - hash.updateByteString(clientKexPayload); - hash.updateByteString(serverKexPayload); - hash.updateByteString(hostKey); - hash.updateByteString(getE()); - hash.updateByteString(getServerE()); - hash.updateBigInt(sharedSecret); - return hash.getDigest(); - } - - public abstract String getHashAlgo(); -}
--- a/src/ch/ethz/ssh2/crypto/digest/Digest.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.digest; - -import java.security.DigestException; - -/** - * Digest. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public interface Digest { - public int getDigestLength(); - - public void update(byte b); - - public void update(byte[] b); - - public void update(byte b[], int off, int len); - - public void reset(); - - public void digest(byte[] out) throws DigestException; - - public void digest(byte[] out, int off) throws DigestException; -}
--- a/src/ch/ethz/ssh2/crypto/digest/HMAC.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.digest; - -import java.security.DigestException; - -/** - * HMAC. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class HMAC implements Digest { - Digest md; - byte[] k_xor_ipad; - byte[] k_xor_opad; - - byte[] tmp; - - int size; - - public HMAC(Digest md, byte[] key, int size) throws DigestException { - this.md = md; - this.size = size; - tmp = new byte[md.getDigestLength()]; - final int BLOCKSIZE = 64; - k_xor_ipad = new byte[BLOCKSIZE]; - k_xor_opad = new byte[BLOCKSIZE]; - - if (key.length > BLOCKSIZE) { - md.reset(); - md.update(key); - md.digest(tmp); - key = tmp; - } - - System.arraycopy(key, 0, k_xor_ipad, 0, key.length); - System.arraycopy(key, 0, k_xor_opad, 0, key.length); - - for (int i = 0; i < BLOCKSIZE; i++) { - k_xor_ipad[i] ^= 0x36; - k_xor_opad[i] ^= 0x5C; - } - - md.update(k_xor_ipad); - } - - public final int getDigestLength() { - return size; - } - - public final void update(byte b) { - md.update(b); - } - - public final void update(byte[] b) { - md.update(b); - } - - public final void update(byte[] b, int off, int len) { - md.update(b, off, len); - } - - public final void reset() { - md.reset(); - md.update(k_xor_ipad); - } - - public final void digest(byte[] out) throws DigestException { - digest(out, 0); - } - - public final void digest(byte[] out, int off) throws DigestException { - md.digest(tmp); - md.update(k_xor_opad); - md.update(tmp); - md.digest(tmp); - System.arraycopy(tmp, 0, out, off, size); - md.update(k_xor_ipad); - } -}
--- a/src/ch/ethz/ssh2/crypto/digest/HashForSSH2Types.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.digest; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.DigestException; - -/** - * HashForSSH2Types. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class HashForSSH2Types { - Digest md; - - public HashForSSH2Types(Digest md) { - this.md = md; - } - - public HashForSSH2Types(String type) { - if (type.equals("SHA1")) { - md = new SHA1(); - } - else if (type.equals("SHA2")) { - md = new SHA256(); - } - else if (type.equals("MD5")) { - md = new MD5(); - } - else { - throw new IllegalArgumentException(String.format("Unknown algorithm %s", type)); - } - } - - public void updateByte(byte b) { - md.update(b); - } - - public void updateBytes(byte[] b) { - md.update(b); - } - - public void updateUINT32(int v) { - md.update((byte)(v >> 24)); - md.update((byte)(v >> 16)); - md.update((byte)(v >> 8)); - md.update((byte)(v)); - } - - public void updateByteString(byte[] b) { - updateUINT32(b.length); - updateBytes(b); - } - - public void updateBigInt(BigInteger b) { - updateByteString(b.toByteArray()); - } - - public void reset() { - md.reset(); - } - - public int getDigestLength() { - return md.getDigestLength(); - } - - public byte[] getDigest() throws IOException { - byte[] tmp = new byte[md.getDigestLength()]; - getDigest(tmp); - return tmp; - } - - public void getDigest(byte[] out) throws IOException { - try { - getDigest(out, 0); - } - catch (DigestException e) { - throw new IOException(e); - } - } - - public void getDigest(byte[] out, int off) throws DigestException { - md.digest(out, off); - } -}
--- a/src/ch/ethz/ssh2/crypto/digest/MAC.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.digest; - -import java.io.IOException; -import java.security.DigestException; - -/** - * MAC. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class MAC { - private Digest mac; - private int size; - - public static String[] getMacList() { - // Higher priority (stronger) first. Added SHA-2 algorithms as in RFC 6668 - return new String[] { - // "hmac-sha2-512", // fails interop w/ centos6 - "hmac-sha2-256", - "hmac-sha1", - "hmac-sha1-96", - "hmac-md5", - "hmac-md5-96" - }; - } - - public static void checkMacList(final String[] macs) { - for (String m : macs) { - getKeyLen(m); - } - } - - public static int getKeyLen(final String type) { - if (type.equals("hmac-sha1")) { - return 20; - } - - if (type.equals("hmac-sha1-96")) { - return 20; - } - - if (type.equals("hmac-md5")) { - return 16; - } - - if (type.equals("hmac-md5-96")) { - return 16; - } - - if (type.equals("hmac-sha2-256")) { - return 32; - } - - if (type.equals("hmac-sha2-512")) { - return 64; - } - - throw new IllegalArgumentException(String.format("Unknown algorithm %s", type)); - } - - public MAC(final String type, final byte[] key) throws DigestException { - if (type.equals("hmac-sha1")) { - mac = new HMAC(new SHA1(), key, 20); - } - else if (type.equals("hmac-sha1-96")) { - mac = new HMAC(new SHA1(), key, 12); - } - else if (type.equals("hmac-md5")) { - mac = new HMAC(new MD5(), key, 16); - } - else if (type.equals("hmac-md5-96")) { - mac = new HMAC(new MD5(), key, 12); - } - else if (type.equals("hmac-sha2-256")) { - mac = new HMAC(new SHA256(), key, 32); - } - else if (type.equals("hmac-sha2-512")) { - mac = new HMAC(new SHA512(), key, 64); - } - else { - throw new IllegalArgumentException(String.format("Unknown algorithm %s", type)); - } - - size = mac.getDigestLength(); - } - - public final void initMac(final int seq) { - mac.reset(); - mac.update((byte)(seq >> 24)); - mac.update((byte)(seq >> 16)); - mac.update((byte)(seq >> 8)); - mac.update((byte)(seq)); - } - - public final void update(byte[] packetdata, int off, int len) { - mac.update(packetdata, off, len); - } - - public final void getMac(byte[] out, int off) throws IOException { - try { - mac.digest(out, off); - } - catch (DigestException e) { - throw new IOException(e); - } - } - - public final int size() { - return size; - } -}
--- a/src/ch/ethz/ssh2/crypto/digest/MD5.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.digest; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * @version $Id: MD5.java 154 2014-04-28 11:45:02Z dkocher@sudo.ch $ - */ -public final class MD5 implements Digest { - - private MessageDigest md; - - public MD5() { - try { - md = MessageDigest.getInstance("MD5"); - } - catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException(e); - } - } - - public final int getDigestLength() { - return md.getDigestLength(); - } - - public final void reset() { - md.reset(); - } - - public final void update(byte b[]) { - this.update(b, 0, b.length); - } - - public final void update(byte b[], int off, int len) { - md.update(b, off, len); - } - - public final void update(byte b) { - md.update(b); - } - - public final void digest(byte[] out) throws DigestException { - this.digest(out, 0); - } - - public final void digest(byte[] out, int off) throws DigestException { - md.digest(out, off, out.length); - } -}
--- a/src/ch/ethz/ssh2/crypto/digest/SHA1.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.digest; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * @version $Id: SHA1.java 154 2014-04-28 11:45:02Z dkocher@sudo.ch $ - */ -public final class SHA1 implements Digest { - - private MessageDigest md; - - public SHA1() { - try { - md = MessageDigest.getInstance("SHA-1"); - } - catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException(e); - } - } - - public final int getDigestLength() { - return md.getDigestLength(); - } - - public final void reset() { - md.reset(); - } - - public final void update(byte b[]) { - this.update(b, 0, b.length); - } - - public final void update(byte b[], int off, int len) { - md.update(b, off, len); - } - - public final void update(byte b) { - md.update(b); - } - - public final void digest(byte[] out) throws DigestException { - this.digest(out, 0); - } - - public final void digest(byte[] out, int off) throws DigestException { - md.digest(out, off, out.length); - } -}
--- a/src/ch/ethz/ssh2/crypto/digest/SHA256.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.digest; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * @version $Id: SHA256.java 152 2014-04-28 11:02:23Z dkocher@sudo.ch $ - */ -public final class SHA256 implements Digest { - - private MessageDigest md; - - public SHA256() { - try { - md = MessageDigest.getInstance("SHA-256"); - } - catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException(e); - } - } - - public final int getDigestLength() { - return md.getDigestLength(); - } - - public final void reset() { - md.reset(); - } - - public final void update(byte b[]) { - this.update(b, 0, b.length); - } - - public final void update(byte b[], int off, int len) { - md.update(b, off, len); - } - - public final void update(byte b) { - md.update(b); - } - - public final void digest(byte[] out) throws DigestException { - this.digest(out, 0); - } - - public final void digest(byte[] out, int off) throws DigestException { - md.digest(out, off, out.length); - } -}
--- a/src/ch/ethz/ssh2/crypto/digest/SHA512.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.crypto.digest; - -import java.security.DigestException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * @version $Id: SHA512.java 152 2014-04-28 11:02:23Z dkocher@sudo.ch $ - */ -public final class SHA512 implements Digest { - - private MessageDigest md; - - public SHA512() { - try { - md = MessageDigest.getInstance("SHA-512"); - } - catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException(e); - } - } - - public final int getDigestLength() { - return md.getDigestLength(); - } - - public final void reset() { - md.reset(); - } - - public final void update(byte b[]) { - md.update(b); - } - - public final void update(byte b[], int off, int len) { - md.update(b, off, len); - } - - public final void update(byte b) { - md.update(b); - } - - public final void digest(byte[] out) { - md.digest(out); - } - - public final void digest(byte[] out, int off) throws DigestException { - md.digest(out, off, out.length); - } -}
--- a/src/ch/ethz/ssh2/log/Logger.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2.log; - -import android.util.Log; - -public class Logger { - private static final String TAG = "ConnectBot.ssh"; - public static boolean enabled = false; - - public static Logger getLogger(Class<?> x) { - return new Logger(); - } - - public Logger() { - } - - public final boolean isEnabled() { - return enabled; - } - - public boolean isDebugEnabled() { - return enabled; - } - - public void debug(String message) { - if (enabled) Log.d(TAG, message); - } - - public boolean isInfoEnabled() { - return enabled; - } - - public void info(String message) { - if (enabled) Log.i(TAG, message); - } - - public boolean isWarningEnabled() { - return enabled; - } - - public void warning(String message) { - if (enabled) Log.w(TAG, message); - } -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/packets/PacketChannelAuthAgentReq.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -package ch.ethz.ssh2.packets; - -/** - * PacketGlobalAuthAgent. - * - * @author Kenny Root, kenny@the-b.org - * @version $Id$ - */ -public class PacketChannelAuthAgentReq { - byte[] payload; - - public int recipientChannelID; - - public PacketChannelAuthAgentReq(int recipientChannelID) { - this.recipientChannelID = recipientChannelID; - } - - public byte[] getPayload() { - if (payload == null) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); - tw.writeUINT32(recipientChannelID); - tw.writeString("auth-agent-req@openssh.com"); - tw.writeBoolean(true); // want reply - payload = tw.getBytes(); - } - - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketChannelFailure.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketChannelFailure.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketChannelFailure { - private final byte[] payload; - - public PacketChannelFailure(int recipientChannelID) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_FAILURE); - tw.writeUINT32(recipientChannelID); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketChannelOpenConfirmation.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketChannelOpenConfirmation.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketChannelOpenConfirmation { - - private final byte[] payload; - - private final int recipientChannelID; - private final int senderChannelID; - private final int initialWindowSize; - private final int maxPacketSize; - - public PacketChannelOpenConfirmation(int recipientChannelID, int senderChannelID, int initialWindowSize, - int maxPacketSize) { - this.recipientChannelID = recipientChannelID; - this.senderChannelID = senderChannelID; - this.initialWindowSize = initialWindowSize; - this.maxPacketSize = maxPacketSize; - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - tw.writeUINT32(recipientChannelID); - tw.writeUINT32(senderChannelID); - tw.writeUINT32(initialWindowSize); - tw.writeUINT32(maxPacketSize); - payload = tw.getBytes(); - } - - public PacketChannelOpenConfirmation(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) { - throw new PacketTypeException(packet_type); - } - - recipientChannelID = tr.readUINT32(); - senderChannelID = tr.readUINT32(); - initialWindowSize = tr.readUINT32(); - maxPacketSize = tr.readUINT32(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public int getRecipientChannelID() { - return recipientChannelID; - } - - public int getSenderChannelID() { - return senderChannelID; - } - - public int getInitialWindowSize() { - return initialWindowSize; - } - - public int getMaxPacketSize() { - return maxPacketSize; - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketChannelOpenFailure.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; - -/** - * @author Christian Plattner - * @version $Id: PacketChannelOpenFailure.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketChannelOpenFailure { - - private final byte[] payload; - - public PacketChannelOpenFailure(int recipientChannelID, int reasonCode, String description, - String languageTag) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN_FAILURE); - tw.writeUINT32(recipientChannelID); - tw.writeUINT32(reasonCode); - tw.writeString(description); - tw.writeString(languageTag); - payload = tw.getBytes(); - } - - public PacketChannelOpenFailure(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN_FAILURE) { - throw new IOException( - "This is not a SSH_MSG_CHANNEL_OPEN_FAILURE! (" - + packet_type + ")" - ); - } - - int recipientChannelID = tr.readUINT32(); - int reasonCode = tr.readUINT32(); - String description = tr.readString(); - String languageTag = tr.readString(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketChannelSuccess.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketChannelSuccess.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketChannelSuccess { - - private final byte[] payload; - - public PacketChannelSuccess(int recipientChannelID) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_SUCCESS); - tw.writeUINT32(recipientChannelID); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketChannelWindowAdjust.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; - -/** - * @author Christian Plattner - * @version $Id: PacketChannelWindowAdjust.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketChannelWindowAdjust { - - private final byte[] payload; - - public PacketChannelWindowAdjust(int recipientChannelID, int windowChange) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST); - tw.writeUINT32(recipientChannelID); - tw.writeUINT32(windowChange); - payload = tw.getBytes(); - } - - public PacketChannelWindowAdjust(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST) { - throw new IOException( - "This is not a SSH_MSG_CHANNEL_WINDOW_ADJUST! (" - + packet_type + ")" - ); - } - - int recipientChannelID = tr.readUINT32(); - int windowChange = tr.readUINT32(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketDisconnect.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketDisconnect.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketDisconnect { - - public enum Reason { - SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT, - SSH_DISCONNECT_PROTOCOL_ERROR, - SSH_DISCONNECT_KEY_EXCHANGE_FAILED, - SSH_DISCONNECT_RESERVED, - SSH_DISCONNECT_MAC_ERROR, - SSH_DISCONNECT_COMPRESSION_ERROR, - SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, - SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED, - SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE, - SSH_DISCONNECT_CONNECTION_LOST, - SSH_DISCONNECT_BY_APPLICATION, - SSH_DISCONNECT_TOO_MANY_CONNECTIONS, - SSH_DISCONNECT_AUTH_CANCELLED_BY_USER, - SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, - SSH_DISCONNECT_ILLEGAL_USER_NAME - } - - private final byte[] payload; - - private final Reason reason; - - private final String message; - - public PacketDisconnect(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_DISCONNECT) { - throw new PacketTypeException(packet_type); - } - - reason = PacketDisconnect.Reason.values()[tr.readUINT32()]; - message = tr.readString(); - String lang = tr.readString(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public PacketDisconnect(Reason reason, String desc) { - this.reason = reason; - this.message = desc; - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_DISCONNECT); - tw.writeUINT32(reason.ordinal()); - tw.writeString(desc); - tw.writeString(""); - payload = tw.getBytes(); - } - - public Reason getReason() { - return reason; - } - - public String getMessage() { - return message; - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketGlobalCancelForwardRequest.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketGlobalCancelForwardRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketGlobalCancelForwardRequest { - - private final byte[] payload; - - public PacketGlobalCancelForwardRequest(boolean wantReply, String bindAddress, int bindPort) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_GLOBAL_REQUEST); - tw.writeString("cancel-tcpip-forward"); - tw.writeBoolean(wantReply); - tw.writeString(bindAddress); - tw.writeUINT32(bindPort); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketGlobalForwardRequest.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketGlobalForwardRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketGlobalForwardRequest { - - private final byte[] payload; - - public PacketGlobalForwardRequest(boolean wantReply, String bindAddress, int bindPort) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_GLOBAL_REQUEST); - tw.writeString("tcpip-forward"); - tw.writeBoolean(wantReply); - tw.writeString(bindAddress); - tw.writeUINT32(bindPort); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketIgnore.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketIgnore.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketIgnore { - private final byte[] payload; - - public PacketIgnore(byte[] data) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_IGNORE); - - if (data != null) { - tw.writeString(data, 0, data.length); - } - else { - tw.writeString(""); - } - - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketKexDHInit.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; -import java.math.BigInteger; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketKexDHInit.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketKexDHInit { - - private final byte[] payload; - - private final BigInteger e; - - public PacketKexDHInit(BigInteger e) { - this.e = e; - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_KEXDH_INIT); - tw.writeMPInt(e); - payload = tw.getBytes(); - } - - public PacketKexDHInit(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_KEXDH_INIT) { - throw new PacketTypeException(packet_type); - } - - e = tr.readMPINT(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public BigInteger getE() { - return e; - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketKexDHReply.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; -import java.math.BigInteger; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketKexDHReply.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketKexDHReply { - - private final byte[] payload; - - private final byte[] hostKey; - private final BigInteger f; - private final byte[] signature; - - public PacketKexDHReply(byte[] hostKey, BigInteger f, byte[] signature) { - this.hostKey = hostKey; - this.f = f; - this.signature = signature; - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_KEXDH_REPLY); - tw.writeString(hostKey, 0, hostKey.length); - tw.writeMPInt(f); - tw.writeString(signature, 0, signature.length); - payload = tw.getBytes(); - } - - public PacketKexDHReply(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_KEXDH_REPLY) { - throw new PacketTypeException(packet_type); - } - - hostKey = tr.readByteString(); - f = tr.readMPINT(); - signature = tr.readByteString(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } - - public BigInteger getF() { - return f; - } - - public byte[] getHostKey() { - return hostKey; - } - - public byte[] getSignature() { - return signature; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketKexDhGexGroup.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; -import java.math.BigInteger; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketKexDhGexGroup.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketKexDhGexGroup { - - private final BigInteger p; - private final BigInteger g; - - public PacketKexDhGexGroup(byte payload[]) throws IOException { - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_KEX_DH_GEX_GROUP) { - throw new PacketTypeException(packet_type); - } - - p = tr.readMPINT(); - g = tr.readMPINT(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public BigInteger getG() { - return g; - } - - public BigInteger getP() { - return p; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketKexDhGexInit.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.math.BigInteger; - -/** - * @author Christian Plattner - * @version $Id: PacketKexDhGexInit.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketKexDhGexInit { - - private final byte[] payload; - - public PacketKexDhGexInit(BigInteger e) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_KEX_DH_GEX_INIT); - tw.writeMPInt(e); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketKexDhGexReply.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; -import java.math.BigInteger; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketKexDhGexReply.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketKexDhGexReply { - - private final byte[] hostKey; - private final BigInteger f; - private final byte[] signature; - - public PacketKexDhGexReply(byte payload[]) throws IOException { - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_KEX_DH_GEX_REPLY) { - throw new PacketTypeException(packet_type); - } - - hostKey = tr.readByteString(); - f = tr.readMPINT(); - signature = tr.readByteString(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public BigInteger getF() { - return f; - } - - public byte[] getHostKey() { - return hostKey; - } - - public byte[] getSignature() { - return signature; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketKexDhGexRequest.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import ch.ethz.ssh2.DHGexParameters; - -/** - * @author Christian Plattner - * @version $Id: PacketKexDhGexRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketKexDhGexRequest { - private final byte[] payload; - - public PacketKexDhGexRequest(DHGexParameters para) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_KEX_DH_GEX_REQUEST); - tw.writeUINT32(para.getMin_group_len()); - tw.writeUINT32(para.getPref_group_len()); - tw.writeUINT32(para.getMax_group_len()); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketKexDhGexRequestOld.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import ch.ethz.ssh2.DHGexParameters; - -/** - * @author Christian Plattner - * @version $Id: PacketKexDhGexRequestOld.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketKexDhGexRequestOld { - - private final byte[] payload; - - public PacketKexDhGexRequestOld(DHGexParameters para) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_KEX_DH_GEX_REQUEST_OLD); - tw.writeUINT32(para.getPref_group_len()); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketKexInit.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; -import java.security.SecureRandom; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; -import ch.ethz.ssh2.crypto.CryptoWishList; -import ch.ethz.ssh2.transport.KexParameters; - -/** - * @author Christian Plattner - * @version $Id: PacketKexInit.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketKexInit { - private final byte[] payload; - - KexParameters kp = new KexParameters(); - - public PacketKexInit(CryptoWishList cwl, SecureRandom rnd) { - kp.cookie = new byte[16]; - rnd.nextBytes(kp.cookie); - kp.kex_algorithms = cwl.kexAlgorithms; - kp.server_host_key_algorithms = cwl.serverHostKeyAlgorithms; - kp.encryption_algorithms_client_to_server = cwl.c2s_enc_algos; - kp.encryption_algorithms_server_to_client = cwl.s2c_enc_algos; - kp.mac_algorithms_client_to_server = cwl.c2s_mac_algos; - kp.mac_algorithms_server_to_client = cwl.s2c_mac_algos; - kp.compression_algorithms_client_to_server = cwl.c2s_comp_algos; - kp.compression_algorithms_server_to_client = cwl.s2c_comp_algos; - kp.languages_client_to_server = new String[] {""}; - kp.languages_server_to_client = new String[] {""}; - kp.first_kex_packet_follows = false; - kp.reserved_field1 = 0; - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_KEXINIT); - tw.writeBytes(kp.cookie, 0, 16); - tw.writeNameList(kp.kex_algorithms); - tw.writeNameList(kp.server_host_key_algorithms); - tw.writeNameList(kp.encryption_algorithms_client_to_server); - tw.writeNameList(kp.encryption_algorithms_server_to_client); - tw.writeNameList(kp.mac_algorithms_client_to_server); - tw.writeNameList(kp.mac_algorithms_server_to_client); - tw.writeNameList(kp.compression_algorithms_client_to_server); - tw.writeNameList(kp.compression_algorithms_server_to_client); - tw.writeNameList(kp.languages_client_to_server); - tw.writeNameList(kp.languages_server_to_client); - tw.writeBoolean(kp.first_kex_packet_follows); - tw.writeUINT32(kp.reserved_field1); - payload = tw.getBytes(); - } - - public PacketKexInit(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_KEXINIT) { - throw new PacketTypeException(packet_type); - } - - kp.cookie = tr.readBytes(16); - kp.kex_algorithms = tr.readNameList(); - kp.server_host_key_algorithms = tr.readNameList(); - kp.encryption_algorithms_client_to_server = tr.readNameList(); - kp.encryption_algorithms_server_to_client = tr.readNameList(); - kp.mac_algorithms_client_to_server = tr.readNameList(); - kp.mac_algorithms_server_to_client = tr.readNameList(); - kp.compression_algorithms_client_to_server = tr.readNameList(); - kp.compression_algorithms_server_to_client = tr.readNameList(); - kp.languages_client_to_server = tr.readNameList(); - kp.languages_server_to_client = tr.readNameList(); - kp.first_kex_packet_follows = tr.readBoolean(); - kp.reserved_field1 = tr.readUINT32(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } - - public KexParameters getKexParameters() { - return kp; - } - - public String[] getCompression_algorithms_client_to_server() { - return kp.compression_algorithms_client_to_server; - } - - public String[] getCompression_algorithms_server_to_client() { - return kp.compression_algorithms_server_to_client; - } - - public byte[] getCookie() { - return kp.cookie; - } - - public String[] getEncryption_algorithms_client_to_server() { - return kp.encryption_algorithms_client_to_server; - } - - public String[] getEncryption_algorithms_server_to_client() { - return kp.encryption_algorithms_server_to_client; - } - - public boolean isFirst_kex_packet_follows() { - return kp.first_kex_packet_follows; - } - - public String[] getKex_algorithms() { - return kp.kex_algorithms; - } - - public String[] getLanguages_client_to_server() { - return kp.languages_client_to_server; - } - - public String[] getLanguages_server_to_client() { - return kp.languages_server_to_client; - } - - public String[] getMac_algorithms_client_to_server() { - return kp.mac_algorithms_client_to_server; - } - - public String[] getMac_algorithms_server_to_client() { - return kp.mac_algorithms_server_to_client; - } - - public int getReserved_field1() { - return kp.reserved_field1; - } - - public String[] getServer_host_key_algorithms() { - return kp.server_host_key_algorithms; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketNewKeys.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketNewKeys.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketNewKeys { - private final byte[] payload; - - public PacketNewKeys() { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_NEWKEYS); - payload = tw.getBytes(); - } - - public PacketNewKeys(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_NEWKEYS) { - throw new PacketTypeException(packet_type); - } - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketOpenDirectTCPIPChannel.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketOpenDirectTCPIPChannel.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketOpenDirectTCPIPChannel { - private final byte[] payload; - - public PacketOpenDirectTCPIPChannel(int channelID, int initialWindowSize, int maxPacketSize, - String host_to_connect, int port_to_connect, String originator_IP_address, - int originator_port) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN); - tw.writeString("direct-tcpip"); - tw.writeUINT32(channelID); - tw.writeUINT32(initialWindowSize); - tw.writeUINT32(maxPacketSize); - tw.writeString(host_to_connect); - tw.writeUINT32(port_to_connect); - tw.writeString(originator_IP_address); - tw.writeUINT32(originator_port); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketOpenSessionChannel.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketOpenSessionChannel.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketOpenSessionChannel { - private final byte[] payload; - - public PacketOpenSessionChannel(int channelID, int initialWindowSize, int maxPacketSize) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN); - tw.writeString("session"); - tw.writeUINT32(channelID); - tw.writeUINT32(initialWindowSize); - tw.writeUINT32(maxPacketSize); - payload = tw.getBytes(); - } - - public PacketOpenSessionChannel(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN) { - throw new PacketTypeException(packet_type); - } - - int channelID = tr.readUINT32(); - int initialWindowSize = tr.readUINT32(); - int maxPacketSize = tr.readUINT32(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketServiceAccept.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketServiceAccept.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketServiceAccept { - private final byte[] payload; - - public PacketServiceAccept(String serviceName) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_SERVICE_ACCEPT); - tw.writeString(serviceName); - payload = tw.getBytes(); - } - - public PacketServiceAccept(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_SERVICE_ACCEPT) { - throw new PacketTypeException(packet_type); - } - - if (tr.remain() != 0) { - String serviceName = tr.readString(); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketServiceRequest.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketServiceRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketServiceRequest { - private final byte[] payload; - - private final String serviceName; - - public PacketServiceRequest(String serviceName) { - this.serviceName = serviceName; - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_SERVICE_REQUEST); - tw.writeString(serviceName); - payload = tw.getBytes(); - } - - public String getServiceName() { - return serviceName; - } - - public PacketServiceRequest(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_SERVICE_REQUEST) { - throw new PacketTypeException(packet_type); - } - - serviceName = tr.readString(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketSessionExecCommand.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -/** - * @author Christian Plattner - * @version $Id: PacketSessionExecCommand.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketSessionExecCommand { - private final byte[] payload; - - public PacketSessionExecCommand(int recipientChannelID, boolean wantReply, String command, String charsetName) throws UnsupportedEncodingException { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); - tw.writeUINT32(recipientChannelID); - tw.writeString("exec"); - tw.writeBoolean(wantReply); - tw.writeString(command, charsetName); - payload = tw.getBytes(); - } - - public byte[] getPayload() throws IOException { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketSessionPtyRequest.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketSessionPtyRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketSessionPtyRequest { - private final byte[] payload; - - public PacketSessionPtyRequest(int recipientChannelID, boolean wantReply, String term, - int character_width, int character_height, int pixel_width, int pixel_height, - byte[] terminal_modes) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); - tw.writeUINT32(recipientChannelID); - tw.writeString("pty-req"); - tw.writeBoolean(wantReply); - tw.writeString(term); - tw.writeUINT32(character_width); - tw.writeUINT32(character_height); - tw.writeUINT32(pixel_width); - tw.writeUINT32(pixel_height); - tw.writeString(terminal_modes, 0, terminal_modes.length); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketSessionStartShell.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketSessionStartShell.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketSessionStartShell { - private final byte[] payload; - - public PacketSessionStartShell(int recipientChannelID, boolean wantReply) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); - tw.writeUINT32(recipientChannelID); - tw.writeString("shell"); - tw.writeBoolean(wantReply); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketSessionSubsystemRequest.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketSessionSubsystemRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketSessionSubsystemRequest { - private final byte[] payload; - - public PacketSessionSubsystemRequest(int recipientChannelID, boolean wantReply, String subsystem) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); - tw.writeUINT32(recipientChannelID); - tw.writeString("subsystem"); - tw.writeBoolean(wantReply); - tw.writeString(subsystem); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketSessionX11Request.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketSessionX11Request.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketSessionX11Request { - private final byte[] payload; - - public PacketSessionX11Request(int recipientChannelID, boolean wantReply, boolean singleConnection, - String x11AuthenticationProtocol, String x11AuthenticationCookie, int x11ScreenNumber) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); - tw.writeUINT32(recipientChannelID); - tw.writeString("x11-req"); - tw.writeBoolean(wantReply); - tw.writeBoolean(singleConnection); - tw.writeString(x11AuthenticationProtocol); - tw.writeString(x11AuthenticationCookie); - tw.writeUINT32(x11ScreenNumber); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketUserauthBanner.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketUserauthBanner.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketUserauthBanner { - private final byte[] payload; - - private final String message; - - public PacketUserauthBanner(String message) { - this.message = message; - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_USERAUTH_BANNER); - tw.writeString(message); - tw.writeString(""); - payload = tw.getBytes(); - } - - public String getBanner() { - return message; - } - - public PacketUserauthBanner(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_USERAUTH_BANNER) { - throw new PacketTypeException(packet_type); - } - - message = tr.readString("UTF-8"); - String language = tr.readString(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketUserauthFailure.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketUserauthFailure.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketUserauthFailure { - - private final byte[] payload; - - private Set<String> authThatCanContinue; - - private boolean partialSuccess; - - public PacketUserauthFailure(Set<String> authThatCanContinue, boolean partialSuccess) { - this.authThatCanContinue = authThatCanContinue; - this.partialSuccess = partialSuccess; - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_USERAUTH_FAILURE); - tw.writeNameList(authThatCanContinue.toArray(new String[authThatCanContinue.size()])); - tw.writeBoolean(partialSuccess); - payload = tw.getBytes(); - } - - public PacketUserauthFailure(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_USERAUTH_FAILURE) { - throw new PacketTypeException(packet_type); - } - - authThatCanContinue = new HashSet<String>(Arrays.asList(tr.readNameList())); - partialSuccess = tr.readBoolean(); - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } - - public Set<String> getAuthThatCanContinue() { - return authThatCanContinue; - } - - public boolean isPartialSuccess() { - return partialSuccess; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketUserauthInfoRequest.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketUserauthInfoRequest.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketUserauthInfoRequest { - - private final String name; - private final String instruction; - private final String languageTag; - private final int numPrompts; - - private final String prompt[]; - private final boolean echo[]; - - public PacketUserauthInfoRequest(byte payload[]) throws IOException { - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_USERAUTH_INFO_REQUEST) { - throw new PacketTypeException(packet_type); - } - - name = tr.readString(); - instruction = tr.readString(); - languageTag = tr.readString(); - numPrompts = tr.readUINT32(); - prompt = new String[numPrompts]; - echo = new boolean[numPrompts]; - - for (int i = 0; i < numPrompts; i++) { - prompt[i] = tr.readString(); - echo[i] = tr.readBoolean(); - } - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public boolean[] getEcho() { - return echo; - } - - public String getInstruction() { - return instruction; - } - - public String getLanguageTag() { - return languageTag; - } - - public String getName() { - return name; - } - - public int getNumPrompts() { - return numPrompts; - } - - public String[] getPrompt() { - return prompt; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketUserauthInfoResponse.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketUserauthInfoResponse.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketUserauthInfoResponse { - private final byte[] payload; - - public PacketUserauthInfoResponse(String[] responses) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_USERAUTH_INFO_RESPONSE); - tw.writeUINT32(responses.length); - - for (String response : responses) { - tw.writeString(response); - } - - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketUserauthRequestInteractive.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * @author Christian Plattner - * @version $Id: PacketUserauthRequestInteractive.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketUserauthRequestInteractive { - - private final byte[] payload; - - public PacketUserauthRequestInteractive(String serviceName, String user, String[] submethods) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); - tw.writeString(user); - tw.writeString(serviceName); - tw.writeString("keyboard-interactive"); - tw.writeString(""); // draft-ietf-secsh-newmodes-04.txt says that - // the language tag should be empty. - tw.writeNameList(null == submethods ? new String[] {} : submethods); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketUserauthRequestNone.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketUserauthRequestNone.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketUserauthRequestNone { - - private final byte[] payload; - - public PacketUserauthRequestNone(String serviceName, String user) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); - tw.writeString(user); - tw.writeString(serviceName); - tw.writeString("none"); - payload = tw.getBytes(); - } - - public PacketUserauthRequestNone(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { - throw new PacketTypeException(packet_type); - } - - String userName = tr.readString(); - String serviceName = tr.readString(); - String method = tr.readString(); - - if (!method.equals("none")) { - throw new IOException(String.format("Unexpected method %s", method)); - } - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketUserauthRequestPassword.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketUserauthRequestPassword.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketUserauthRequestPassword { - - private final byte[] payload; - - public PacketUserauthRequestPassword(String serviceName, String user, String pass) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); - tw.writeString(user); - tw.writeString(serviceName); - tw.writeString("password"); - tw.writeBoolean(false); - tw.writeString(pass); - payload = tw.getBytes(); - } - - public PacketUserauthRequestPassword(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { - throw new PacketTypeException(packet_type); - } - - String userName = tr.readString(); - String serviceName = tr.readString(); - String method = tr.readString(); - - if (!method.equals("password")) { - throw new IOException(String.format("Unexpected method %s", method)); - } - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketUserauthRequestPublicKey.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketUserauthRequestPublicKey.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketUserauthRequestPublicKey { - - private final byte[] payload; - - public PacketUserauthRequestPublicKey(String serviceName, String user, - String pkAlgorithmName, byte[] pk, byte[] sig) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); - tw.writeString(user); - tw.writeString(serviceName); - tw.writeString("publickey"); - tw.writeBoolean(true); - tw.writeString(pkAlgorithmName); - tw.writeString(pk, 0, pk.length); - tw.writeString(sig, 0, sig.length); - payload = tw.getBytes(); - } - - public PacketUserauthRequestPublicKey(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { - throw new PacketTypeException(packet_type); - } - - String userName = tr.readString(); - String serviceName = tr.readString(); - String method = tr.readString(); - - if (!method.equals("publickey")) { - throw new IOException(String.format("Unexpected method %s", method)); - } - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketUserauthSuccess.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.PacketTypeException; - -/** - * @author Christian Plattner - * @version $Id: PacketUserauthSuccess.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class PacketUserauthSuccess { - - private final byte[] payload; - - public PacketUserauthSuccess() { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_USERAUTH_SUCCESS); - payload = tw.getBytes(); - } - - public PacketUserauthSuccess(byte payload[]) throws IOException { - this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - - if (packet_type != Packets.SSH_MSG_USERAUTH_SUCCESS) { - throw new PacketTypeException(packet_type); - } - - if (tr.remain() != 0) { - throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); - } - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/PacketWindowChange.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -package ch.ethz.ssh2.packets; - -/** - * Indicates that that size of the terminal (window) size has changed on the client side. - * <p/> - * See section 6.7 of RFC 4254. - * - * @author Kohsuke Kawaguchi - */ -public final class PacketWindowChange { - private final byte[] payload; - - public PacketWindowChange(int recipientChannelID, - int character_width, int character_height, int pixel_width, int pixel_height) { - TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); - tw.writeUINT32(recipientChannelID); - tw.writeString("window-change"); - tw.writeBoolean(false); - tw.writeUINT32(character_width); - tw.writeUINT32(character_height); - tw.writeUINT32(pixel_width); - tw.writeUINT32(pixel_height); - payload = tw.getBytes(); - } - - public byte[] getPayload() { - return payload; - } -}
--- a/src/ch/ethz/ssh2/packets/Packets.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -/** - * Packets. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class Packets { - public static final int SSH_MSG_DISCONNECT = 1; - public static final int SSH_MSG_IGNORE = 2; - public static final int SSH_MSG_UNIMPLEMENTED = 3; - public static final int SSH_MSG_DEBUG = 4; - public static final int SSH_MSG_SERVICE_REQUEST = 5; - public static final int SSH_MSG_SERVICE_ACCEPT = 6; - - public static final int SSH_MSG_KEXINIT = 20; - public static final int SSH_MSG_NEWKEYS = 21; - - public static final int SSH_MSG_KEXDH_INIT = 30; - public static final int SSH_MSG_KEXDH_REPLY = 31; - - public static final int SSH_MSG_KEX_DH_GEX_REQUEST_OLD = 30; - public static final int SSH_MSG_KEX_DH_GEX_REQUEST = 34; - public static final int SSH_MSG_KEX_DH_GEX_GROUP = 31; - public static final int SSH_MSG_KEX_DH_GEX_INIT = 32; - public static final int SSH_MSG_KEX_DH_GEX_REPLY = 33; - - public static final int SSH_MSG_USERAUTH_REQUEST = 50; - public static final int SSH_MSG_USERAUTH_FAILURE = 51; - public static final int SSH_MSG_USERAUTH_SUCCESS = 52; - public static final int SSH_MSG_USERAUTH_BANNER = 53; - public static final int SSH_MSG_USERAUTH_INFO_REQUEST = 60; - public static final int SSH_MSG_USERAUTH_INFO_RESPONSE = 61; - - public static final int SSH_MSG_GLOBAL_REQUEST = 80; - public static final int SSH_MSG_REQUEST_SUCCESS = 81; - public static final int SSH_MSG_REQUEST_FAILURE = 82; - - public static final int SSH_MSG_CHANNEL_OPEN = 90; - public static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91; - public static final int SSH_MSG_CHANNEL_OPEN_FAILURE = 92; - public static final int SSH_MSG_CHANNEL_WINDOW_ADJUST = 93; - public static final int SSH_MSG_CHANNEL_DATA = 94; - public static final int SSH_MSG_CHANNEL_EXTENDED_DATA = 95; - public static final int SSH_MSG_CHANNEL_EOF = 96; - public static final int SSH_MSG_CHANNEL_CLOSE = 97; - public static final int SSH_MSG_CHANNEL_REQUEST = 98; - public static final int SSH_MSG_CHANNEL_SUCCESS = 99; - public static final int SSH_MSG_CHANNEL_FAILURE = 100; - - public static final int SSH_EXTENDED_DATA_STDERR = 1; - - public static final int SSH_OPEN_ADMINISTRATIVELY_PROHIBITED = 1; - public static final int SSH_OPEN_CONNECT_FAILED = 2; - public static final int SSH_OPEN_UNKNOWN_CHANNEL_TYPE = 3; - public static final int SSH_OPEN_RESOURCE_SHORTAGE = 4; - - private static final String[] reverseNames = new String[101]; - - static { - reverseNames[1] = "SSH_MSG_DISCONNECT"; - reverseNames[2] = "SSH_MSG_IGNORE"; - reverseNames[3] = "SSH_MSG_UNIMPLEMENTED"; - reverseNames[4] = "SSH_MSG_DEBUG"; - reverseNames[5] = "SSH_MSG_SERVICE_REQUEST"; - reverseNames[6] = "SSH_MSG_SERVICE_ACCEPT"; - reverseNames[20] = "SSH_MSG_KEXINIT"; - reverseNames[21] = "SSH_MSG_NEWKEYS"; - reverseNames[30] = "SSH_MSG_KEXDH_INIT"; - reverseNames[31] = "SSH_MSG_KEXDH_REPLY/SSH_MSG_KEX_DH_GEX_GROUP"; - reverseNames[32] = "SSH_MSG_KEX_DH_GEX_INIT"; - reverseNames[33] = "SSH_MSG_KEX_DH_GEX_REPLY"; - reverseNames[34] = "SSH_MSG_KEX_DH_GEX_REQUEST"; - reverseNames[50] = "SSH_MSG_USERAUTH_REQUEST"; - reverseNames[51] = "SSH_MSG_USERAUTH_FAILURE"; - reverseNames[52] = "SSH_MSG_USERAUTH_SUCCESS"; - reverseNames[53] = "SSH_MSG_USERAUTH_BANNER"; - reverseNames[60] = "SSH_MSG_USERAUTH_INFO_REQUEST"; - reverseNames[61] = "SSH_MSG_USERAUTH_INFO_RESPONSE"; - reverseNames[80] = "SSH_MSG_GLOBAL_REQUEST"; - reverseNames[81] = "SSH_MSG_REQUEST_SUCCESS"; - reverseNames[82] = "SSH_MSG_REQUEST_FAILURE"; - reverseNames[90] = "SSH_MSG_CHANNEL_OPEN"; - reverseNames[91] = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION"; - reverseNames[92] = "SSH_MSG_CHANNEL_OPEN_FAILURE"; - reverseNames[93] = "SSH_MSG_CHANNEL_WINDOW_ADJUST"; - reverseNames[94] = "SSH_MSG_CHANNEL_DATA"; - reverseNames[95] = "SSH_MSG_CHANNEL_EXTENDED_DATA"; - reverseNames[96] = "SSH_MSG_CHANNEL_EOF"; - reverseNames[97] = "SSH_MSG_CHANNEL_CLOSE"; - reverseNames[98] = "SSH_MSG_CHANNEL_REQUEST"; - reverseNames[99] = "SSH_MSG_CHANNEL_SUCCESS"; - reverseNames[100] = "SSH_MSG_CHANNEL_FAILURE"; - } - - public static final String getMessageName(int type) { - String res = null; - - if ((type >= 0) && (type < reverseNames.length)) { - res = reverseNames[type]; - } - - return (res == null) ? ("UNKNOWN MSG " + type) : res; - } - - // public static final void debug(String tag, byte[] msg) - // { - // System.err.println(tag + " Type: " + msg[0] + ", LEN: " + msg.length); - // - // for (int i = 0; i < msg.length; i++) - // { - // if (((msg[i] >= 'a') && (msg[i] <= 'z')) || ((msg[i] >= 'A') && (msg[i] <= 'Z')) - // || ((msg[i] >= '0') && (msg[i] <= '9')) || (msg[i] == ' ')) - // System.err.print((char) msg[i]); - // else - // System.err.print("."); - // } - // System.err.println(); - // System.err.flush(); - // } -}
--- a/src/ch/ethz/ssh2/packets/TypesReader.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.IOException; -import java.math.BigInteger; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.util.StringEncoder; - -/** - * @author Christian Plattner - * @version $Id: TypesReader.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class TypesReader { - byte[] arr; - int pos = 0; - int max = 0; - - public TypesReader(byte[] arr) { - this.arr = arr; - pos = 0; - max = arr.length; - } - - public TypesReader(byte[] arr, int off) { - this.arr = arr; - this.pos = off; - this.max = arr.length; - - if ((pos < 0) || (pos > arr.length)) { - throw new IllegalArgumentException("Illegal offset."); - } - } - - public TypesReader(byte[] arr, int off, int len) { - this.arr = arr; - this.pos = off; - this.max = off + len; - - if ((pos < 0) || (pos > arr.length)) { - throw new IllegalArgumentException("Illegal offset."); - } - - if ((max < 0) || (max > arr.length)) { - throw new IllegalArgumentException("Illegal length."); - } - } - - public int readByte() throws IOException { - if (pos >= max) { - throw new PacketFormatException("Packet too short."); - } - - return (arr[pos++] & 0xff); - } - - public byte[] readBytes(int len) throws IOException { - if ((pos + len) > max) { - throw new PacketFormatException("Packet too short."); - } - - byte[] res = new byte[len]; - System.arraycopy(arr, pos, res, 0, len); - pos += len; - return res; - } - - public void readBytes(byte[] dst, int off, int len) throws IOException { - if ((pos + len) > max) { - throw new PacketFormatException("Packet too short."); - } - - System.arraycopy(arr, pos, dst, off, len); - pos += len; - } - - public boolean readBoolean() throws IOException { - if (pos >= max) { - throw new PacketFormatException("Packet too short."); - } - - return (arr[pos++] != 0); - } - - public int readUINT32() throws IOException { - if ((pos + 4) > max) { - throw new PacketFormatException("Packet too short."); - } - - return ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8) - | (arr[pos++] & 0xff); - } - - public long readUINT64() throws IOException { - if ((pos + 8) > max) { - throw new PacketFormatException("Packet too short."); - } - - long high = ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8) - | (arr[pos++] & 0xff); /* sign extension may take place - will be shifted away =) */ - long low = ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8) - | (arr[pos++] & 0xff); /* sign extension may take place - handle below */ - return (high << 32) | (low & 0xffffffffl); /* see Java language spec (15.22.1, 5.6.2) */ - } - - public BigInteger readMPINT() throws IOException { - BigInteger b; - byte raw[] = readByteString(); - - if (raw.length == 0) { - b = BigInteger.ZERO; - } - else { - b = new BigInteger(raw); - } - - return b; - } - - public byte[] readByteString() throws IOException { - int len = readUINT32(); - - if ((len + pos) > max) { - throw new PacketFormatException("Malformed SSH byte string."); - } - - byte[] res = new byte[len]; - System.arraycopy(arr, pos, res, 0, len); - pos += len; - return res; - } - - public String readString(String charsetName) throws IOException { - int len = readUINT32(); - - if ((len + pos) > max) { - throw new PacketFormatException("Malformed SSH string."); - } - - String res = (charsetName == null) ? new String(arr, pos, len) : new String(arr, pos, len, charsetName); - pos += len; - return res; - } - - public String readString() throws IOException { - int len = readUINT32(); - - if ((len + pos) > max) { - throw new PacketFormatException("Malformed SSH string."); - } - - String res = StringEncoder.GetString(arr, pos, len); - pos += len; - return res; - } - - public String[] readNameList() throws IOException { - return readString().split(","); - } - - public int remain() { - return max - pos; - } - -}
--- a/src/ch/ethz/ssh2/packets/TypesWriter.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.packets; - -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; - -import ch.ethz.ssh2.util.StringEncoder; - -/** - * @author Christian Plattner - * @version $Id: TypesWriter.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public final class TypesWriter { - byte arr[]; - int pos; - - public TypesWriter() { - arr = new byte[256]; - pos = 0; - } - - private void resize(int len) { - byte new_arr[] = new byte[len]; - System.arraycopy(arr, 0, new_arr, 0, arr.length); - arr = new_arr; - } - - public int length() { - return pos; - } - - public byte[] getBytes() { - byte[] dst = new byte[pos]; - System.arraycopy(arr, 0, dst, 0, pos); - return dst; - } - - public void getBytes(byte dst[]) { - System.arraycopy(arr, 0, dst, 0, pos); - } - - public void writeUINT32(int val, int off) { - if ((off + 4) > arr.length) { - resize(off + 32); - } - - arr[off++] = (byte)(val >> 24); - arr[off++] = (byte)(val >> 16); - arr[off++] = (byte)(val >> 8); - arr[off++] = (byte) val; - } - - public void writeUINT32(int val) { - writeUINT32(val, pos); - pos += 4; - } - - public void writeUINT64(long val) { - if ((pos + 8) > arr.length) { - resize(arr.length + 32); - } - - arr[pos++] = (byte)(val >> 56); - arr[pos++] = (byte)(val >> 48); - arr[pos++] = (byte)(val >> 40); - arr[pos++] = (byte)(val >> 32); - arr[pos++] = (byte)(val >> 24); - arr[pos++] = (byte)(val >> 16); - arr[pos++] = (byte)(val >> 8); - arr[pos++] = (byte) val; - } - - public void writeBoolean(boolean v) { - if ((pos + 1) > arr.length) { - resize(arr.length + 32); - } - - arr[pos++] = v ? (byte) 1 : (byte) 0; - } - - public void writeByte(int v, int off) { - if ((off + 1) > arr.length) { - resize(off + 32); - } - - arr[off] = (byte) v; - } - - public void writeByte(int v) { - writeByte(v, pos); - pos++; - } - - public void writeMPInt(BigInteger b) { - byte raw[] = b.toByteArray(); - - if ((raw.length == 1) && (raw[0] == 0)) { - writeUINT32(0); /* String with zero bytes of data */ - } - else { - writeString(raw, 0, raw.length); - } - } - - public void writeBytes(byte[] buff) { - writeBytes(buff, 0, buff.length); - } - - public void writeBytes(byte[] buff, int off, int len) { - if ((pos + len) > arr.length) { - resize(arr.length + len + 32); - } - - System.arraycopy(buff, off, arr, pos, len); - pos += len; - } - - public void writeString(byte[] buff, int off, int len) { - writeUINT32(len); - writeBytes(buff, off, len); - } - - public void writeString(String v) { - byte[] b = StringEncoder.GetBytes(v); - writeUINT32(b.length); - writeBytes(b, 0, b.length); - } - - public void writeString(String v, String charsetName) throws UnsupportedEncodingException { - byte[] b = (charsetName == null) ? StringEncoder.GetBytes(v) : v.getBytes(charsetName); - writeUINT32(b.length); - writeBytes(b, 0, b.length); - } - - public void writeNameList(String v[]) { - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < v.length; i++) { - if (i > 0) { - sb.append(','); - } - - sb.append(v[i]); - } - - writeString(sb.toString()); - } -}
--- a/src/ch/ethz/ssh2/server/ServerConnectionState.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.server; - -import java.net.Socket; - -import ch.ethz.ssh2.ServerAuthenticationCallback; -import ch.ethz.ssh2.ServerConnection; -import ch.ethz.ssh2.ServerConnectionCallback; -import ch.ethz.ssh2.auth.ServerAuthenticationManager; -import ch.ethz.ssh2.channel.ChannelManager; -import ch.ethz.ssh2.crypto.CryptoWishList; -import ch.ethz.ssh2.crypto.SecureRandomFix; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.RSAPrivateKey; -import ch.ethz.ssh2.transport.ClientServerHello; -import ch.ethz.ssh2.transport.ServerTransportManager; - -public class ServerConnectionState { - public ServerConnection conn; - - public SecureRandomFix generator = new SecureRandomFix(); - - public String softwareversion; - - //public String auth_banner = null; - public ServerConnectionCallback cb_conn; - public ServerAuthenticationCallback cb_auth; - - /* Settings for the next key exchange */ - public CryptoWishList next_cryptoWishList = CryptoWishList.forServer(); - public KeyPair next_dsa_key; - public KeyPair next_ec_key; - public KeyPair next_rsa_key; - - public Socket s; - - public ClientServerHello csh; - public ServerTransportManager tm; - public ServerAuthenticationManager am; - public ChannelManager cm; - - public boolean flag_auth_serviceRequested = false; - public boolean flag_auth_completed = false; - - public ServerConnectionState(ServerConnection conn) { - this.conn = conn; - } -}
--- a/src/ch/ethz/ssh2/sftp/AceFlags.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package ch.ethz.ssh2.sftp; - -/** - * @version $Id: AceFlags.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public final class AceFlags { - private AceFlags() { - } - - public static final int ACE4_FILE_INHERIT_ACE = 0x00000001; - public static final int ACE4_DIRECTORY_INHERIT_ACE = 0x00000002; - public static final int ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004; - public static final int ACE4_INHERIT_ONLY_ACE = 0x00000008; - public static final int ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010; - public static final int ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020; - public static final int ACE4_IDENTIFIER_GROUP = 0x00000040; -}
--- a/src/ch/ethz/ssh2/sftp/AceMask.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -package ch.ethz.ssh2.sftp; - -/** - * @version $Id: AceMask.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public final class AceMask { - private AceMask() { - } - - public static final int ACE4_READ_DATA = 0x00000001; - public static final int ACE4_LIST_DIRECTORY = 0x00000001; - public static final int ACE4_WRITE_DATA = 0x00000002; - public static final int ACE4_ADD_FILE = 0x00000002; - public static final int ACE4_APPEND_DATA = 0x00000004; - public static final int ACE4_ADD_SUBDIRECTORY = 0x00000004; - public static final int ACE4_READ_NAMED_ATTRS = 0x00000008; - public static final int ACE4_WRITE_NAMED_ATTRS = 0x00000010; - public static final int ACE4_EXECUTE = 0x00000020; - public static final int ACE4_DELETE_CHILD = 0x00000040; - public static final int ACE4_READ_ATTRIBUTES = 0x00000080; - public static final int ACE4_WRITE_ATTRIBUTES = 0x00000100; - public static final int ACE4_DELETE = 0x00010000; - public static final int ACE4_READ_ACL = 0x00020000; - public static final int ACE4_WRITE_ACL = 0x00040000; - public static final int ACE4_WRITE_OWNER = 0x00080000; - public static final int ACE4_SYNCHRONIZE = 0x00100000; - -}
--- a/src/ch/ethz/ssh2/sftp/AceType.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -package ch.ethz.ssh2.sftp; - -/** - * @version $Id: AceType.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public final class AceType { - - private AceType() { - } - - private static final int ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000; - private static final int ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001; - private static final int ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002; - private static final int ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003; - -}
--- a/src/ch/ethz/ssh2/sftp/AclFlags.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -package ch.ethz.ssh2.sftp; - -/** - * @version $Id: AclFlags.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public final class AclFlags { - - /** - * If INCLUDED is set during a setstat operation, then the client - * intends to modify the ALLOWED/DENIED entries of the ACL. - * Otherwise, the client intends for these entries to be - * preserved. - */ - public static final int SFX_ACL_CONTROL_INCLUDED = 0x00000001; - /** - * If the PRESENT bit is not set, then the client wishes to remove - * control entries. If the server doesn't support separate - * control and audit information, the client MUST not clear this - * bit without also clearing the AUDIT_ALARM_PRESENT bit. - */ - public static final int SFX_ACL_CONTROL_PRESENT = 0x00000002; - /** - * If INHERITED is set, then ALLOW/DENY ACEs MAY be inherited from - * the parent directory. If it is off, then they MUST not be - * INHERITED. If the server does not support controlling - * inheritance, then the client MUST clear this bit; in this case - * the inheritance properties of the server are undefined. - */ - public static final int SFX_ACL_CONTROL_INHERITED = 0x00000004; - /** - * If INCLUDE is set during a setstat operation, then the client - * intends to modify the AUDIT/ALARM entries of the ACL. - * Otherwise, the client intends for these entries to be - * preserved. - */ - public static final int SFX_ACL_AUDIT_ALARM_INCLUDED = 0x00000010; - /** - * If INHERITED is set, then AUDIT/ALARM ACEs MAY be inherited - * from the parent directory. If it is off, then they MUST not be - * INHERITED. If the server does not support controlling - * inheritance, then the client MUST clear this bit; in this case - * the inheritance properties of the server are undefined. - */ - public static final int SFX_ACL_AUDIT_ALARM_INHERITED = 0x00000020; -}
--- a/src/ch/ethz/ssh2/sftp/AttrTextHints.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.sftp; - -/** - * - * Values for the 'text-hint' field in the SFTP ATTRS data type. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - * - */ -public class AttrTextHints { - /** - * The server knows the file is a text file, and should be opened - * using the SSH_FXF_ACCESS_TEXT_MODE flag. - */ - public static final int SSH_FILEXFER_ATTR_KNOWN_TEXT = 0x00; - - /** - * The server has applied a heuristic or other mechanism and - * believes that the file should be opened with the - * SSH_FXF_ACCESS_TEXT_MODE flag. - */ - public static final int SSH_FILEXFER_ATTR_GUESSED_TEXT = 0x01; - - /** - * The server knows the file has binary content. - */ - public static final int SSH_FILEXFER_ATTR_KNOWN_BINARY = 0x02; - - /** - * The server has applied a heuristic or other mechanism and - * believes has binary content, and should not be opened with the - * SSH_FXF_ACCESS_TEXT_MODE flag. - */ - public static final int SSH_FILEXFER_ATTR_GUESSED_BINARY = 0x03; -}
--- a/src/ch/ethz/ssh2/sftp/AttribBits.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.sftp; - -/** - * SFTP Attribute Bits for the "attrib-bits" and "attrib-bits-valid" fields - * of the SFTP ATTR data type. - * <p/> - * Yes, these are the "attrib-bits", even though they have "_FLAGS_" in - * their name. Don't ask - I did not invent it. - * <p/> - * "<i>These fields, taken together, reflect various attributes of the file - * or directory, on the server. Bits not set in 'attrib-bits-valid' MUST be - * ignored in the 'attrib-bits' field. This allows both the server and the - * client to communicate only the bits it knows about without inadvertently - * twiddling bits they don't understand.</i>" - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class AttribBits { - - private AttribBits() { - } - - /** - * Advisory, read-only bit. This bit is not part of the access - * control information on the file, but is rather an advisory field - * indicating that the file should not be written. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_READONLY = 0x00000001; - - /** - * The file is part of the operating system. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_SYSTEM = 0x00000002; - - /** - * File SHOULD NOT be shown to user unless specifically requested. - * For example, most UNIX systems SHOULD set this bit if the filename - * begins with a 'period'. This bit may be read-only (see section 5.4 of - * the SFTP standard draft). Most UNIX systems will not allow this to be - * changed. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_HIDDEN = 0x00000004; - - /** - * This attribute applies only to directories. This attribute is - * always read-only, and cannot be modified. This attribute means - * that files and directory names in this directory should be compared - * without regard to case. - * <p/> - * It is recommended that where possible, the server's filesystem be - * allowed to do comparisons. For example, if a client wished to prompt - * a user before overwriting a file, it should not compare the new name - * with the previously retrieved list of names in the directory. Rather, - * it should first try to create the new file by specifying - * SSH_FXF_CREATE_NEW flag. Then, if this fails and returns - * SSH_FX_FILE_ALREADY_EXISTS, it should prompt the user and then retry - * the create specifying SSH_FXF_CREATE_TRUNCATE. - * <p/> - * Unless otherwise specified, filenames are assumed to be case sensitive. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE = 0x00000008; - - /** - * The file should be included in backup / archive operations. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_ARCHIVE = 0x00000010; - - /** - * The file is stored on disk using file-system level transparent - * encryption. This flag does not affect the file data on the wire - * (for either READ or WRITE requests.) - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED = 0x00000020; - - /** - * The file is stored on disk using file-system level transparent - * compression. This flag does not affect the file data on the wire. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_COMPRESSED = 0x00000040; - - /** - * The file is a sparse file; this means that file blocks that have - * not been explicitly written are not stored on disk. For example, if - * a client writes a buffer at 10 M from the beginning of the file, - * the blocks between the previous EOF marker and the 10 M offset would - * not consume physical disk space. - * <p/> - * Some servers may store all files as sparse files, in which case - * this bit will be unconditionally set. Other servers may not have - * a mechanism for determining if the file is sparse, and so the file - * MAY be stored sparse even if this flag is not set. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_SPARSE = 0x00000080; - - /** - * Opening the file without either the SSH_FXF_ACCESS_APPEND_DATA or - * the SSH_FXF_ACCESS_APPEND_DATA_ATOMIC flag (see section 8.1.1.3 - * of the SFTP standard draft) MUST result in an - * SSH_FX_INVALID_PARAMETER error. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY = 0x00000100; - - /** - * The file cannot be deleted or renamed, no hard link can be created - * to this file, and no data can be written to the file. - * <p/> - * This bit implies a stronger level of protection than - * SSH_FILEXFER_ATTR_FLAGS_READONLY, the file permission mask or ACLs. - * Typically even the superuser cannot write to immutable files, and - * only the superuser can set or remove the bit. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE = 0x00000200; - - /** - * When the file is modified, the changes are written synchronously - * to the disk. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_SYNC = 0x00000400; - - /** - * The server MAY include this bit in a directory listing or realpath - * response. It indicates there was a failure in the translation to UTF-8. - * If this flag is included, the server SHOULD also include the - * UNTRANSLATED_NAME attribute. - */ - public static final int SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR = 0x00000800; - -}
--- a/src/ch/ethz/ssh2/sftp/AttribFlags.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.sftp; - -/** - * Attribute Flags. The 'valid-attribute-flags' field in - * the SFTP ATTRS data type specifies which of the fields are actually present. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class AttribFlags { - - private AttribFlags() { - } - - /** - * Indicates that the 'allocation-size' field is present. - */ - public static final int SSH_FILEXFER_ATTR_SIZE = 0x00000001; - - /** - * Protocol version 6: - * 0x00000002 was used in a previous version of this protocol. - * It is now a reserved value and MUST NOT appear in the mask. - * Some future version of this protocol may reuse this value. - */ - public static final int SSH_FILEXFER_ATTR_V3_UIDGID = 0x00000002; - - /** - * Indicates that the 'permissions' field is present. - */ - public static final int SSH_FILEXFER_ATTR_PERMISSIONS = 0x00000004; - - /** - * Indicates that the 'atime' and 'mtime' field are present - * (protocol v3). - */ - public static final int SSH_FILEXFER_ATTR_V3_ACMODTIME = 0x00000008; - - /** - * Indicates that the 'atime' field is present. - */ - public static final int SSH_FILEXFER_ATTR_ACCESSTIME = 0x00000008; - - /** - * Indicates that the 'createtime' field is present. - */ - public static final int SSH_FILEXFER_ATTR_CREATETIME = 0x00000010; - - /** - * Indicates that the 'mtime' field is present. - */ - public static final int SSH_FILEXFER_ATTR_MODIFYTIME = 0x00000020; - - /** - * Indicates that the 'acl' field is present. - */ - public static final int SSH_FILEXFER_ATTR_ACL = 0x00000040; - - /** - * Indicates that the 'owner' and 'group' fields are present. - */ - public static final int SSH_FILEXFER_ATTR_OWNERGROUP = 0x00000080; - - /** - * Indicates that additionally to the 'atime', 'createtime', - * 'mtime' and 'ctime' fields (if present), there is also - * 'atime-nseconds', 'createtime-nseconds', 'mtime-nseconds' - * and 'ctime-nseconds'. - */ - public static final int SSH_FILEXFER_ATTR_SUBSECOND_TIMES = 0x00000100; - - /** - * Indicates that the 'attrib-bits' and 'attrib-bits-valid' - * fields are present. - */ - public static final int SSH_FILEXFER_ATTR_BITS = 0x00000200; - - /** - * Indicates that the 'allocation-size' field is present. Field specifies the number of bytes that the - * file consumes on disk. - */ - public static final int SSH_FILEXFER_ATTR_ALLOCATION_SIZE = 0x00000400; - - /** - * Indicates that the 'text-hint' field is present. - */ - public static final int SSH_FILEXFER_ATTR_TEXT_HINT = 0x00000800; - - /** - * Indicates that the 'mime-type' field is present. - */ - public static final int SSH_FILEXFER_ATTR_MIME_TYPE = 0x00001000; - - /** - * Indicates that the 'link-count' field is present. - */ - public static final int SSH_FILEXFER_ATTR_LINK_COUNT = 0x00002000; - - /** - * Indicates that the 'untranslated-name' field is present. - */ - public static final int SSH_FILEXFER_ATTR_UNTRANSLATED_NAME = 0x00004000; - - /** - * Indicates that the 'ctime' field is present. - */ - public static final int SSH_FILEXFER_ATTR_CTIME = 0x00008000; - - /** - * Indicates that the 'extended-count' field (and probablby some - * 'extensions') is present. - */ - public static final int SSH_FILEXFER_ATTR_EXTENDED = 0x80000000; -}
--- a/src/ch/ethz/ssh2/sftp/AttribPermissions.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.sftp; - -/** - * Permissions for the 'permissions' field in the SFTP ATTRS data type. - * <p/> - * "<i>The 'permissions' field contains a bit mask specifying file permissions. - * These permissions correspond to the st_mode field of the stat structure - * defined by POSIX [IEEE.1003-1.1996].</i>" - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class AttribPermissions { - private AttribPermissions() { - } - - /* Octal values! */ - - public static final int S_IRUSR = 0400; - public static final int S_IWUSR = 0200; - public static final int S_IXUSR = 0100; - public static final int S_IRGRP = 0040; - public static final int S_IWGRP = 0020; - public static final int S_IXGRP = 0010; - public static final int S_IROTH = 0004; - public static final int S_IWOTH = 0002; - public static final int S_IXOTH = 0001; - public static final int S_ISUID = 04000; - public static final int S_ISGID = 02000; - public static final int S_ISVTX = 01000; -}
--- a/src/ch/ethz/ssh2/sftp/AttribTypes.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.sftp; - -/** - * Types for the 'type' field in the SFTP ATTRS data type. - * <p/> - * "<i>On a POSIX system, these values would be derived from the mode field - * of the stat structure. SPECIAL should be used for files that are of - * a known type which cannot be expressed in the protocol. UNKNOWN - * should be used if the type is not known.</i>" - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class AttribTypes { - private AttribTypes() { - } - - public static final int SSH_FILEXFER_TYPE_REGULAR = 1; - public static final int SSH_FILEXFER_TYPE_DIRECTORY = 2; - public static final int SSH_FILEXFER_TYPE_SYMLINK = 3; - public static final int SSH_FILEXFER_TYPE_SPECIAL = 4; - /** - * Should be used if the type is not known. - */ - public static final int SSH_FILEXFER_TYPE_UNKNOWN = 5; - public static final int SSH_FILEXFER_TYPE_SOCKET = 6; - public static final int SSH_FILEXFER_TYPE_CHAR_DEVICE = 7; - public static final int SSH_FILEXFER_TYPE_BLOCK_DEVICE = 8; - public static final int SSH_FILEXFER_TYPE_FIFO = 9; -}
--- a/src/ch/ethz/ssh2/sftp/ErrorCodes.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.sftp; - -/** - * SFTP Error Codes - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class ErrorCodes { - private ErrorCodes() { - } - - public static final int SSH_FX_OK = 0; - public static final int SSH_FX_EOF = 1; - public static final int SSH_FX_NO_SUCH_FILE = 2; - public static final int SSH_FX_PERMISSION_DENIED = 3; - public static final int SSH_FX_FAILURE = 4; - public static final int SSH_FX_BAD_MESSAGE = 5; - public static final int SSH_FX_NO_CONNECTION = 6; - public static final int SSH_FX_CONNECTION_LOST = 7; - /** - * The server MUST respond with SSH_FXP_STATUS(SSH_FX_OP_UNSUPPORTED) if - * it receives a packet it does not recognize. - */ - public static final int SSH_FX_OP_UNSUPPORTED = 8; - public static final int SSH_FX_INVALID_HANDLE = 9; - public static final int SSH_FX_NO_SUCH_PATH = 10; - public static final int SSH_FX_FILE_ALREADY_EXISTS = 11; - public static final int SSH_FX_WRITE_PROTECT = 12; - public static final int SSH_FX_NO_MEDIA = 13; - public static final int SSH_FX_NO_SPACE_ON_FILESYSTEM = 14; - public static final int SSH_FX_QUOTA_EXCEEDED = 15; - public static final int SSH_FX_UNKNOWN_PRINCIPAL = 16; - public static final int SSH_FX_LOCK_CONFLICT = 17; - public static final int SSH_FX_DIR_NOT_EMPTY = 18; - public static final int SSH_FX_NOT_A_DIRECTORY = 19; - public static final int SSH_FX_INVALID_FILENAME = 20; - public static final int SSH_FX_LINK_LOOP = 21; - public static final int SSH_FX_CANNOT_DELETE = 22; - public static final int SSH_FX_INVALID_PARAMETER = 23; - public static final int SSH_FX_FILE_IS_A_DIRECTORY = 24; - public static final int SSH_FX_BYTE_RANGE_LOCK_CONFLICT = 25; - public static final int SSH_FX_BYTE_RANGE_LOCK_REFUSED = 26; - public static final int SSH_FX_DELETE_PENDING = 27; - public static final int SSH_FX_FILE_CORRUPT = 28; - public static final int SSH_FX_OWNER_INVALID = 29; - public static final int SSH_FX_GROUP_INVALID = 30; - public static final int SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK = 31; - - private static final String[][] messages = { - - {"SSH_FX_OK", "Indicates successful completion of the operation."}, - { - "SSH_FX_EOF", - "An attempt to read past the end-of-file was made; or, there are no more directory entries to return." - }, - {"SSH_FX_NO_SUCH_FILE", "A reference was made to a file which does not exist."}, - {"SSH_FX_PERMISSION_DENIED", "The user does not have sufficient permissions to perform the operation."}, - {"SSH_FX_FAILURE", "An error occurred, but no specific error code exists to describe the failure."}, - {"SSH_FX_BAD_MESSAGE", "A badly formatted packet or other SFTP protocol incompatibility was detected."}, - {"SSH_FX_NO_CONNECTION", "There is no connection to the server."}, - {"SSH_FX_CONNECTION_LOST", "The connection to the server was lost."}, - { - "SSH_FX_OP_UNSUPPORTED", - "An attempted operation could not be completed by the server because the server does not support the operation." - }, - {"SSH_FX_INVALID_HANDLE", "The handle value was invalid."}, - {"SSH_FX_NO_SUCH_PATH", "The file path does not exist or is invalid."}, - {"SSH_FX_FILE_ALREADY_EXISTS", "The file already exists."}, - {"SSH_FX_WRITE_PROTECT", "The file is on read-only media, or the media is write protected."}, - { - "SSH_FX_NO_MEDIA", - "The requested operation cannot be completed because there is no media available in the drive." - }, - { - "SSH_FX_NO_SPACE_ON_FILESYSTEM", - "The requested operation cannot be completed because there is insufficient free space on the filesystem." - }, - { - "SSH_FX_QUOTA_EXCEEDED", - "The operation cannot be completed because it would exceed the user's storage quota." - }, - { - "SSH_FX_UNKNOWN_PRINCIPAL", - "A principal referenced by the request (either the 'owner', 'group', or 'who' field of an ACL), was unknown. The error specific data contains the problematic names." - }, - {"SSH_FX_LOCK_CONFLICT", "The file could not be opened because it is locked by another process."}, - {"SSH_FX_DIR_NOT_EMPTY", "The directory is not empty."}, - {"SSH_FX_NOT_A_DIRECTORY", "The specified file is not a directory."}, - {"SSH_FX_INVALID_FILENAME", "The filename is not valid."}, - { - "SSH_FX_LINK_LOOP", - "Too many symbolic links encountered or, an SSH_FXF_NOFOLLOW open encountered a symbolic link as the final component." - }, - { - "SSH_FX_CANNOT_DELETE", - "The file cannot be deleted. One possible reason is that the advisory READONLY attribute-bit is set." - }, - { - "SSH_FX_INVALID_PARAMETER", - "One of the parameters was out of range, or the parameters specified cannot be used together." - }, - { - "SSH_FX_FILE_IS_A_DIRECTORY", - "The specified file was a directory in a context where a directory cannot be used." - }, - { - "SSH_FX_BYTE_RANGE_LOCK_CONFLICT", - " A read or write operation failed because another process's mandatory byte-range lock overlaps with the request." - }, - {"SSH_FX_BYTE_RANGE_LOCK_REFUSED", "A request for a byte range lock was refused."}, - {"SSH_FX_DELETE_PENDING", "An operation was attempted on a file for which a delete operation is pending."}, - {"SSH_FX_FILE_CORRUPT", "The file is corrupt; an filesystem integrity check should be run."}, - {"SSH_FX_OWNER_INVALID", "The principal specified can not be assigned as an owner of a file."}, - {"SSH_FX_GROUP_INVALID", "The principal specified can not be assigned as the primary group of a file."}, - { - "SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK", - "The requested operation could not be completed because the specifed byte range lock has not been granted." - }, - - }; - - public static final String[] getDescription(int errorCode) { - if ((errorCode < 0) || (errorCode >= messages.length)) { - return null; - } - - return messages[errorCode]; - } -}
--- a/src/ch/ethz/ssh2/sftp/OpenFlags.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.sftp; - -/** - * SFTP Open Flags. - * <p/> - * The following table is provided to assist in mapping POSIX semantics - * to equivalent SFTP file open parameters: - * <p/> - * <ul> - * <li>O_RDONLY - * <ul><li>desired-access = READ_DATA | READ_ATTRIBUTES</li></ul> - * </li> - * </ul> - * <ul> - * <li>O_WRONLY - * <ul><li>desired-access = WRITE_DATA | WRITE_ATTRIBUTES</li></ul> - * </li> - * </ul> - * <ul> - * <li>O_RDWR - * <ul><li>desired-access = READ_DATA | READ_ATTRIBUTES | WRITE_DATA | WRITE_ATTRIBUTES</li></ul> - * </li> - * </ul> - * <ul> - * <li>O_APPEND - * <ul> - * <li>desired-access = WRITE_DATA | WRITE_ATTRIBUTES | APPEND_DATA</li> - * <li>flags = SSH_FXF_ACCESS_APPEND_DATA and or SSH_FXF_ACCESS_APPEND_DATA_ATOMIC</li> - * </ul> - * </li> - * </ul> - * <ul> - * <li>O_CREAT - * <ul> - * <li>flags = SSH_FXF_OPEN_OR_CREATE</li> - * </ul> - * </li> - * </ul> - * <ul> - * <li>O_TRUNC - * <ul> - * <li>flags = SSH_FXF_TRUNCATE_EXISTING</li> - * </ul> - * </li> - * </ul> - * <ul> - * <li>O_TRUNC|O_CREATE - * <ul> - * <li>flags = SSH_FXF_CREATE_TRUNCATE</li> - * </ul> - * </li> - * </ul> - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public final class OpenFlags { - private OpenFlags() { - } - - /** - * Disposition is a 3 bit field that controls how the file is opened. - * The server MUST support these bits (possible enumaration values: - * SSH_FXF_CREATE_NEW, SSH_FXF_CREATE_TRUNCATE, SSH_FXF_OPEN_EXISTING, - * SSH_FXF_OPEN_OR_CREATE or SSH_FXF_TRUNCATE_EXISTING). - */ - public static final int SSH_FXF_ACCESS_DISPOSITION = 0x00000007; - - /** - * A new file is created; if the file already exists, the server - * MUST return status SSH_FX_FILE_ALREADY_EXISTS. - */ - public static final int SSH_FXF_CREATE_NEW = 0x00000000; - - /** - * A new file is created; if the file already exists, it is opened - * and truncated. - */ - public static final int SSH_FXF_CREATE_TRUNCATE = 0x00000001; - - /** - * An existing file is opened. If the file does not exist, the - * server MUST return SSH_FX_NO_SUCH_FILE. If a directory in the - * path does not exist, the server SHOULD return - * SSH_FX_NO_SUCH_PATH. It is also acceptable if the server - * returns SSH_FX_NO_SUCH_FILE in this case. - */ - public static final int SSH_FXF_OPEN_EXISTING = 0x00000002; - - /** - * If the file exists, it is opened. If the file does not exist, - * it is created. - */ - public static final int SSH_FXF_OPEN_OR_CREATE = 0x00000003; - - /** - * An existing file is opened and truncated. If the file does not - * exist, the server MUST return the same error codes as defined - * for SSH_FXF_OPEN_EXISTING. - */ - public static final int SSH_FXF_TRUNCATE_EXISTING = 0x00000004; - - /** - * Data is always written at the end of the file. The offset field - * of the SSH_FXP_WRITE requests are ignored. - * <p/> - * Data is not required to be appended atomically. This means that - * if multiple writers attempt to append data simultaneously, data - * from the first may be lost. However, data MAY be appended - * atomically. - */ - public static final int SSH_FXF_ACCESS_APPEND_DATA = 0x00000008; - - /** - * Data is always written at the end of the file. The offset field - * of the SSH_FXP_WRITE requests are ignored. - * <p/> - * Data MUST be written atomically so that there is no chance that - * multiple appenders can collide and result in data being lost. - * <p/> - * If both append flags are specified, the server SHOULD use atomic - * append if it is available, but SHOULD use non-atomic appends - * otherwise. The server SHOULD NOT fail the request in this case. - */ - public static final int SSH_FXF_ACCESS_APPEND_DATA_ATOMIC = 0x00000010; - - /** - * Indicates that the server should treat the file as text and - * convert it to the canonical newline convention in use. - * (See Determining Server Newline Convention in section 5.3 in the - * SFTP standard draft). - * <p/> - * When a file is opened with this flag, the offset field in the read - * and write functions is ignored. - * <p/> - * Servers MUST process multiple, parallel reads and writes correctly - * in this mode. Naturally, it is permissible for them to do this by - * serializing the requests. - * <p/> - * Clients SHOULD use the SSH_FXF_ACCESS_APPEND_DATA flag to append - * data to a text file rather then using write with a calculated offset. - */ - public static final int SSH_FXF_ACCESS_TEXT_MODE = 0x00000020; - - /** - * The server MUST guarantee that no other handle has been opened - * with ACE4_READ_DATA access, and that no other handle will be - * opened with ACE4_READ_DATA access until the client closes the - * handle. (This MUST apply both to other clients and to other - * processes on the server.) - * <p/> - * If there is a conflicting lock the server MUST return - * SSH_FX_LOCK_CONFLICT. If the server cannot make the locking - * guarantee, it MUST return SSH_FX_OP_UNSUPPORTED. - * <p/> - * Other handles MAY be opened for ACE4_WRITE_DATA or any other - * combination of accesses, as long as ACE4_READ_DATA is not included - * in the mask. - */ - public static final int SSH_FXF_ACCESS_BLOCK_READ = 0x00000040; - - /** - * The server MUST guarantee that no other handle has been opened - * with ACE4_WRITE_DATA or ACE4_APPEND_DATA access, and that no other - * handle will be opened with ACE4_WRITE_DATA or ACE4_APPEND_DATA - * access until the client closes the handle. (This MUST apply both - * to other clients and to other processes on the server.) - * <p/> - * If there is a conflicting lock the server MUST return - * SSH_FX_LOCK_CONFLICT. If the server cannot make the locking - * guarantee, it MUST return SSH_FX_OP_UNSUPPORTED. - * <p/> - * Other handles MAY be opened for ACE4_READ_DATA or any other - * combination of accesses, as long as neither ACE4_WRITE_DATA nor - * ACE4_APPEND_DATA are included in the mask. - */ - public static final int SSH_FXF_ACCESS_BLOCK_WRITE = 0x00000080; - - /** - * The server MUST guarantee that no other handle has been opened - * with ACE4_DELETE access, opened with the - * SSH_FXF_ACCESS_DELETE_ON_CLOSE flag set, and that no other handle - * will be opened with ACE4_DELETE access or with the - * SSH_FXF_ACCESS_DELETE_ON_CLOSE flag set, and that the file itself - * is not deleted in any other way until the client closes the handle. - * <p/> - * If there is a conflicting lock the server MUST return - * SSH_FX_LOCK_CONFLICT. If the server cannot make the locking - * guarantee, it MUST return SSH_FX_OP_UNSUPPORTED. - */ - public static final int SSH_FXF_ACCESS_BLOCK_DELETE = 0x00000100; - - /** - * If this bit is set, the above BLOCK modes are advisory. In advisory - * mode, only other accesses that specify a BLOCK mode need be - * considered when determining whether the BLOCK can be granted, - * and the server need not prevent I/O operations that violate the - * block mode. - * <p/> - * The server MAY perform mandatory locking even if the BLOCK_ADVISORY - * bit is set. - */ - public static final int SSH_FXF_ACCESS_BLOCK_ADVISORY = 0x00000200; - - /** - * If the final component of the path is a symlink, then the open - * MUST fail, and the error SSH_FX_LINK_LOOP MUST be returned. - */ - public static final int SSH_FXF_ACCESS_NOFOLLOW = 0x00000400; - - /** - * The file should be deleted when the last handle to it is closed. - * (The last handle may not be an sftp-handle.) This MAY be emulated - * by a server if the OS doesn't support it by deleting the file when - * this handle is closed. - * <p/> - * It is implementation specific whether the directory entry is - * removed immediately or when the handle is closed. - */ - public static final int SSH_FXF_ACCESS_DELETE_ON_CLOSE = 0x00000800; -}
--- a/src/ch/ethz/ssh2/sftp/Packet.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.sftp; - -/** - * SFTP Paket Types - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class Packet { - public static final int SSH_FXP_INIT = 1; - public static final int SSH_FXP_VERSION = 2; - public static final int SSH_FXP_OPEN = 3; - public static final int SSH_FXP_CLOSE = 4; - public static final int SSH_FXP_READ = 5; - public static final int SSH_FXP_WRITE = 6; - public static final int SSH_FXP_LSTAT = 7; - public static final int SSH_FXP_FSTAT = 8; - public static final int SSH_FXP_SETSTAT = 9; - public static final int SSH_FXP_FSETSTAT = 10; - public static final int SSH_FXP_OPENDIR = 11; - public static final int SSH_FXP_READDIR = 12; - public static final int SSH_FXP_REMOVE = 13; - public static final int SSH_FXP_MKDIR = 14; - public static final int SSH_FXP_RMDIR = 15; - public static final int SSH_FXP_REALPATH = 16; - public static final int SSH_FXP_STAT = 17; - public static final int SSH_FXP_RENAME = 18; - public static final int SSH_FXP_READLINK = 19; - public static final int SSH_FXP_SYMLINK = 20; - public static final int SSH_FXP_LINK = 21; - - public static final int SSH_FXP_STATUS = 101; - public static final int SSH_FXP_HANDLE = 102; - public static final int SSH_FXP_DATA = 103; - public static final int SSH_FXP_NAME = 104; - public static final int SSH_FXP_ATTRS = 105; - - /** - * SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY packets can be used to - * implement extensions, which can be vendor specific. - */ - public static final int SSH_FXP_EXTENDED = 200; - /** - * SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY packets can be used to - * implement extensions, which can be vendor specific. - */ - public static final int SSH_FXP_EXTENDED_REPLY = 201; - - public static String forName(int type) { - switch (type) { - case SSH_FXP_INIT: - return "SSH_FXP_INIT"; - - case SSH_FXP_VERSION: - return "SSH_FXP_VERSION"; - - case SSH_FXP_OPEN: - return "SSH_FXP_OPEN"; - - case SSH_FXP_CLOSE: - return "SSH_FXP_CLOSE"; - - case SSH_FXP_READ: - return "SSH_FXP_READ"; - - case SSH_FXP_WRITE: - return "SSH_FXP_WRITE"; - - case SSH_FXP_LSTAT: - return "SSH_FXP_LSTAT"; - - case SSH_FXP_FSTAT: - return "SSH_FXP_FSTAT"; - - case SSH_FXP_SETSTAT: - return "SSH_FXP_SETSTAT"; - - case SSH_FXP_FSETSTAT: - return "SSH_FXP_FSETSTAT"; - - case SSH_FXP_OPENDIR: - return "SSH_FXP_OPENDIR"; - - case SSH_FXP_READDIR: - return "SSH_FXP_READDIR"; - - case SSH_FXP_REMOVE: - return "SSH_FXP_REMOVE"; - - case SSH_FXP_MKDIR: - return "SSH_FXP_MKDIR"; - - case SSH_FXP_RMDIR: - return "SSH_FXP_RMDIR"; - - case SSH_FXP_REALPATH: - return "SSH_FXP_REALPATH"; - - case SSH_FXP_STAT: - return "SSH_FXP_STAT"; - - case SSH_FXP_RENAME: - return "SSH_FXP_RENAME"; - - case SSH_FXP_READLINK: - return "SSH_FXP_READLINK"; - - case SSH_FXP_SYMLINK: - return "SSH_FXP_SYMLINK"; - - case SSH_FXP_STATUS: - return "SSH_FXP_STATUS"; - - case SSH_FXP_HANDLE: - return "SSH_FXP_HANDLE"; - - case SSH_FXP_DATA: - return "SSH_FXP_DATA"; - - case SSH_FXP_NAME: - return "SSH_FXP_NAME"; - - case SSH_FXP_ATTRS: - return "SSH_FXP_ATTRS"; - - case SSH_FXP_EXTENDED: - return "SSH_FXP_EXTENDED"; - - case SSH_FXP_EXTENDED_REPLY: - return "SSH_FXP_EXTENDED_REPLY"; - } - - return null; - } -}
--- a/src/ch/ethz/ssh2/signature/DSASHA1Verify.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,230 +0,0 @@ - -package ch.ethz.ssh2.signature; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.Signature; -import java.security.SignatureException; -import java.security.interfaces.DSAParams; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.DSAPublicKey; -import java.security.spec.DSAPublicKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; - -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.packets.TypesWriter; - - -/** - * DSASHA1Verify. - * - * @author Christian Plattner, plattner@trilead.com - * @version $Id: DSASHA1Verify.java,v 1.2 2008/04/01 12:38:09 cplattne Exp $ - */ -public class DSASHA1Verify { - private static final Logger log = Logger.getLogger(DSASHA1Verify.class); - - public static DSAPublicKey decodeSSHDSAPublicKey(byte[] key) throws IOException { - TypesReader tr = new TypesReader(key); - String key_format = tr.readString(); - - if (key_format.equals("ssh-dss") == false) - throw new IllegalArgumentException("This is not a ssh-dss public key!"); - - BigInteger p = tr.readMPINT(); - BigInteger q = tr.readMPINT(); - BigInteger g = tr.readMPINT(); - BigInteger y = tr.readMPINT(); - - if (tr.remain() != 0) - throw new IOException("Padding in DSA public key!"); - - try { - KeyFactory kf = KeyFactory.getInstance("DSA"); - KeySpec ks = new DSAPublicKeySpec(y, p, q, g); - return (DSAPublicKey) kf.generatePublic(ks); - } - catch (NoSuchAlgorithmException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - catch (InvalidKeySpecException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - } - - public static byte[] encodeSSHDSAPublicKey(DSAPublicKey pk) throws IOException { - TypesWriter tw = new TypesWriter(); - tw.writeString("ssh-dss"); - DSAParams params = pk.getParams(); - tw.writeMPInt(params.getP()); - tw.writeMPInt(params.getQ()); - tw.writeMPInt(params.getG()); - tw.writeMPInt(pk.getY()); - return tw.getBytes(); - } - - /** - * Convert from Java's signature ASN.1 encoding to the SSH spec. - * <p> - * Java ASN.1 encoding: - * <pre> - * SEQUENCE ::= { - * r INTEGER, - * s INTEGER - * } - * </pre> - */ - public static byte[] encodeSSHDSASignature(byte[] ds) { - TypesWriter tw = new TypesWriter(); - tw.writeString("ssh-dss"); - int len, index; - index = 3; - len = ds[index++] & 0xff; - byte[] r = new byte[len]; - System.arraycopy(ds, index, r, 0, r.length); - index = index + len + 1; - len = ds[index++] & 0xff; - byte[] s = new byte[len]; - System.arraycopy(ds, index, s, 0, s.length); - byte[] a40 = new byte[40]; - /* Patch (unsigned) r and s into the target array. */ - int r_copylen = (r.length < 20) ? r.length : 20; - int s_copylen = (s.length < 20) ? s.length : 20; - System.arraycopy(r, r.length - r_copylen, a40, 20 - r_copylen, r_copylen); - System.arraycopy(s, s.length - s_copylen, a40, 40 - s_copylen, s_copylen); - tw.writeString(a40, 0, 40); - return tw.getBytes(); - } - - public static byte[] decodeSSHDSASignature(byte[] sig) throws IOException { - byte[] rsArray = null; - - if (sig.length == 40) { - /* OK, another broken SSH server. */ - rsArray = sig; - } - else { - /* Hopefully a server obeying the standard... */ - TypesReader tr = new TypesReader(sig); - String sig_format = tr.readString(); - - if (sig_format.equals("ssh-dss") == false) - throw new IOException("Peer sent wrong signature format"); - - rsArray = tr.readByteString(); - - if (rsArray.length != 40) - throw new IOException("Peer sent corrupt signature"); - - if (tr.remain() != 0) - throw new IOException("Padding in DSA signature!"); - } - - int i = 0; - int j = 0; - byte[] tmp; - - if (rsArray[0] == 0 && rsArray[1] == 0 && rsArray[2] == 0) { - j = ((rsArray[i++] << 24) & 0xff000000) | ((rsArray[i++] << 16) & 0x00ff0000) - | ((rsArray[i++] << 8) & 0x0000ff00) | ((rsArray[i++]) & 0x000000ff); - i += j; - j = ((rsArray[i++] << 24) & 0xff000000) | ((rsArray[i++] << 16) & 0x00ff0000) - | ((rsArray[i++] << 8) & 0x0000ff00) | ((rsArray[i++]) & 0x000000ff); - tmp = new byte[j]; - System.arraycopy(rsArray, i, tmp, 0, j); - rsArray = tmp; - } - - /* ASN.1 */ - int frst = ((rsArray[0] & 0x80) != 0 ? 1 : 0); - int scnd = ((rsArray[20] & 0x80) != 0 ? 1 : 0); - /* Calculate output length */ - int length = rsArray.length + 6 + frst + scnd; - tmp = new byte[length]; - /* DER-encoding to match Java */ - tmp[0] = (byte) 0x30; - - if (rsArray.length != 40) - throw new IOException("Peer sent corrupt signature"); - - /* Calculate length */ - tmp[1] = (byte) 0x2c; - tmp[1] += frst; - tmp[1] += scnd; - /* First item */ - tmp[2] = (byte) 0x02; - /* First item length */ - tmp[3] = (byte) 0x14; - tmp[3] += frst; - /* Copy in the data for first item */ - System.arraycopy(rsArray, 0, tmp, 4 + frst, 20); - /* Second item */ - tmp[4 + tmp[3]] = (byte) 0x02; - /* Second item length */ - tmp[5 + tmp[3]] = (byte) 0x14; - tmp[5 + tmp[3]] += scnd; - /* Copy in the data for the second item */ - System.arraycopy(rsArray, 20, tmp, 6 + tmp[3] + scnd, 20); - /* Swap buffers */ - rsArray = tmp; - return rsArray; - } - - public static boolean verifySignature(byte[] message, byte[] ds, DSAPublicKey dpk) throws IOException { - try { - Signature s = Signature.getInstance("SHA1withDSA"); - s.initVerify(dpk); - s.update(message); - return s.verify(ds); - } - catch (NoSuchAlgorithmException e) { - IOException ex = new IOException("No such algorithm"); - ex.initCause(e); - throw ex; - } - catch (InvalidKeyException e) { - IOException ex = new IOException("No such algorithm"); - ex.initCause(e); - throw ex; - } - catch (SignatureException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - } - - public static byte[] generateSignature(byte[] message, DSAPrivateKey pk, SecureRandom rnd) throws IOException { - try { - Signature s = Signature.getInstance("SHA1withDSA"); - s.initSign(pk); - s.update(message); - return s.sign(); - } - catch (NoSuchAlgorithmException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - catch (InvalidKeyException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - catch (SignatureException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - } -}
--- a/src/ch/ethz/ssh2/signature/ECDSASHA2Verify.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,488 +0,0 @@ -/** - * - */ -package ch.ethz.ssh2.signature; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.math.BigInteger; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.Signature; -import java.security.SignatureException; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECFieldFp; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.EllipticCurve; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import java.util.Map; -import java.util.TreeMap; - -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.packets.TypesWriter; - -/** - * @author Kenny Root - * - */ -public class ECDSASHA2Verify { - private static final Logger log = Logger.getLogger(ECDSASHA2Verify.class); - - public static final String ECDSA_SHA2_PREFIX = "ecdsa-sha2-"; - - private static final String NISTP256 = "nistp256"; - private static final String NISTP256_OID = "1.2.840.10045.3.1.7"; - private static final String NISTP384 = "nistp384"; - private static final String NISTP384_OID = "1.3.132.0.34"; - private static final String NISTP521 = "nistp521"; - private static final String NISTP521_OID = "1.3.132.0.35"; - - private static final Map<String, ECParameterSpec> CURVES = new TreeMap<String, ECParameterSpec>(); - static { - CURVES.put(NISTP256, EllipticCurves.nistp256); - CURVES.put(NISTP384, EllipticCurves.nistp384); - CURVES.put(NISTP521, EllipticCurves.nistp521); - } - - private static final Map<Integer, String> CURVE_SIZES = new TreeMap<Integer, String>(); - static { - CURVE_SIZES.put(256, NISTP256); - CURVE_SIZES.put(384, NISTP384); - CURVE_SIZES.put(521, NISTP521); - } - - private static final Map<String, String> CURVE_OIDS = new TreeMap<String, String>(); - static { - CURVE_OIDS.put(NISTP256_OID, NISTP256); - CURVE_OIDS.put(NISTP384_OID, NISTP256); - CURVE_OIDS.put(NISTP521_OID, NISTP256); - } - - public static int[] getCurveSizes() { - int[] keys = new int[CURVE_SIZES.size()]; - int i = 0; - - for (Integer n : CURVE_SIZES.keySet().toArray(new Integer[keys.length])) { - keys[i++] = n; - } - - return keys; - } - - public static ECParameterSpec getCurveForSize(int size) { - final String name = CURVE_SIZES.get(size); - - if (name == null) { - return null; - } - - return CURVES.get(name); - } - - public static ECPublicKey decodeSSHECDSAPublicKey(byte[] key) throws IOException { - TypesReader tr = new TypesReader(key); - String key_format = tr.readString(); - - if (key_format.startsWith(ECDSA_SHA2_PREFIX) == false) - throw new IllegalArgumentException("This is not an ECDSA public key"); - - String curveName = tr.readString(); - byte[] groupBytes = tr.readByteString(); - - if (tr.remain() != 0) - throw new IOException("Padding in ECDSA public key!"); - - if (key_format.equals(ECDSA_SHA2_PREFIX + curveName) == false) { - throw new IOException("Key format is inconsistent with curve name: " + key_format - + " != " + curveName); - } - - ECParameterSpec params = CURVES.get(curveName); - - if (params == null) { - throw new IOException("Curve is not supported: " + curveName); - } - - ECPoint group = ECDSASHA2Verify.decodeECPoint(groupBytes, params.getCurve()); - - if (group == null) { - throw new IOException("Invalid ECDSA group"); - } - - KeySpec keySpec = new ECPublicKeySpec(group, params); - - try { - KeyFactory kf = KeyFactory.getInstance("EC"); - return (ECPublicKey) kf.generatePublic(keySpec); - } - catch (NoSuchAlgorithmException nsae) { - IOException ioe = new IOException("No EC KeyFactory available"); - ioe.initCause(nsae); - throw ioe; - } - catch (InvalidKeySpecException ikse) { - IOException ioe = new IOException("No EC KeyFactory available"); - ioe.initCause(ikse); - throw ioe; - } - } - - public static byte[] encodeSSHECDSAPublicKey(ECPublicKey key) throws IOException { - TypesWriter tw = new TypesWriter(); - String curveName = getCurveName(key.getParams()); - String keyFormat = ECDSA_SHA2_PREFIX + curveName; - tw.writeString(keyFormat); - tw.writeString(curveName); - byte[] encoded = encodeECPoint(key.getW(), key.getParams().getCurve()); - tw.writeString(encoded, 0, encoded.length); - return tw.getBytes(); - } - - public static String getCurveName(ECParameterSpec params) throws IOException { - int fieldSize = getCurveSize(params); - final String curveName = getCurveName(fieldSize); - - if (curveName == null) { - throw new IOException("invalid curve size " + fieldSize); - } - - return curveName; - } - - public static String getCurveName(int fieldSize) { - String curveName = CURVE_SIZES.get(fieldSize); - - if (curveName == null) { - return null; - } - - return curveName; - } - - public static int getCurveSize(ECParameterSpec params) { - return params.getCurve().getField().getFieldSize(); - } - - public static ECParameterSpec getCurveForOID(String oid) { - String name = CURVE_OIDS.get(oid); - - if (name == null) - return null; - - return CURVES.get(name); - } - - public static byte[] decodeSSHECDSASignature(byte[] sig) throws IOException { - byte[] rsArray = null; - TypesReader tr = new TypesReader(sig); - String sig_format = tr.readString(); - - if (sig_format.startsWith(ECDSA_SHA2_PREFIX) == false) - throw new IOException("Peer sent wrong signature format"); - - String curveName = sig_format.substring(ECDSA_SHA2_PREFIX.length()); - - if (CURVES.containsKey(curveName) == false) { - throw new IOException("Unsupported curve: " + curveName); - } - - rsArray = tr.readByteString(); - - if (tr.remain() != 0) - throw new IOException("Padding in ECDSA signature!"); - - byte[] rArray; - byte[] sArray; - { - TypesReader rsReader = new TypesReader(rsArray); - rArray = rsReader.readMPINT().toByteArray(); - sArray = rsReader.readMPINT().toByteArray(); - } - int first = rArray.length; - int second = sArray.length; - - /* We can't have the high bit set, so add an extra zero at the beginning if so. */ - if ((rArray[0] & 0x80) != 0) { - first++; - } - - if ((sArray[0] & 0x80) != 0) { - second++; - } - - /* Calculate total output length */ - ByteArrayOutputStream os = new ByteArrayOutputStream(6 + first + second); - /* ASN.1 SEQUENCE tag */ - os.write(0x30); - /* Size of SEQUENCE */ - writeLength(4 + first + second, os); - /* ASN.1 INTEGER tag */ - os.write(0x02); - /* "r" INTEGER length */ - writeLength(first, os); - - /* Copy in the "r" INTEGER */ - if (first != rArray.length) { - os.write(0x00); - } - - os.write(rArray); - /* ASN.1 INTEGER tag */ - os.write(0x02); - /* "s" INTEGER length */ - writeLength(second, os); - - /* Copy in the "s" INTEGER */ - if (second != sArray.length) { - os.write(0x00); - } - - os.write(sArray); - return os.toByteArray(); - } - - private static final void writeLength(int length, OutputStream os) throws IOException { - if (length <= 0x7F) { - os.write(length); - return; - } - - int numOctets = 0; - int lenCopy = length; - - while (lenCopy != 0) { - lenCopy >>>= 8; - numOctets++; - } - - os.write(0x80 | numOctets); - - for (int i = (numOctets - 1) * 8; i >= 0; i -= 8) { - os.write((byte)(length >> i)); - } - } - - public static byte[] encodeSSHECDSASignature(byte[] sig, ECParameterSpec params) throws IOException { - TypesWriter tw = new TypesWriter(); - String curveName = getCurveName(params); - tw.writeString(ECDSA_SHA2_PREFIX + curveName); - - if ((sig[0] != 0x30) || (sig[1] != sig.length - 2) || (sig[2] != 0x02)) { - throw new IOException("Invalid signature format"); - } - - int rLength = sig[3]; - - if ((rLength + 6 > sig.length) || (sig[4 + rLength] != 0x02)) { - throw new IOException("Invalid signature format"); - } - - int sLength = sig[5 + rLength]; - - if (6 + rLength + sLength > sig.length) { - throw new IOException("Invalid signature format"); - } - - byte[] rArray = new byte[rLength]; - byte[] sArray = new byte[sLength]; - System.arraycopy(sig, 4, rArray, 0, rLength); - System.arraycopy(sig, 6 + rLength, sArray, 0, sLength); - BigInteger r = new BigInteger(rArray); - BigInteger s = new BigInteger(sArray); - // Write the <r,s> to its own types writer. - TypesWriter rsWriter = new TypesWriter(); - rsWriter.writeMPInt(r); - rsWriter.writeMPInt(s); - byte[] encoded = rsWriter.getBytes(); - tw.writeString(encoded, 0, encoded.length); - return tw.getBytes(); - } - - public static byte[] generateSignature(byte[] message, ECPrivateKey pk) throws IOException { - final String algo = getSignatureAlgorithmForParams(pk.getParams()); - - try { - Signature s = Signature.getInstance(algo); - s.initSign(pk); - s.update(message); - return s.sign(); - } - catch (NoSuchAlgorithmException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - catch (InvalidKeyException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - catch (SignatureException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - } - - public static boolean verifySignature(byte[] message, byte[] ds, ECPublicKey dpk) throws IOException { - final String algo = getSignatureAlgorithmForParams(dpk.getParams()); - - try { - Signature s = Signature.getInstance(algo); - s.initVerify(dpk); - s.update(message); - return s.verify(ds); - } - catch (NoSuchAlgorithmException e) { - IOException ex = new IOException("No such algorithm"); - ex.initCause(e); - throw ex; - } - catch (InvalidKeyException e) { - IOException ex = new IOException("No such algorithm"); - ex.initCause(e); - throw ex; - } - catch (SignatureException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - } - - private static String getSignatureAlgorithmForParams(ECParameterSpec params) { - int size = getCurveSize(params); - - if (size <= 256) { - return "SHA256withECDSA"; - } - else if (size <= 384) { - return "SHA384withECDSA"; - } - else { - return "SHA512withECDSA"; - } - } - - public static String getDigestAlgorithmForParams(ECParameterSpec params) { - int size = getCurveSize(params); - - if (size <= 256) { - return "SHA256"; - } - else if (size <= 384) { - return "SHA384"; - } - else { - return "SHA512"; - } - } - - /** - * Decode an OctetString to EllipticCurvePoint according to SECG 2.3.4 - */ - public static ECPoint decodeECPoint(byte[] M, EllipticCurve curve) { - if (M.length == 0) { - return null; - } - - // M has len 2 ceil(log_2(q)/8) + 1 ? - int elementSize = (curve.getField().getFieldSize() + 7) / 8; - - if (M.length != 2 * elementSize + 1) { - return null; - } - - // step 3.2 - if (M[0] != 0x04) { - return null; - } - - // Step 3.3 - byte[] xp = new byte[elementSize]; - System.arraycopy(M, 1, xp, 0, elementSize); - // Step 3.4 - byte[] yp = new byte[elementSize]; - System.arraycopy(M, 1 + elementSize, yp, 0, elementSize); - ECPoint P = new ECPoint(new BigInteger(1, xp), new BigInteger(1, yp)); - // TODO check point 3.5 - // Step 3.6 - return P; - } - - /** - * Encode EllipticCurvePoint to an OctetString - */ - public static byte[] encodeECPoint(ECPoint group, EllipticCurve curve) { - // M has len 2 ceil(log_2(q)/8) + 1 ? - int elementSize = (curve.getField().getFieldSize() + 7) / 8; - byte[] M = new byte[2 * elementSize + 1]; - // Uncompressed format - M[0] = 0x04; - { - byte[] affineX = removeLeadingZeroes(group.getAffineX().toByteArray()); - System.arraycopy(affineX, 0, M, 1 + elementSize - affineX.length, affineX.length); - } - { - byte[] affineY = removeLeadingZeroes(group.getAffineY().toByteArray()); - System.arraycopy(affineY, 0, M, 1 + elementSize + elementSize - affineY.length, - affineY.length); - } - return M; - } - - private static byte[] removeLeadingZeroes(byte[] input) { - if (input[0] != 0x00) { - return input; - } - - int pos = 1; - - while (pos < input.length - 1 && input[pos] == 0x00) { - pos++; - } - - byte[] output = new byte[input.length - pos]; - System.arraycopy(input, pos, output, 0, output.length); - return output; - } - - public static class EllipticCurves { - public static ECParameterSpec nistp256 = new ECParameterSpec( - new EllipticCurve( - new ECFieldFp(new BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16)), - new BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16), - new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)), - new ECPoint(new BigInteger("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 16), - new BigInteger("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", 16)), - new BigInteger("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 16), - 1); - - public static ECParameterSpec nistp384 = new ECParameterSpec( - new EllipticCurve( - new ECFieldFp(new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", 16)), - new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", 16), - new BigInteger("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", 16)), - new ECPoint(new BigInteger("AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", 16), - new BigInteger("3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", 16)), - new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", 16), - 1); - - public static ECParameterSpec nistp521 = new ECParameterSpec( - new EllipticCurve( - new ECFieldFp(new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16)), - new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", 16), - new BigInteger("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 16)), - new ECPoint(new BigInteger("00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", 16), - new BigInteger("011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", 16)), - new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 16), - 1); - } -}
--- a/src/ch/ethz/ssh2/signature/RSASHA1Verify.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ - -package ch.ethz.ssh2.signature; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.Signature; -import java.security.SignatureException; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import java.security.spec.RSAPublicKeySpec; - -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.TypesReader; -import ch.ethz.ssh2.packets.TypesWriter; - - -/** - * RSASHA1Verify. - * - * @author Christian Plattner, plattner@trilead.com - * @version $Id: RSASHA1Verify.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $ - */ -public class RSASHA1Verify { - private static final Logger log = Logger.getLogger(RSASHA1Verify.class); - - public static RSAPublicKey decodeSSHRSAPublicKey(byte[] key) throws IOException { - TypesReader tr = new TypesReader(key); - String key_format = tr.readString(); - - if (key_format.equals("ssh-rsa") == false) - throw new IllegalArgumentException("This is not a ssh-rsa public key"); - - BigInteger e = tr.readMPINT(); - BigInteger n = tr.readMPINT(); - - if (tr.remain() != 0) - throw new IOException("Padding in RSA public key!"); - - KeySpec keySpec = new RSAPublicKeySpec(n, e); - - try { - KeyFactory kf = KeyFactory.getInstance("RSA"); - return (RSAPublicKey) kf.generatePublic(keySpec); - } - catch (NoSuchAlgorithmException nsae) { - IOException ioe = new IOException("No RSA KeyFactory available"); - ioe.initCause(nsae); - throw ioe; - } - catch (InvalidKeySpecException ikse) { - IOException ioe = new IOException("No RSA KeyFactory available"); - ioe.initCause(ikse); - throw ioe; - } - } - - public static byte[] encodeSSHRSAPublicKey(RSAPublicKey pk) throws IOException { - TypesWriter tw = new TypesWriter(); - tw.writeString("ssh-rsa"); - tw.writeMPInt(pk.getPublicExponent()); - tw.writeMPInt(pk.getModulus()); - return tw.getBytes(); - } - - public static byte[] decodeSSHRSASignature(byte[] sig) throws IOException { - TypesReader tr = new TypesReader(sig); - String sig_format = tr.readString(); - - if (sig_format.equals("ssh-rsa") == false) - throw new IOException("Peer sent wrong signature format"); - - /* S is NOT an MPINT. "The value for 'rsa_signature_blob' is encoded as a string - * containing s (which is an integer, without lengths or padding, unsigned and in - * network byte order)." See also below. - */ - byte[] s = tr.readByteString(); - - if (s.length == 0) - throw new IOException("Error in RSA signature, S is empty."); - - if (log.isEnabled()) { - log.info("Decoding ssh-rsa signature string (length: " + s.length + ")"); - } - - if (tr.remain() != 0) - throw new IOException("Padding in RSA signature!"); - - if (s[0] == 0 && s[1] == 0 && s[2] == 0) { - int i = 0; - int j = ((s[i++] << 24) & 0xff000000) | ((s[i++] << 16) & 0x00ff0000) - | ((s[i++] << 8) & 0x0000ff00) | ((s[i++]) & 0x000000ff); - i += j; - j = ((s[i++] << 24) & 0xff000000) | ((s[i++] << 16) & 0x00ff0000) - | ((s[i++] << 8) & 0x0000ff00) | ((s[i++]) & 0x000000ff); - byte[] tmp = new byte[j]; - System.arraycopy(s, i, tmp, 0, j); - sig = tmp; - } - - return s; - } - - public static byte[] encodeSSHRSASignature(byte[] s) throws IOException { - TypesWriter tw = new TypesWriter(); - tw.writeString("ssh-rsa"); - - /* S is NOT an MPINT. "The value for 'rsa_signature_blob' is encoded as a string - * containing s (which is an integer, without lengths or padding, unsigned and in - * network byte order)." - */ - - /* Remove first zero sign byte, if present */ - - if ((s.length > 1) && (s[0] == 0x00)) - tw.writeString(s, 1, s.length - 1); - else - tw.writeString(s, 0, s.length); - - return tw.getBytes(); - } - - public static byte[] generateSignature(byte[] message, RSAPrivateKey pk) throws IOException { - try { - Signature s = Signature.getInstance("SHA1withRSA"); - s.initSign(pk); - s.update(message); - return s.sign(); - } - catch (NoSuchAlgorithmException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - catch (InvalidKeyException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - catch (SignatureException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - } - - public static boolean verifySignature(byte[] message, byte[] ds, RSAPublicKey dpk) throws IOException { - try { - Signature s = Signature.getInstance("SHA1withRSA"); - s.initVerify(dpk); - s.update(message); - return s.verify(ds); - } - catch (NoSuchAlgorithmException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - catch (InvalidKeyException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - catch (SignatureException e) { - IOException ex = new IOException(); - ex.initCause(e); - throw ex; - } - } -}
--- a/src/ch/ethz/ssh2/transport/ClientKexManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,326 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.transport; - -import java.io.IOException; -import java.security.DigestException; -import java.security.SecureRandom; -import java.security.interfaces.DSAPublicKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPublicKey; - -import ch.ethz.ssh2.ConnectionInfo; -import ch.ethz.ssh2.PacketTypeException; -import ch.ethz.ssh2.ServerHostKeyVerifier; -import ch.ethz.ssh2.compression.CompressionFactory; -import ch.ethz.ssh2.compression.Compressor; -import ch.ethz.ssh2.crypto.CryptoWishList; -import ch.ethz.ssh2.crypto.cipher.BlockCipher; -import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; -import ch.ethz.ssh2.crypto.dh.GenericDhExchange; -import ch.ethz.ssh2.crypto.dh.DhGroupExchange; -import ch.ethz.ssh2.crypto.digest.MAC; -import ch.ethz.ssh2.packets.PacketKexDHInit; -import ch.ethz.ssh2.packets.PacketKexDHReply; -import ch.ethz.ssh2.packets.PacketKexDhGexGroup; -import ch.ethz.ssh2.packets.PacketKexDhGexInit; -import ch.ethz.ssh2.packets.PacketKexDhGexReply; -import ch.ethz.ssh2.packets.PacketKexDhGexRequest; -import ch.ethz.ssh2.packets.PacketKexDhGexRequestOld; -import ch.ethz.ssh2.packets.PacketKexInit; -import ch.ethz.ssh2.packets.Packets; -import ch.ethz.ssh2.signature.DSASHA1Verify; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; -import ch.ethz.ssh2.signature.RSASHA1Verify; - -/** - * @version $Id: ClientKexManager.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public class ClientKexManager extends KexManager { - - private final ServerHostKeyVerifier verifier; - - private final String hostname; - - private final int port; - - public ClientKexManager(TransportManager tm, ClientServerHello csh, CryptoWishList initialCwl, String hostname, int port, - ServerHostKeyVerifier keyVerifier, SecureRandom rnd) { - super(tm, csh, initialCwl, rnd); - this.hostname = hostname; - this.port = port; - this.verifier = keyVerifier; - } - - protected boolean verifySignature(byte[] sig, byte[] hostkey) throws IOException { - if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) { - byte[] rs = ECDSASHA2Verify.decodeSSHECDSASignature(sig); - ECPublicKey epk = ECDSASHA2Verify.decodeSSHECDSAPublicKey(hostkey); - log.debug("Verifying ecdsa signature"); - return ECDSASHA2Verify.verifySignature(kxs.H, rs, epk); - } - - if (kxs.np.server_host_key_algo.equals("ssh-rsa")) { - byte[] rs = RSASHA1Verify.decodeSSHRSASignature(sig); - RSAPublicKey rpk = RSASHA1Verify.decodeSSHRSAPublicKey(hostkey); - log.debug("Verifying ssh-rsa signature"); - return RSASHA1Verify.verifySignature(kxs.H, rs, rpk); - } - - if (kxs.np.server_host_key_algo.equals("ssh-dss")) { - byte[] ds = DSASHA1Verify.decodeSSHDSASignature(sig); - DSAPublicKey dpk = DSASHA1Verify.decodeSSHDSAPublicKey(hostkey); - log.debug("Verifying ssh-dss signature"); - return DSASHA1Verify.verifySignature(kxs.H, ds, dpk); - } - - throw new IOException("Unknown server host key algorithm '" + kxs.np.server_host_key_algo + "'"); - } - - public void handleFailure(final IOException failure) { - synchronized (accessLock) { - connectionClosed = true; - accessLock.notifyAll(); - } - } - - public synchronized void handleMessage(byte[] msg) throws IOException { - PacketKexInit kip; - - if (msg == null) { - synchronized (accessLock) { - connectionClosed = true; - accessLock.notifyAll(); - return; - } - } - - log.debug(String.format("client kex manager, packet type %d", msg[0])); - - if ((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) { - throw new PacketTypeException(msg[0]); - } - - if (ignore_next_kex_packet) { - ignore_next_kex_packet = false; - return; - } - - if (msg[0] == Packets.SSH_MSG_KEXINIT) { - if ((kxs != null) && (kxs.state != 0)) { - throw new PacketTypeException(msg[0]); - } - - if (kxs == null) { - /* - * Ah, OK, peer wants to do KEX. Let's be nice and play - * together. - */ - kxs = new KexState(); - kxs.dhgexParameters = nextKEXdhgexParameters; - kip = new PacketKexInit(nextKEXcryptoWishList, rnd); - kxs.localKEX = kip; - tm.sendKexMessage(kip.getPayload()); - } - - kip = new PacketKexInit(msg); - kxs.remoteKEX = kip; - kxs.np = mergeKexParameters(kxs.localKEX.getKexParameters(), kxs.remoteKEX.getKexParameters()); - - if (kxs.np == null) - throw new IOException("Cannot negotiate, proposals do not match."); - - if (kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) { - // Guess was wrong, we need to ignore the next kex packet. - ignore_next_kex_packet = true; - } - - if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1") || - kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha256")) { - if (kxs.dhgexParameters.getMin_group_len() == 0) { - PacketKexDhGexRequestOld dhgexreq = new PacketKexDhGexRequestOld(kxs.dhgexParameters); - tm.sendKexMessage(dhgexreq.getPayload()); - } - else { - PacketKexDhGexRequest dhgexreq = new PacketKexDhGexRequest(kxs.dhgexParameters); - tm.sendKexMessage(dhgexreq.getPayload()); - } - - if (kxs.np.kex_algo.endsWith("sha1")) { - kxs.hashAlgo = "SHA1"; - } - else { - kxs.hashAlgo = "SHA2"; - } - - kxs.state = 1; - return; - } - - if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || - kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp256") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp384") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) { - kxs.dhx = GenericDhExchange.getInstance(kxs.np.kex_algo); - kxs.dhx.init(kxs.np.kex_algo); - kxs.hashAlgo = kxs.dhx.getHashAlgo(); - PacketKexDHInit kp = new PacketKexDHInit(kxs.dhx.getE()); - tm.sendKexMessage(kp.getPayload()); - kxs.state = 1; - return; - } - - throw new IllegalStateException("Unkown KEX method!"); - } - - if (msg[0] == Packets.SSH_MSG_NEWKEYS) { - if (km == null) { - throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!"); - } - - BlockCipher cbc; - MAC mac; - Compressor comp; - - try { - cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_server_to_client, false, - km.enc_key_server_to_client, km.initial_iv_server_to_client); - - try { - mac = new MAC(kxs.np.mac_algo_server_to_client, km.integrity_key_server_to_client); - } - catch (DigestException e) { - throw new IOException(e); - } - - comp = CompressionFactory.createCompressor(kxs.np.comp_algo_server_to_client); - } - catch (IllegalArgumentException e) { - throw new IOException(e.getMessage()); - } - - tm.changeRecvCipher(cbc, mac); - tm.changeRecvCompression(comp); - ConnectionInfo sci = new ConnectionInfo(); - kexCount++; - sci.keyExchangeAlgorithm = kxs.np.kex_algo; - sci.keyExchangeCounter = kexCount; - sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server; - sci.serverToClientCryptoAlgorithm = kxs.np.enc_algo_server_to_client; - sci.clientToServerMACAlgorithm = kxs.np.mac_algo_client_to_server; - sci.serverToClientMACAlgorithm = kxs.np.mac_algo_server_to_client; - sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo; - sci.serverHostKey = kxs.remote_hostkey; - - synchronized (accessLock) { - lastConnInfo = sci; - accessLock.notifyAll(); - } - - kxs = null; - return; - } - - if ((kxs == null) || (kxs.state == 0)) { - throw new IOException("Unexpected Kex submessage!"); - } - - if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1") || - kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha256")) { - if (kxs.state == 1) { - PacketKexDhGexGroup dhgexgrp = new PacketKexDhGexGroup(msg); - kxs.dhgx = new DhGroupExchange(dhgexgrp.getP(), dhgexgrp.getG()); - kxs.dhgx.init(rnd); - PacketKexDhGexInit dhgexinit = new PacketKexDhGexInit(kxs.dhgx.getE()); - tm.sendKexMessage(dhgexinit.getPayload()); - kxs.state = 2; - return; - } - - if (kxs.state == 2) { - PacketKexDhGexReply dhgexrpl = new PacketKexDhGexReply(msg); - kxs.remote_hostkey = dhgexrpl.getHostKey(); - - if (verifier != null) { - try { - if (!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) { - throw new IOException("The server host key was not accepted by the verifier callback"); - } - } - catch (Exception e) { - throw new IOException( - "The server host key was not accepted by the verifier callback.", e); - } - } - - kxs.dhgx.setF(dhgexrpl.getF()); - - try { - kxs.H = kxs.dhgx.calculateH(kxs.hashAlgo, csh.getClientString(), csh.getServerString(), - kxs.localKEX.getPayload(), kxs.remoteKEX.getPayload(), dhgexrpl.getHostKey(), - kxs.dhgexParameters); - } - catch (IllegalArgumentException e) { - throw new IOException("KEX error.", e); - } - - if (!verifySignature(dhgexrpl.getSignature(), kxs.remote_hostkey)) { - throw new IOException("Invalid remote host key signature"); - } - - kxs.K = kxs.dhgx.getK(); - finishKex(true); - kxs.state = -1; - return; - } - - throw new IllegalStateException("Illegal State in KEX Exchange!"); - } - - if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || - kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp256") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp384") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) { - if (kxs.state == 1) { - PacketKexDHReply dhr = new PacketKexDHReply(msg); - kxs.remote_hostkey = dhr.getHostKey(); - - if (verifier != null) { - try { - if (!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) { - throw new IOException("The server host key was not accepted by the verifier callback"); - } - } - catch (Exception e) { - throw new IOException("The server host key was not accepted by the verifier callback", e); - } - } - - kxs.dhx.setF(dhr.getF().toByteArray()); - - try { - kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(), kxs.localKEX.getPayload(), - kxs.remoteKEX.getPayload(), dhr.getHostKey()); - } - catch (IllegalArgumentException e) { - throw new IOException("KEX error.", e); - } - - if (!verifySignature(dhr.getSignature(), kxs.remote_hostkey)) { - throw new IOException("Invalid remote host key signature"); - } - - kxs.K = kxs.dhx.getK(); - finishKex(true); - kxs.state = -1; - return; - } - } - - throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo)); - } -}
--- a/src/ch/ethz/ssh2/transport/ClientServerHello.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2.transport; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.io.OutputStream; - -import ch.ethz.ssh2.util.StringEncoder; - -/** - * @author Christian Plattner - * @version $Id: ClientServerHello.java 155 2014-04-28 12:01:19Z dkocher@sudo.ch $ - */ -public class ClientServerHello { - private final String client_line; - private final String server_line; - - public final static int readLineRN(InputStream is, byte[] buffer) throws IOException { - int pos = 0; - boolean need10 = false; - int len = 0; - - while (true) { - int c = is.read(); - - if (c == -1) - throw new IOException("Premature connection close"); - - buffer[pos++] = (byte) c; - - if (c == 13) { - need10 = true; - continue; - } - - if (c == 10) - break; - - if (need10 == true) - throw new IOException("Malformed line sent by the server, the line does not end correctly."); - - len++; - - if (pos >= buffer.length) - throw new IOException("The server sent a too long line."); - } - - return len; - } - - private ClientServerHello(String client_line, String server_line) { - this.client_line = client_line; - this.server_line = server_line; - } - - public static ClientServerHello clientHello(String softwareversion, InputStream bi, OutputStream bo) - throws IOException { - return exchange(softwareversion, bi, bo, true); - } - - public static ClientServerHello serverHello(String softwareversion, InputStream bi, OutputStream bo) - throws IOException { - return exchange(softwareversion, bi, bo, false); - } - - private static ClientServerHello exchange(String softwareversion, InputStream bi, OutputStream bo, boolean clientMode) - throws IOException { - String localIdentifier = String.format("SSH-2.0-%s", softwareversion); - bo.write(StringEncoder.GetBytes(String.format("%s\r\n", localIdentifier))); - bo.flush(); - // Expect SSH-protoversion-softwareversion SP comments CR LF - byte[] serverVersion = new byte[512]; - String remoteIdentifier = null; - for (int i = 0; i < 50; i++) { - int len = readLineRN(bi, serverVersion); - remoteIdentifier = new String(serverVersion, 0, len, "ISO-8859-1"); - if (remoteIdentifier.startsWith("SSH-")) break; - } - - if (remoteIdentifier.equals("")) { - throw new IOException("Premature connection close"); - } - - if (!remoteIdentifier.startsWith("SSH-")) { - throw new IOException(String.format("Malformed SSH identification %s", remoteIdentifier)); - } - - if (!remoteIdentifier.startsWith("SSH-1.99-") - && !remoteIdentifier.startsWith("SSH-2.0-")) { - throw new IOException(String.format("Incompatible remote protocol version %s", remoteIdentifier)); - } - - if (clientMode) { - return new ClientServerHello(localIdentifier, remoteIdentifier); - } - else { - return new ClientServerHello(remoteIdentifier, localIdentifier); - } - } - - /** - * @return Returns the client_versioncomment. - */ - public byte[] getClientString() { - return StringEncoder.GetBytes(client_line); - } - - /** - * @return Returns the server_versioncomment. - */ - public byte[] getServerString() { - return StringEncoder.GetBytes(server_line); - } -}
--- a/src/ch/ethz/ssh2/transport/ClientTransportManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -package ch.ethz.ssh2.transport; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.security.SecureRandom; - -import ch.ethz.ssh2.DHGexParameters; -import ch.ethz.ssh2.ServerHostKeyVerifier; -import ch.ethz.ssh2.crypto.CryptoWishList; - -/** - * @version $Id: ClientTransportManager.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class ClientTransportManager extends TransportManager { - - private final Socket sock; - - public ClientTransportManager(final Socket socket) { - super(socket); - this.sock = socket; - } - - public void setTcpNoDelay(boolean state) throws IOException { - sock.setTcpNoDelay(state); - } - - public void setSoTimeout(int timeout) throws IOException { - sock.setSoTimeout(timeout); - } - - public void connect(String hostname, int port, String softwareversion, CryptoWishList cwl, - ServerHostKeyVerifier verifier, DHGexParameters dhgex, int connectTimeout, SecureRandom rnd) - throws IOException { - // Establish the TCP connection to the SSH-2 server - this.connect(hostname, port, connectTimeout); - // Parse the server line and say hello - important: this information is later needed for the - // key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object - // for later use. - ClientServerHello csh = ClientServerHello.clientHello(softwareversion, sock.getInputStream(), - sock.getOutputStream()); - TransportConnection tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), rnd); - KexManager km = new ClientKexManager(this, csh, cwl, hostname, port, verifier, rnd); - super.init(tc, km); - km.initiateKEX(cwl, dhgex, null, null, null); - this.startReceiver(); - } - - protected void connect(String hostname, int port, int connectTimeout) throws IOException { - log.debug(String.format("client transport manager connecting to %s:%d", hostname, port)); - sock.connect(new InetSocketAddress(hostname, port), connectTimeout); - log.debug(String.format("client transport manager connected to %s:%d", hostname, port)); - } -} \ No newline at end of file
--- a/src/ch/ethz/ssh2/transport/DisconnectException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -package ch.ethz.ssh2.transport; - -import java.io.IOException; - -import ch.ethz.ssh2.packets.PacketDisconnect; - -/** - * @version $Id: DisconnectException.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public class DisconnectException extends IOException { - - private PacketDisconnect.Reason reason; - - public DisconnectException(final PacketDisconnect.Reason reason, final String message) { - super(message); - this.reason = reason; - } - - public PacketDisconnect.Reason getReason() { - return reason; - } -}
--- a/src/ch/ethz/ssh2/transport/HTTPProxyClientTransportManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -package ch.ethz.ssh2.transport; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.net.Socket; - -import ch.ethz.ssh2.HTTPProxyData; -import ch.ethz.ssh2.HTTPProxyException; -import ch.ethz.ssh2.crypto.Base64; -import ch.ethz.ssh2.util.StringEncoder; - -/** - * @version $Id: HTTPProxyClientTransportManager.java 155 2014-04-28 12:01:19Z dkocher@sudo.ch $ - */ -public class HTTPProxyClientTransportManager extends ClientTransportManager { - - /** - * Used to tell the library that the connection shall be established through a proxy server. - */ - - private HTTPProxyData pd; - - private final Socket sock; - - public HTTPProxyClientTransportManager(final Socket socket, final HTTPProxyData pd) { - super(socket); - this.sock = socket; - this.pd = pd; - } - - @Override - protected void connect(final String hostname, final int port, final int connectTimeout) throws IOException { - sock.connect(new InetSocketAddress(pd.proxyHost, pd.proxyPort), connectTimeout); - // Tell the proxy where we actually want to connect to - StringBuilder sb = new StringBuilder(); - sb.append("CONNECT "); - sb.append(hostname); - sb.append(':'); - sb.append(port); - sb.append(" HTTP/1.0\r\n"); - - if ((pd.proxyUser != null) && (pd.proxyPass != null)) { - String credentials = pd.proxyUser + ":" + pd.proxyPass; - char[] encoded = Base64.encode(StringEncoder.GetBytes(credentials)); - sb.append("Proxy-Authorization: Basic "); - sb.append(encoded); - sb.append("\r\n"); - } - - if (pd.requestHeaderLines != null) { - for (int i = 0; i < pd.requestHeaderLines.length; i++) { - if (pd.requestHeaderLines[i] != null) { - sb.append(pd.requestHeaderLines[i]); - sb.append("\r\n"); - } - } - } - - sb.append("\r\n"); - OutputStream out = sock.getOutputStream(); - out.write(StringEncoder.GetBytes(sb.toString())); - out.flush(); - // Parse the HTTP response - InputStream in = sock.getInputStream(); - final LineNumberReader reader = new LineNumberReader(new InputStreamReader(in)); - String httpReponse = reader.readLine(); - - if (!httpReponse.startsWith("HTTP/")) { - throw new IOException("The proxy did not send back a valid HTTP response."); - } - - // "HTTP/1.X XYZ X" => 14 characters minimum - - if ((httpReponse.length() < 14) || (httpReponse.charAt(8) != ' ') || (httpReponse.charAt(12) != ' ')) { - throw new IOException("The proxy did not send back a valid HTTP response."); - } - - int errorCode; - - try { - errorCode = Integer.parseInt(httpReponse.substring(9, 12)); - } - catch (NumberFormatException ignore) { - throw new IOException("The proxy did not send back a valid HTTP response."); - } - - if ((errorCode < 0) || (errorCode > 999)) { - throw new IOException("The proxy did not send back a valid HTTP response."); - } - - if (errorCode != 200) { - throw new HTTPProxyException(httpReponse.substring(13), errorCode); - } - - while (reader.readLine() != null) { - // Read until empty line - } - } -}
--- a/src/ch/ethz/ssh2/transport/KexManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.transport; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.security.DigestException; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.SecureRandom; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.ECPrivateKey; -import java.util.Arrays; -import java.util.ArrayList; - -import ch.ethz.ssh2.ConnectionInfo; -import ch.ethz.ssh2.DHGexParameters; -import ch.ethz.ssh2.compression.CompressionFactory; -import ch.ethz.ssh2.compression.Compressor; -import ch.ethz.ssh2.crypto.CryptoWishList; -import ch.ethz.ssh2.crypto.KeyMaterial; -import ch.ethz.ssh2.crypto.cipher.BlockCipher; -import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; -import ch.ethz.ssh2.crypto.digest.MAC; -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.PacketKexInit; -import ch.ethz.ssh2.packets.PacketNewKeys; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.ECPrivateKey; - -/** - * @version $Id: KexManager.java 152 2014-04-28 11:02:23Z dkocher@sudo.ch $ - */ -public abstract class KexManager implements MessageHandler { - protected static final Logger log = Logger.getLogger(KexManager.class); - - private static final ArrayList<String> HOSTKEY_ALGS = new ArrayList<String>(); - static { - HOSTKEY_ALGS.add("ssh-rsa"); - HOSTKEY_ALGS.add("ssh-dss"); - HOSTKEY_ALGS.add("ecdsa-sha2-nistp256"); - HOSTKEY_ALGS.add("ecdsa-sha2-nistp384"); - HOSTKEY_ALGS.add("ecdsa-sha2-nistp521"); - } - - private static final ArrayList<String> KEX_ALGS = new ArrayList<String>(); - static { - KEX_ALGS.add("diffie-hellman-group-exchange-sha256"); - KEX_ALGS.add("diffie-hellman-group-exchange-sha1"); - KEX_ALGS.add("diffie-hellman-group14-sha1"); - KEX_ALGS.add("diffie-hellman-group1-sha1"); - KEX_ALGS.add("ecdh-sha2-nistp256"); - KEX_ALGS.add("ecdh-sha2-nistp384"); - KEX_ALGS.add("ecdh-sha2-nistp521"); - } - - KexState kxs; - int kexCount = 0; - KeyMaterial km; - byte[] sessionId; - ClientServerHello csh; - - final Object accessLock = new Object(); - ConnectionInfo lastConnInfo = null; - - boolean connectionClosed = false; - - boolean ignore_next_kex_packet = false; - - final TransportManager tm; - - CryptoWishList nextKEXcryptoWishList; - DHGexParameters nextKEXdhgexParameters; - KeyPair nextKEXdsakey; - KeyPair nextKEXrsakey; - KeyPair nextKEXeckey; - - final SecureRandom rnd; - - public KexManager(TransportManager tm, ClientServerHello csh, CryptoWishList initialCwl, SecureRandom rnd) { - this.tm = tm; - this.csh = csh; - this.nextKEXcryptoWishList = initialCwl; - this.nextKEXdhgexParameters = new DHGexParameters(); - this.rnd = rnd; - } - - public ConnectionInfo getOrWaitForConnectionInfo(int minKexCount) throws IOException { - synchronized (accessLock) { - while (true) { - if ((lastConnInfo != null) && (lastConnInfo.keyExchangeCounter >= minKexCount)) { - return lastConnInfo; - } - - if (connectionClosed) { - throw(IOException) new IOException("Key exchange was not finished, connection is closed.").initCause(tm.getReasonClosedCause()); - } - - try { - accessLock.wait(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(e.getMessage()); - } - } - } - } - - private String getFirstMatch(String[] client, String[] server) throws NegotiateException { - if (client == null || server == null) { - throw new IllegalArgumentException(); - } - - for (String c : client) { - for (String s : server) { - if (c.equals(s)) { - return c; - } - } - } - - throw new NegotiateException(String.format("Negotiation failed for %s", Arrays.toString(server))); - } - - private boolean compareFirstOfNameList(String[] a, String[] b) { - if (a == null || b == null) { - throw new IllegalArgumentException(); - } - - if ((a.length == 0) && (b.length == 0)) { - return true; - } - - if ((a.length == 0) || (b.length == 0)) { - return false; - } - - return (a[0].equals(b[0])); - } - - private boolean isGuessOK(KexParameters cpar, KexParameters spar) { - if (cpar == null || spar == null) { - throw new IllegalArgumentException(); - } - - if (!compareFirstOfNameList(cpar.kex_algorithms, spar.kex_algorithms)) { - return false; - } - - if (!compareFirstOfNameList(cpar.server_host_key_algorithms, spar.server_host_key_algorithms)) { - return false; - } - - /* - * We do NOT check here if the other algorithms can be agreed on, this - * is just a check if kex_algorithms and server_host_key_algorithms were - * guessed right! - */ - return true; - } - - protected NegotiatedParameters mergeKexParameters(KexParameters client, KexParameters server) - throws NegotiateException { - NegotiatedParameters np = new NegotiatedParameters(); - np.kex_algo = getFirstMatch(client.kex_algorithms, server.kex_algorithms); - log.info("kex_algo=" + np.kex_algo); - np.server_host_key_algo = getFirstMatch(client.server_host_key_algorithms, - server.server_host_key_algorithms); - log.info("server_host_key_algo=" + np.server_host_key_algo); - np.enc_algo_client_to_server = getFirstMatch(client.encryption_algorithms_client_to_server, - server.encryption_algorithms_client_to_server); - np.enc_algo_server_to_client = getFirstMatch(client.encryption_algorithms_server_to_client, - server.encryption_algorithms_server_to_client); - log.info("enc_algo_client_to_server=" + np.enc_algo_client_to_server); - log.info("enc_algo_server_to_client=" + np.enc_algo_server_to_client); - np.mac_algo_client_to_server = getFirstMatch(client.mac_algorithms_client_to_server, - server.mac_algorithms_client_to_server); - np.mac_algo_server_to_client = getFirstMatch(client.mac_algorithms_server_to_client, - server.mac_algorithms_server_to_client); - log.info("mac_algo_client_to_server=" + np.mac_algo_client_to_server); - log.info("mac_algo_server_to_client=" + np.mac_algo_server_to_client); - np.comp_algo_client_to_server = getFirstMatch(client.compression_algorithms_client_to_server, - server.compression_algorithms_client_to_server); - np.comp_algo_server_to_client = getFirstMatch(client.compression_algorithms_server_to_client, - server.compression_algorithms_server_to_client); - log.info("comp_algo_client_to_server=" + np.comp_algo_client_to_server); - log.info("comp_algo_server_to_client=" + np.comp_algo_server_to_client); - np.lang_client_to_server = getFirstMatch(client.languages_client_to_server, - server.languages_client_to_server); - np.lang_server_to_client = getFirstMatch(client.languages_server_to_client, - server.languages_server_to_client); - - if (isGuessOK(client, server)) { - np.guessOK = true; - } - - return np; - } - - public synchronized void initiateKEX(CryptoWishList cwl, DHGexParameters dhgex, KeyPair dsa, KeyPair rsa, KeyPair ec) - throws IOException { - nextKEXcryptoWishList = cwl; - nextKEXdhgexParameters = dhgex; - nextKEXdsakey = dsa; - nextKEXrsakey = rsa; - nextKEXeckey = ec; - - if (kxs == null) { - kxs = new KexState(); - kxs.local_dsa_key = dsa; - kxs.local_rsa_key = rsa; - kxs.local_ec_key = ec; - kxs.dhgexParameters = nextKEXdhgexParameters; - kxs.localKEX = new PacketKexInit(nextKEXcryptoWishList, rnd); - tm.sendKexMessage(kxs.localKEX.getPayload()); - } - } - - private boolean establishKeyMaterial() throws IOException { - try { - int mac_cs_key_len = MAC.getKeyLen(kxs.np.mac_algo_client_to_server); - int enc_cs_key_len = BlockCipherFactory.getKeySize(kxs.np.enc_algo_client_to_server); - int enc_cs_block_len = BlockCipherFactory.getBlockSize(kxs.np.enc_algo_client_to_server); - int mac_sc_key_len = MAC.getKeyLen(kxs.np.mac_algo_server_to_client); - int enc_sc_key_len = BlockCipherFactory.getKeySize(kxs.np.enc_algo_server_to_client); - int enc_sc_block_len = BlockCipherFactory.getBlockSize(kxs.np.enc_algo_server_to_client); - km = KeyMaterial.create(kxs.hashAlgo, kxs.H, kxs.K, sessionId, enc_cs_key_len, enc_cs_block_len, mac_cs_key_len, - enc_sc_key_len, enc_sc_block_len, mac_sc_key_len); - } - catch (IllegalArgumentException e) { - return false; - } - - return true; - } - - protected void finishKex(boolean clientMode) throws IOException { - if (sessionId == null) { - sessionId = kxs.H; - } - - establishKeyMaterial(); - /* Tell the other side that we start using the new material */ - PacketNewKeys ign = new PacketNewKeys(); - tm.sendKexMessage(ign.getPayload()); - BlockCipher cbc; - MAC mac; - Compressor comp; - - try { - cbc = BlockCipherFactory.createCipher(clientMode ? kxs.np.enc_algo_client_to_server - : kxs.np.enc_algo_server_to_client, true, clientMode ? km.enc_key_client_to_server - : km.enc_key_server_to_client, clientMode ? km.initial_iv_client_to_server - : km.initial_iv_server_to_client); - - try { - mac = new MAC(clientMode ? kxs.np.mac_algo_client_to_server : kxs.np.mac_algo_server_to_client, clientMode - ? km.integrity_key_client_to_server : km.integrity_key_server_to_client); - } - catch (DigestException e) { - throw new IOException(e); - } - - comp = CompressionFactory.createCompressor(kxs.np.comp_algo_client_to_server); - } - catch (IllegalArgumentException f) { - throw new IOException(String.format("Fatal error initializing ciphers. %s", f.getMessage())); - } - - tm.changeSendCipher(cbc, mac); - tm.changeSendCompression(comp); - tm.kexFinished(); - } - - public static String[] getDefaultServerHostkeyAlgorithmList() { - return HOSTKEY_ALGS.toArray(new String[HOSTKEY_ALGS.size()]); - } - - public static void checkServerHostkeyAlgorithmsList(String[] algos) { - for (final String algo : algos) { - if (!HOSTKEY_ALGS.contains(algo)) - throw new IllegalArgumentException("Unknown server host key algorithm '" + algo + "'"); - } - } - - public static String[] getDefaultClientKexAlgorithmList() { - return KEX_ALGS.toArray(new String[KEX_ALGS.size()]); - } - - public static String[] getDefaultServerKexAlgorithmList() { - return KEX_ALGS.toArray(new String[KEX_ALGS.size()]); - } - - public static void checkKexAlgorithmList(String[] algos) { - for (final String algo : algos) { - if (!KEX_ALGS.contains(algo)) - throw new IllegalArgumentException("Unknown kex algorithm '" + algo + "'"); - } - } -}
--- a/src/ch/ethz/ssh2/transport/KexParameters.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.transport; - -import java.util.Arrays; - -/** - * @author Christian Plattner - * @version $Id: KexParameters.java 159 2014-05-01 14:12:34Z dkocher@sudo.ch $ - */ -public class KexParameters { - public byte[] cookie; - public String[] kex_algorithms; - public String[] server_host_key_algorithms; - public String[] encryption_algorithms_client_to_server; - public String[] encryption_algorithms_server_to_client; - public String[] mac_algorithms_client_to_server; - public String[] mac_algorithms_server_to_client; - public String[] compression_algorithms_client_to_server; - public String[] compression_algorithms_server_to_client; - public String[] languages_client_to_server; - public String[] languages_server_to_client; - public boolean first_kex_packet_follows; - public int reserved_field1; - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("KexParameters{"); - sb.append("cookie=").append(Arrays.toString(cookie)); - sb.append(", kex_algorithms=").append(Arrays.toString(kex_algorithms)); - sb.append(", server_host_key_algorithms=").append(Arrays.toString(server_host_key_algorithms)); - sb.append(", encryption_algorithms_client_to_server=").append(Arrays.toString(encryption_algorithms_client_to_server)); - sb.append(", encryption_algorithms_server_to_client=").append(Arrays.toString(encryption_algorithms_server_to_client)); - sb.append(", mac_algorithms_client_to_server=").append(Arrays.toString(mac_algorithms_client_to_server)); - sb.append(", mac_algorithms_server_to_client=").append(Arrays.toString(mac_algorithms_server_to_client)); - sb.append(", compression_algorithms_client_to_server=").append(Arrays.toString(compression_algorithms_client_to_server)); - sb.append(", compression_algorithms_server_to_client=").append(Arrays.toString(compression_algorithms_server_to_client)); - sb.append(", languages_client_to_server=").append(Arrays.toString(languages_client_to_server)); - sb.append(", languages_server_to_client=").append(Arrays.toString(languages_server_to_client)); - sb.append(", first_kex_packet_follows=").append(first_kex_packet_follows); - sb.append(", reserved_field1=").append(reserved_field1); - sb.append('}'); - return sb.toString(); - } -}
--- a/src/ch/ethz/ssh2/transport/KexState.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.transport; - -import ch.ethz.ssh2.DHGexParameters; -import ch.ethz.ssh2.crypto.dh.GenericDhExchange; -import ch.ethz.ssh2.crypto.dh.DhGroupExchange; -import java.math.BigInteger; -import ch.ethz.ssh2.packets.PacketKexInit; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.ECPrivateKey; - -/** - * KexState. - * - * @author Christian Plattner - * @version 2.50, 03/15/10 - */ -public class KexState { - public PacketKexInit localKEX; - public PacketKexInit remoteKEX; - public NegotiatedParameters np; - public int state = 0; - - public BigInteger K; - public byte[] H; - - public byte[] remote_hostkey; - - public String hashAlgo; - public GenericDhExchange dhx; - public DhGroupExchange dhgx; - public DHGexParameters dhgexParameters; - - public KeyPair local_dsa_key; - public KeyPair local_rsa_key; - public KeyPair local_ec_key; -}
--- a/src/ch/ethz/ssh2/transport/MessageHandler.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.transport; - -import java.io.IOException; - -/** - * @author Christian Plattner - * @version $Id: MessageHandler.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public interface MessageHandler { - public void handleMessage(byte[] msg) throws IOException; - - public void handleFailure(IOException failure); -}
--- a/src/ch/ethz/ssh2/transport/NegotiateException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.transport; - -import java.io.IOException; - -/** - * @version $Id: NegotiateException.java 149 2014-04-28 09:18:35Z dkocher@sudo.ch $ - */ -public class NegotiateException extends IOException { - private static final long serialVersionUID = 3689910669428143157L; - - public NegotiateException() { - // - } - - public NegotiateException(String message) { - super(message); - } -}
--- a/src/ch/ethz/ssh2/transport/NegotiatedParameters.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.transport; - -/** - * @author Christian Plattner - * @version $Id: NegotiatedParameters.java 159 2014-05-01 14:12:34Z dkocher@sudo.ch $ - */ -public class NegotiatedParameters { - public boolean guessOK; - public String kex_algo; - public String server_host_key_algo; - public String enc_algo_client_to_server; - public String enc_algo_server_to_client; - public String mac_algo_client_to_server; - public String mac_algo_server_to_client; - public String comp_algo_client_to_server; - public String comp_algo_server_to_client; - public String lang_client_to_server; - public String lang_server_to_client; - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("NegotiatedParameters{"); - sb.append("guessOK=").append(guessOK); - sb.append(", kex_algo='").append(kex_algo).append('\''); - sb.append(", server_host_key_algo='").append(server_host_key_algo).append('\''); - sb.append(", enc_algo_client_to_server='").append(enc_algo_client_to_server).append('\''); - sb.append(", enc_algo_server_to_client='").append(enc_algo_server_to_client).append('\''); - sb.append(", mac_algo_client_to_server='").append(mac_algo_client_to_server).append('\''); - sb.append(", mac_algo_server_to_client='").append(mac_algo_server_to_client).append('\''); - sb.append(", comp_algo_client_to_server='").append(comp_algo_client_to_server).append('\''); - sb.append(", comp_algo_server_to_client='").append(comp_algo_server_to_client).append('\''); - sb.append(", lang_client_to_server='").append(lang_client_to_server).append('\''); - sb.append(", lang_server_to_client='").append(lang_server_to_client).append('\''); - sb.append('}'); - return sb.toString(); - } -}
--- a/src/ch/ethz/ssh2/transport/ServerKexManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.transport; - -import java.io.IOException; -import java.security.DigestException; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.DSAPublicKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.math.BigInteger; - -import ch.ethz.ssh2.ConnectionInfo; -import ch.ethz.ssh2.PacketTypeException; -import ch.ethz.ssh2.auth.ServerAuthenticationManager; -import ch.ethz.ssh2.crypto.cipher.BlockCipher; -import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; -import ch.ethz.ssh2.crypto.dh.GenericDhExchange; -import ch.ethz.ssh2.crypto.digest.MAC; -import ch.ethz.ssh2.packets.PacketKexDHInit; -import ch.ethz.ssh2.packets.PacketKexDHReply; -import ch.ethz.ssh2.packets.PacketKexInit; -import ch.ethz.ssh2.packets.Packets; -import ch.ethz.ssh2.server.ServerConnectionState; -import ch.ethz.ssh2.signature.DSASHA1Verify; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; -import ch.ethz.ssh2.signature.RSASHA1Verify; - -/** - * @version $Id: ServerKexManager.java 160 2014-05-01 14:30:26Z dkocher@sudo.ch $ - */ -public class ServerKexManager extends KexManager { - - private final ServerConnectionState state; - - private boolean authenticationStarted = false; - - public ServerKexManager(ServerConnectionState state) { - super(state.tm, state.csh, state.next_cryptoWishList, state.generator); - this.state = state; - } - - public void handleFailure(final IOException failure) { - synchronized (accessLock) { - connectionClosed = true; - accessLock.notifyAll(); - } - } - - public void handleMessage(byte[] msg) throws IOException { - PacketKexInit kip; - - if (msg == null) { - synchronized (accessLock) { - connectionClosed = true; - accessLock.notifyAll(); - return; - } - } - - if ((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) { - throw new PacketTypeException(msg[0]); - } - - if (ignore_next_kex_packet) { - ignore_next_kex_packet = false; - return; - } - - if (msg[0] == Packets.SSH_MSG_KEXINIT) { - if ((kxs != null) && (kxs.state != 0)) { - throw new PacketTypeException(msg[0]); - } - - if (kxs == null) { - /* - * Ah, OK, peer wants to do KEX. Let's be nice and play - * together. - */ - kxs = new KexState(); - kxs.local_dsa_key = nextKEXdsakey; - kxs.local_rsa_key = nextKEXrsakey; - kxs.local_ec_key = nextKEXeckey; - kxs.dhgexParameters = nextKEXdhgexParameters; - kip = new PacketKexInit(nextKEXcryptoWishList, rnd); - kxs.localKEX = kip; - tm.sendKexMessage(kip.getPayload()); - } - - kip = new PacketKexInit(msg); - kxs.remoteKEX = kip; - kxs.np = mergeKexParameters(kxs.remoteKEX.getKexParameters(), kxs.localKEX.getKexParameters()); - - if (kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) { - // Guess was wrong, we need to ignore the next kex packet. - ignore_next_kex_packet = true; - } - - if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || - kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp256") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp384") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) { - kxs.dhx = GenericDhExchange.getInstance(kxs.np.kex_algo); - kxs.dhx.init(kxs.np.kex_algo); - kxs.state = 1; - return; - } - - throw new IllegalStateException("Unkown KEX method!"); - } - - if (msg[0] == Packets.SSH_MSG_NEWKEYS) { - if (km == null) { - throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!"); - } - - BlockCipher cbc; - MAC mac; - - try { - cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_client_to_server, false, - km.enc_key_client_to_server, km.initial_iv_client_to_server); - - try { - mac = new MAC(kxs.np.mac_algo_client_to_server, km.integrity_key_client_to_server); - } - catch (DigestException e) { - throw new IOException(e); - } - } - catch (IllegalArgumentException e) { - throw new IOException(e); - } - - tm.changeRecvCipher(cbc, mac); - ConnectionInfo sci = new ConnectionInfo(); - kexCount++; - sci.keyExchangeAlgorithm = kxs.np.kex_algo; - sci.keyExchangeCounter = kexCount; - sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server; - sci.serverToClientCryptoAlgorithm = kxs.np.enc_algo_server_to_client; - sci.clientToServerMACAlgorithm = kxs.np.mac_algo_client_to_server; - sci.serverToClientMACAlgorithm = kxs.np.mac_algo_server_to_client; - sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo; - sci.serverHostKey = kxs.remote_hostkey; - - synchronized (accessLock) { - lastConnInfo = sci; - accessLock.notifyAll(); - } - - kxs = null; - return; - } - - if ((kxs == null) || (kxs.state == 0)) { - throw new IOException("Unexpected Kex submessage!"); - } - - if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || - kxs.np.kex_algo.equals("diffie-hellman-group14-sha1") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp256") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp384") || - kxs.np.kex_algo.equals("ecdh-sha2-nistp521")) { - if (kxs.state == 1) { - PacketKexDHInit dhi = new PacketKexDHInit(msg); - kxs.dhx.setE(dhi.getE()); - byte[] hostKey = null; - - if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) { - hostKey = ECDSASHA2Verify.encodeSSHECDSAPublicKey((ECPublicKey)kxs.local_ec_key.getPublic()); - } - - if (kxs.np.server_host_key_algo.equals("ssh-rsa")) { - hostKey = RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey)kxs.local_rsa_key.getPublic()); - } - - if (kxs.np.server_host_key_algo.equals("ssh-dss")) { - hostKey = DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey)kxs.local_dsa_key.getPublic()); - } - - try { - kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(), - kxs.remoteKEX.getPayload(), kxs.localKEX.getPayload(), hostKey); - } - catch (IllegalArgumentException e) { - throw new IOException("KEX error.", e); - } - - kxs.K = kxs.dhx.getK(); - byte[] signature = null; - - if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) { - ECPrivateKey pk = (ECPrivateKey)kxs.local_ec_key.getPrivate(); - byte[] es = ECDSASHA2Verify.generateSignature(kxs.H, pk); - signature = ECDSASHA2Verify.encodeSSHECDSASignature(es, pk.getParams()); - } - - if (kxs.np.server_host_key_algo.equals("ssh-rsa")) { - byte[] rs = RSASHA1Verify.generateSignature(kxs.H, (RSAPrivateKey)kxs.local_rsa_key.getPrivate()); - signature = RSASHA1Verify.encodeSSHRSASignature(rs); - } - - if (kxs.np.server_host_key_algo.equals("ssh-dss")) { - byte[] ds = DSASHA1Verify.generateSignature(kxs.H, (DSAPrivateKey)kxs.local_dsa_key.getPrivate(), rnd); - signature = DSASHA1Verify.encodeSSHDSASignature(ds); - } - - PacketKexDHReply dhr = new PacketKexDHReply(hostKey, new BigInteger(kxs.dhx.getF()), signature); - tm.sendKexMessage(dhr.getPayload()); - finishKex(false); - kxs.state = -1; - - if (authenticationStarted == false) { - authenticationStarted = true; - state.am = new ServerAuthenticationManager(state); - } - - return; - } - } - - throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo)); - } -}
--- a/src/ch/ethz/ssh2/transport/ServerTransportManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -package ch.ethz.ssh2.transport; - -import java.io.IOException; -import java.net.Socket; - -import ch.ethz.ssh2.server.ServerConnectionState; - -/** - * @version $Id: ServerTransportManager.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ - */ -public class ServerTransportManager extends TransportManager { - - private final Socket sock; - - public ServerTransportManager(final Socket socket) { - super(socket); - // TCP connection is already established - this.sock = socket; - } - - public void connect(ServerConnectionState state) throws IOException { - /* Parse the client lin - e and say hello - important: this information is later needed for the - * key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object - * for later use. - */ - state.csh = ClientServerHello.serverHello(state.softwareversion, sock.getInputStream(), sock.getOutputStream()); - TransportConnection tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), state.generator); - KexManager km = new ServerKexManager(state); - super.init(tc, km); - km.initiateKEX(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - this.startReceiver(); - } -}
--- a/src/ch/ethz/ssh2/transport/TransportConnection.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,319 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.transport; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.SecureRandom; - -import ch.ethz.ssh2.PacketFormatException; -import ch.ethz.ssh2.compression.Compressor; -import ch.ethz.ssh2.crypto.cipher.BlockCipher; -import ch.ethz.ssh2.crypto.cipher.CipherInputStream; -import ch.ethz.ssh2.crypto.cipher.CipherOutputStream; -import ch.ethz.ssh2.crypto.cipher.NullCipher; -import ch.ethz.ssh2.crypto.digest.MAC; -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.Packets; - -/** - * TransportConnection. - * - * @author Christian Plattner - * @version $Id: TransportConnection.java 144 2014-04-25 12:48:25Z dkocher@sudo.ch $ - */ -public class TransportConnection { - private static final Logger log = Logger.getLogger(TransportConnection.class); - - int send_seq_number = 0; - - int recv_seq_number = 0; - - CipherInputStream cis; - - CipherOutputStream cos; - - boolean useRandomPadding; - - /* Depends on current MAC and CIPHER */ - - MAC send_mac; - - byte[] send_mac_buffer; - - int send_padd_blocksize = 8; - - MAC recv_mac; - - byte[] recv_mac_buffer; - - byte[] recv_mac_buffer_cmp; - - int recv_padd_blocksize = 8; - - Compressor recv_comp; - - Compressor send_comp; - - boolean can_compress; - - byte[] recv_comp_buffer; - - byte[] send_comp_buffer; - - /* won't change */ - - final byte[] send_padding_buffer = new byte[256]; - - final byte[] send_packet_header_buffer = new byte[5]; - - final byte[] recv_padding_buffer = new byte[256]; - - final byte[] recv_packet_header_buffer = new byte[5]; - - boolean recv_packet_header_present = false; - - ClientServerHello csh; - - final SecureRandom rnd; - - public TransportConnection(InputStream is, OutputStream os, SecureRandom rnd) { - this.cis = new CipherInputStream(new NullCipher(), is); - this.cos = new CipherOutputStream(new NullCipher(), os); - this.rnd = rnd; - } - - public void changeRecvCipher(BlockCipher bc, MAC mac) { - cis.changeCipher(bc); - recv_mac = mac; - recv_mac_buffer = (mac != null) ? new byte[mac.size()] : null; - recv_mac_buffer_cmp = (mac != null) ? new byte[mac.size()] : null; - recv_padd_blocksize = bc.getBlockSize(); - - if (recv_padd_blocksize < 8) { - recv_padd_blocksize = 8; - } - } - - public void changeSendCipher(BlockCipher bc, MAC mac) { - if ((bc instanceof NullCipher) == false) { - /* Only use zero byte padding for the first few packets */ - useRandomPadding = true; - /* Once we start encrypting, there is no way back */ - } - - cos.changeCipher(bc); - send_mac = mac; - send_mac_buffer = (mac != null) ? new byte[mac.size()] : null; - send_padd_blocksize = bc.getBlockSize(); - - if (send_padd_blocksize < 8) { - send_padd_blocksize = 8; - } - } - - public void changeRecvCompression(Compressor comp) { - recv_comp = comp; - - if (comp != null) { - recv_comp_buffer = new byte[comp.getBufferSize()]; - } - } - - public void changeSendCompression(Compressor comp) { - send_comp = comp; - - if (comp != null) { - send_comp_buffer = new byte[comp.getBufferSize()]; - } - } - - public void sendMessage(byte[] message) throws IOException { - sendMessage(message, 0, message.length, 0); - } - - public void sendMessage(byte[] message, int off, int len) throws IOException { - sendMessage(message, off, len, 0); - } - - public int getPacketOverheadEstimate() { - // return an estimate for the paket overhead (for send operations) - return 5 + 4 + (send_padd_blocksize - 1) + send_mac_buffer.length; - } - - public void sendMessage(byte[] message, int off, int len, int padd) throws IOException { - if (padd < 4) { - padd = 4; - } - else if (padd > 64) { - padd = 64; - } - - if (send_comp != null && can_compress) { - len = send_comp.compress(message, off, len, send_comp_buffer); - message = send_comp_buffer; - } - - int packet_len = 5 + len + padd; /* Minimum allowed padding is 4 */ - int slack = packet_len % send_padd_blocksize; - - if (slack != 0) { - packet_len += (send_padd_blocksize - slack); - } - - if (packet_len < 16) { - packet_len = 16; - } - - int padd_len = packet_len - (5 + len); - - if (useRandomPadding) { - for (int i = 0; i < padd_len; i = i + 4) { - /* - * don't waste calls to rnd.nextInt() (by using only 8bit of the - * output). just believe me: even though we may write here up to 3 - * bytes which won't be used, there is no "buffer overflow" (i.e., - * arrayindexoutofbounds). the padding buffer is big enough =) (256 - * bytes, and that is bigger than any current cipher block size + 64). - */ - int r = rnd.nextInt(); - send_padding_buffer[i] = (byte) r; - send_padding_buffer[i + 1] = (byte)(r >> 8); - send_padding_buffer[i + 2] = (byte)(r >> 16); - send_padding_buffer[i + 3] = (byte)(r >> 24); - } - } - else { - /* use zero padding for unencrypted traffic */ - for (int i = 0; i < padd_len; i++) { - send_padding_buffer[i] = 0; - } - - /* Actually this code is paranoid: we never filled any - * bytes into the padding buffer so far, therefore it should - * consist of zeros only. - */ - } - - send_packet_header_buffer[0] = (byte)((packet_len - 4) >> 24); - send_packet_header_buffer[1] = (byte)((packet_len - 4) >> 16); - send_packet_header_buffer[2] = (byte)((packet_len - 4) >> 8); - send_packet_header_buffer[3] = (byte)((packet_len - 4)); - send_packet_header_buffer[4] = (byte) padd_len; - cos.write(send_packet_header_buffer, 0, 5); - cos.write(message, off, len); - cos.write(send_padding_buffer, 0, padd_len); - - if (send_mac != null) { - send_mac.initMac(send_seq_number); - send_mac.update(send_packet_header_buffer, 0, 5); - send_mac.update(message, off, len); - send_mac.update(send_padding_buffer, 0, padd_len); - send_mac.getMac(send_mac_buffer, 0); - cos.writePlain(send_mac_buffer, 0, send_mac_buffer.length); - } - - cos.flush(); - - if (log.isDebugEnabled()) { - log.debug("Sent " + Packets.getMessageName(message[off] & 0xff) + " " + len + " bytes payload"); - } - - send_seq_number++; - } - - public int peekNextMessageLength() throws IOException { - if (recv_packet_header_present == false) { - cis.read(recv_packet_header_buffer, 0, 5); - recv_packet_header_present = true; - } - - int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24) | - ((recv_packet_header_buffer[1] & 0xff) << 16) | - ((recv_packet_header_buffer[2] & 0xff) << 8) | - ((recv_packet_header_buffer[3] & 0xff)); - int padding_length = recv_packet_header_buffer[4] & 0xff; - - if (packet_length > TransportManager.MAX_PACKET_SIZE || packet_length < 12) { - throw new PacketFormatException(String.format("Illegal packet size (%d)", packet_length)); - } - - int payload_length = packet_length - padding_length - 1; - - if (payload_length < 0) { - throw new PacketFormatException(String.format("Illegal padding_length in packet from remote (%d)", padding_length)); - } - - return payload_length; - } - - public int receiveMessage(byte buffer[], int off, int len) throws IOException { - if (recv_packet_header_present == false) { - cis.read(recv_packet_header_buffer, 0, 5); - } - else { - recv_packet_header_present = false; - } - - int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24) | - ((recv_packet_header_buffer[1] & 0xff) << 16) | - ((recv_packet_header_buffer[2] & 0xff) << 8) | - ((recv_packet_header_buffer[3] & 0xff)); - int padding_length = recv_packet_header_buffer[4] & 0xff; - - if (packet_length > TransportManager.MAX_PACKET_SIZE || packet_length < 12) { - throw new PacketFormatException(String.format("Illegal packet size (%d)", packet_length)); - } - - int payload_length = packet_length - padding_length - 1; - - if (payload_length < 0) { - throw new PacketFormatException(String.format("Illegal padding_length in packet from remote (%d)", padding_length)); - } - - if (payload_length >= len) { - throw new IOException("Receive buffer too small (" + len + ", need " + payload_length + ")"); - } - - cis.read(buffer, off, payload_length); - cis.read(recv_padding_buffer, 0, padding_length); - - if (recv_mac != null) { - cis.readPlain(recv_mac_buffer, 0, recv_mac_buffer.length); - recv_mac.initMac(recv_seq_number); - recv_mac.update(recv_packet_header_buffer, 0, 5); - recv_mac.update(buffer, off, payload_length); - recv_mac.update(recv_padding_buffer, 0, padding_length); - recv_mac.getMac(recv_mac_buffer_cmp, 0); - - for (int i = 0; i < recv_mac_buffer.length; i++) { - if (recv_mac_buffer[i] != recv_mac_buffer_cmp[i]) { - throw new IOException("Remote sent corrupt MAC."); - } - } - } - - recv_seq_number++; - - if (log.isDebugEnabled()) { - log.debug("Received " + Packets.getMessageName(buffer[off] & 0xff) + " " + payload_length - + " bytes payload"); - } - - if (recv_comp != null && can_compress) { - int[] uncomp_len = new int[] {payload_length}; - buffer = recv_comp.uncompress(buffer, off, uncomp_len); - return uncomp_len[0]; - } - else { - return payload_length; - } - } - - public void startCompression() { - can_compress = true; - } -}
--- a/src/ch/ethz/ssh2/transport/TransportManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,505 +0,0 @@ -/* - * Copyright (c) 2006-2013 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2.transport; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.Socket; -import java.security.KeyPair; -import java.util.ArrayList; -import java.util.List; - -import ch.ethz.ssh2.ConnectionInfo; -import ch.ethz.ssh2.ConnectionMonitor; -import ch.ethz.ssh2.DHGexParameters; -import ch.ethz.ssh2.PacketTypeException; -import ch.ethz.ssh2.compression.Compressor; -import ch.ethz.ssh2.crypto.CryptoWishList; -import ch.ethz.ssh2.crypto.cipher.BlockCipher; -import ch.ethz.ssh2.crypto.digest.MAC; -import ch.ethz.ssh2.log.Logger; -import ch.ethz.ssh2.packets.PacketDisconnect; -import ch.ethz.ssh2.packets.Packets; -import ch.ethz.ssh2.packets.TypesReader; - -/** - * Yes, the "standard" is a big mess. On one side, the say that arbitrary channel - * packets are allowed during kex exchange, on the other side we need to blindly - * ignore the next _packet_ if the KEX guess was wrong. Where do we know from that - * the next packet is not a channel data packet? Yes, we could check if it is in - * the KEX range. But the standard says nothing about this. The OpenSSH guys - * block local "normal" traffic during KEX. That's fine - however, they assume - * that the other side is doing the same. During re-key, if they receive traffic - * other than KEX, they become horribly irritated and kill the connection. Since - * we are very likely going to communicate with OpenSSH servers, we have to play - * the same game - even though we could do better. - * - * @author Christian Plattner - * @version $Id: TransportManager.java 161 2014-05-01 18:01:55Z dkocher@sudo.ch $ - */ -public abstract class TransportManager { - protected static final Logger log = Logger.getLogger(TransportManager.class); - - private static final class HandlerEntry { - MessageHandler mh; - int low; - int high; - } - - /** - * Advertised maximum SSH packet size that the other side can send to us. - */ - public static final int MAX_PACKET_SIZE = 64 * 1024; - - private final List<AsynchronousEntry> asynchronousQueue - = new ArrayList<AsynchronousEntry>(); - - private Thread asynchronousThread = null; - private boolean asynchronousPending = false; - - private Socket socket; - - protected TransportManager(final Socket socket) { - this.socket = socket; - } - - private static final class AsynchronousEntry { - public byte[] message; - - public AsynchronousEntry(byte[] message) { - this.message = message; - } - } - - private final class AsynchronousWorker implements Runnable { - public void run() { - while (true) { - final AsynchronousEntry item; - - synchronized (asynchronousQueue) { - if (asynchronousQueue.size() == 0) { - // Only now we may reset the flag, since we are sure that all queued items - // have been sent (there is a slight delay between de-queuing and sending, - // this is why we need this flag! See code below. Sending takes place outside - // of this lock, this is why a test for size()==0 (from another thread) does not ensure - // that all messages have been sent. - asynchronousPending = false; - // Notify any senders that they can proceed, all async messages have been delivered - asynchronousQueue.notifyAll(); - - // After the queue is empty for about 2 seconds, stop this thread - try { - asynchronousQueue.wait(2000); - } - catch (InterruptedException ignore) { - // - } - - if (asynchronousQueue.size() == 0) { - asynchronousThread = null; - return; - } - } - - item = asynchronousQueue.remove(0); - } - - try { - sendMessageImmediate(item.message); - } - catch (IOException e) { - // There is no point in handling it - it simply means that the connection has a problem and we should stop - // sending asynchronously messages. We do not need to signal that we have exited (asynchronousThread = null): - // further messages in the queue cannot be sent by this or any other thread. - // Other threads will sooner or later (when receiving or sending the next message) get the - // same IOException and get to the same conclusion. - log.warning(e.getMessage()); - return; - } - } - } - } - - private final Object connectionSemaphore = new Object(); - - private boolean flagKexOngoing; - - private boolean connectionClosed; - private Throwable reasonClosedCause; - - private TransportConnection tc; - private KexManager km; - - private final List<HandlerEntry> messageHandlers = new ArrayList<HandlerEntry>(); - - private List<ConnectionMonitor> connectionMonitors = new ArrayList<ConnectionMonitor>(); - boolean monitorsWereInformed = false; - - protected void init(TransportConnection tc, KexManager km) { - this.tc = tc; - this.km = km; - } - - public int getPacketOverheadEstimate() { - return tc.getPacketOverheadEstimate(); - } - - public ConnectionInfo getConnectionInfo(int kexNumber) throws IOException { - return km.getOrWaitForConnectionInfo(kexNumber); - } - - public Throwable getReasonClosedCause() { - synchronized (connectionSemaphore) { - return reasonClosedCause; - } - } - - public byte[] getSessionIdentifier() { - return km.sessionId; - } - - public void close(Throwable cause, boolean useDisconnectPacket) { - if (useDisconnectPacket == false) { - // OK, hard shutdown - do not acquire the semaphore, - // perhaps somebody is inside (and waits until - // the remote side is ready to accept new data). - try { - socket.close(); - } - catch (IOException ignore) { - } - - // OK, whoever tried to send data, should now agree that - // there is no point in further waiting =) - // It is safe now to acquire the semaphore. - } - - synchronized (connectionSemaphore) { - if (!connectionClosed) { - if (useDisconnectPacket == true) { - try { - if (tc != null) - tc.sendMessage(new PacketDisconnect(PacketDisconnect.Reason.SSH_DISCONNECT_BY_APPLICATION, "").getPayload()); - } - catch (IOException ignore) { - } - - try { - socket.close(); - } - catch (IOException ignore) { - } - } - - connectionClosed = true; - reasonClosedCause = cause; - } - - connectionSemaphore.notifyAll(); - } - - // check if we need to inform the monitors - List<ConnectionMonitor> monitors = null; - - synchronized (this) { - // Short term lock to protect "connectionMonitors" - // and "monitorsWereInformed" - // (they may be modified concurrently) - if (monitorsWereInformed == false) { - monitorsWereInformed = true; - monitors = new ArrayList<ConnectionMonitor>(connectionMonitors); - } - } - - if (monitors != null) { - for (ConnectionMonitor cmon : monitors) { - try { - cmon.connectionLost(reasonClosedCause); - } - catch (Exception ignore) { - } - } - } - } - - protected void startReceiver() throws IOException { - final Thread receiveThread = new Thread(new Runnable() { - public void run() { - try { - receiveLoop(); - // Can only exit with exception - } - catch (IOException e) { - close(e, false); - log.warning(e.getMessage()); - - // Tell all handlers that it is time to say goodbye - if (km != null) { - km.handleFailure(e); - } - - for (HandlerEntry he : messageHandlers) { - he.mh.handleFailure(e); - } - } - - if (log.isDebugEnabled()) { - log.debug("Receive thread: back from receiveLoop"); - } - } - }); - receiveThread.setName("Transport Manager"); - receiveThread.setDaemon(true); - receiveThread.start(); - } - - public void registerMessageHandler(MessageHandler mh, int low, int high) { - HandlerEntry he = new HandlerEntry(); - he.mh = mh; - he.low = low; - he.high = high; - - synchronized (messageHandlers) { - messageHandlers.add(he); - } - } - - public void removeMessageHandler(MessageHandler handler) { - synchronized (messageHandlers) { - for (int i = 0; i < messageHandlers.size(); i++) { - HandlerEntry he = messageHandlers.get(i); - - if (he.mh == handler) { - messageHandlers.remove(i); - break; - } - } - } - } - - public void sendKexMessage(byte[] msg) throws IOException { - synchronized (connectionSemaphore) { - if (connectionClosed) { - throw(IOException) new IOException("Sorry, this connection is closed.").initCause(reasonClosedCause); - } - - flagKexOngoing = true; - - try { - tc.sendMessage(msg); - } - catch (IOException e) { - close(e, false); - throw e; - } - } - } - - public void kexFinished() throws IOException { - synchronized (connectionSemaphore) { - flagKexOngoing = false; - connectionSemaphore.notifyAll(); - } - } - - /** - * @param cwl Crypto wishlist - * @param dhgex Diffie-hellman group exchange - * @param dsa may be null if this is a client connection - * @param rsa may be null if this is a client connection - * @throws IOException - */ - public void forceKeyExchange(CryptoWishList cwl, DHGexParameters dhgex, KeyPair dsa, KeyPair rsa, KeyPair ec) - throws IOException { - synchronized (connectionSemaphore) { - if (connectionClosed) { - throw(IOException) new IOException("Sorry, this connection is closed.").initCause(reasonClosedCause); - } - } - - km.initiateKEX(cwl, dhgex, dsa, rsa, ec); - } - - public void changeRecvCipher(BlockCipher bc, MAC mac) { - tc.changeRecvCipher(bc, mac); - } - - public void changeSendCipher(BlockCipher bc, MAC mac) { - tc.changeSendCipher(bc, mac); - } - - public void changeRecvCompression(Compressor comp) { - tc.changeRecvCompression(comp); - } - - public void changeSendCompression(Compressor comp) { - tc.changeSendCompression(comp); - } - - public void sendAsynchronousMessage(byte[] msg) throws IOException { - synchronized (asynchronousQueue) { - asynchronousQueue.add(new AsynchronousEntry(msg)); - asynchronousPending = true; - - /* This limit should be flexible enough. We need this, otherwise the peer - * can flood us with global requests (and other stuff where we have to reply - * with an asynchronous message) and (if the server just sends data and does not - * read what we send) this will probably put us in a low memory situation - * (our send queue would grow and grow and...) */ - - if (asynchronousQueue.size() > 100) { - throw new IOException("The peer is not consuming our asynchronous replies."); - } - - // Check if we have an asynchronous sending thread - if (asynchronousThread == null) { - asynchronousThread = new Thread(new AsynchronousWorker()); - asynchronousThread.setDaemon(true); - asynchronousThread.start(); - // The thread will stop after 2 seconds of inactivity (i.e., empty queue) - } - - asynchronousQueue.notifyAll(); - } - } - - public void setConnectionMonitors(List<ConnectionMonitor> monitors) { - synchronized (this) { - connectionMonitors = new ArrayList<ConnectionMonitor>(monitors); - } - } - - /** - * Send a message but ensure that all queued messages are being sent first. - * - * @param msg Message - * @throws IOException - */ - public void sendMessage(byte[] msg) throws IOException { - synchronized (asynchronousQueue) { - while (asynchronousPending) { - try { - asynchronousQueue.wait(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(e.getMessage()); - } - } - } - - sendMessageImmediate(msg); - } - - /** - * Send message, ignore queued async messages that have not been delivered yet. - * Will be called directly from the asynchronousThread thread. - * - * @param msg Message - * @throws IOException - */ - public void sendMessageImmediate(byte[] msg) throws IOException { - synchronized (connectionSemaphore) { - while (true) { - if (connectionClosed) { - throw(IOException) new IOException("Sorry, this connection is closed.").initCause(reasonClosedCause); - } - - if (!flagKexOngoing) { - break; - } - - try { - connectionSemaphore.wait(); - } - catch (InterruptedException e) { - throw new InterruptedIOException(e.getMessage()); - } - } - - try { - tc.sendMessage(msg); - } - catch (IOException e) { - close(e, false); - throw e; - } - } - } - - private void receiveLoop() throws IOException { - while (true) { - final byte[] buffer = new byte[MAX_PACKET_SIZE]; - final int length = tc.receiveMessage(buffer, 0, buffer.length); - final byte[] packet = new byte[length]; - System.arraycopy(buffer, 0, packet, 0, length); - final int type = packet[0] & 0xff; - log.debug(String.format("transport manager receive loop type %d", type)); - - switch (type) { - case Packets.SSH_MSG_IGNORE: - break; - - case Packets.SSH_MSG_DEBUG: { - TypesReader tr = new TypesReader(packet); - tr.readByte(); - // always_display - tr.readBoolean(); - String message = tr.readString(); - - if (log.isDebugEnabled()) { - log.debug(String.format("Debug message from remote: '%s'", message)); - } - - break; - } - - case Packets.SSH_MSG_UNIMPLEMENTED: - throw new PacketTypeException(type); - - case Packets.SSH_MSG_DISCONNECT: { - final PacketDisconnect disconnect = new PacketDisconnect(packet); - throw new DisconnectException(disconnect.getReason(), disconnect.getMessage()); - } - - case Packets.SSH_MSG_KEXINIT: - case Packets.SSH_MSG_NEWKEYS: - case Packets.SSH_MSG_KEXDH_INIT: - case Packets.SSH_MSG_KEXDH_REPLY: - case Packets.SSH_MSG_KEX_DH_GEX_REQUEST: - case Packets.SSH_MSG_KEX_DH_GEX_INIT: - case Packets.SSH_MSG_KEX_DH_GEX_REPLY: - // Is it a KEX Packet - km.handleMessage(packet); - break; - - case Packets.SSH_MSG_USERAUTH_SUCCESS: - tc.startCompression(); - - // Continue with message handlers - default: - boolean handled = false; - - for (HandlerEntry handler : messageHandlers) { - if ((handler.low <= type) && (type <= handler.high)) { - handler.mh.handleMessage(packet); - handled = true; - break; - } - } - - if (!handled) { - throw new PacketTypeException(type); - } - - break; - } - - if (log.isDebugEnabled()) { - log.debug(String.format("Handled packet %d", type)); - } - } - } -}
--- a/src/ch/ethz/ssh2/util/StringEncoder.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. - * All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ -package ch.ethz.ssh2.util; - -import java.io.UnsupportedEncodingException; - -/** - * @author Christian Plattner - * @version $Id: StringEncoder.java 43 2011-06-21 18:34:06Z dkocher@sudo.ch $ - */ -public class StringEncoder { - public static byte[] GetBytes(String data) { - try { - return data.getBytes("UTF-8"); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - public static String GetString(byte[] data) { - return GetString(data, 0, data.length); - } - - public static String GetString(byte[] data, int off, int len) { - try { - return new String(data, off, len, "UTF-8"); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } -}
--- a/src/ch/ethz/ssh2/util/TimeoutService.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. - * Please refer to the LICENSE.txt for licensing details. - */ - -package ch.ethz.ssh2.util; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedList; - -import ch.ethz.ssh2.log.Logger; - -/** - * TimeoutService (beta). Here you can register a timeout. - * <p> - * Implemented having large scale programs in mind: if you open many concurrent SSH connections - * that rely on timeouts, then there will be only one timeout thread. Once all timeouts - * have expired/are cancelled, the thread will (sooner or later) exit. - * Only after new timeouts arrive a new thread (singleton) will be instantiated. - * - * @author Christian Plattner - * @version $Id: TimeoutService.java 89 2014-04-07 14:36:24Z dkocher@sudo.ch $ - */ -public class TimeoutService { - private static final Logger log = Logger.getLogger(TimeoutService.class); - - public static class TimeoutToken { - private long runTime; - private Runnable handler; - - private TimeoutToken(long runTime, Runnable handler) { - this.runTime = runTime; - this.handler = handler; - } - } - - private static class TimeoutThread extends Thread { - @Override - public void run() { - synchronized (todolist) { - while (true) { - if (todolist.size() == 0) { - timeoutThread = null; - return; - } - - long now = System.currentTimeMillis(); - TimeoutToken tt = todolist.getFirst(); - - if (tt.runTime > now) { - /* Not ready yet, sleep a little bit */ - try { - todolist.wait(tt.runTime - now); - } - catch (InterruptedException ignored) { - } - - /* We cannot simply go on, since it could be that the token - * was removed (cancelled) or another one has been inserted in - * the meantime. - */ - continue; - } - - todolist.removeFirst(); - - try { - tt.handler.run(); - } - catch (Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - log.warning("Exeception in Timeout handler:" + e.getMessage() + "(" + sw.toString() + ")"); - } - } - } - } - } - - /* The list object is also used for locking purposes */ - private static final LinkedList<TimeoutToken> todolist = new LinkedList<TimeoutService.TimeoutToken>(); - - private static Thread timeoutThread = null; - - /** - * It is assumed that the passed handler will not execute for a long time. - * - * @param runTime - * @param handler - * @return a TimeoutToken that can be used to cancel the timeout. - */ - public static TimeoutToken addTimeoutHandler(long runTime, Runnable handler) { - TimeoutToken token = new TimeoutToken(runTime, handler); - - synchronized (todolist) { - todolist.add(token); - Collections.sort(todolist, new Comparator<TimeoutToken>() { - public int compare(TimeoutToken o1, TimeoutToken o2) { - if (o1.runTime > o2.runTime) - return 1; - - if (o1.runTime == o2.runTime) - return 0; - - return -1; - } - }); - - if (timeoutThread != null) - timeoutThread.interrupt(); - else { - timeoutThread = new TimeoutThread(); - timeoutThread.setDaemon(true); - timeoutThread.start(); - } - } - - return token; - } - - public static void cancelTimeoutHandler(TimeoutToken token) { - synchronized (todolist) { - todolist.remove(token); - - if (timeoutThread != null) - timeoutThread.interrupt(); - } - } - -}
--- a/src/com/five_ten_sg/connectbot/ActionBarWrapper.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import com.five_ten_sg.connectbot.util.PreferenceConstants; -import android.annotation.TargetApi; -import android.app.ActionBar; -import android.app.Activity; - -public abstract class ActionBarWrapper { - public interface OnMenuVisibilityListener { - public void onMenuVisibilityChanged(boolean isVisible); - } - - public static ActionBarWrapper getActionBar(Activity activity) { - if (PreferenceConstants.PRE_HONEYCOMB) - return new DummyActionBar(); - else - return new RealActionBar(activity); - } - - public void hide() { - } - - public void show() { - } - - public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { - } - - public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { - } - - private static class DummyActionBar extends ActionBarWrapper { - } - - @TargetApi(11) - private static class RealActionBar extends ActionBarWrapper { - private final ActionBar actionBar; - - public RealActionBar(Activity activity) { - actionBar = activity.getActionBar(); - } - - @Override - public void hide() { - actionBar.hide(); - } - - @Override - public void show() { - actionBar.show(); - } - - @Override - public void addOnMenuVisibilityListener(final OnMenuVisibilityListener listener) { - actionBar.addOnMenuVisibilityListener(new ActionBar.OnMenuVisibilityListener() { - public void onMenuVisibilityChanged(boolean isVisible) { - listener.onMenuVisibilityChanged(isVisible); - } - }); - } - - @Override - public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { - actionBar.setDisplayHomeAsUpEnabled(showHomeAsUp); - } - } -}
--- a/src/com/five_ten_sg/connectbot/ColorsActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,319 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import java.util.Arrays; -import java.util.List; - -import com.five_ten_sg.connectbot.util.Colors; -import com.five_ten_sg.connectbot.util.HostDatabase; -import com.five_ten_sg.connectbot.util.UberColorPickerDialog; -import com.five_ten_sg.connectbot.util.UberColorPickerDialog.OnColorChangedListener; -import android.app.Activity; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MenuItem.OnMenuItemClickListener; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.BaseAdapter; -import android.widget.GridView; -import android.widget.Spinner; - -/** - * @author Kenny Root - * - */ -public class ColorsActivity extends Activity implements OnItemClickListener, OnColorChangedListener, OnItemSelectedListener { - private GridView mColorGrid; - private Spinner mFgSpinner; - private Spinner mBgSpinner; - - private int mColorScheme; - - private List<Integer> mColorList; - private HostDatabase hostdb; - - private int mCurrentColor = 0; - - private int[] mDefaultColors; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.act_colors); - this.setTitle(String.format("%s: %s", - getResources().getText(R.string.app_name), - getResources().getText(R.string.title_colors))); - mColorScheme = HostDatabase.DEFAULT_COLOR_SCHEME; - hostdb = new HostDatabase(this); - mColorList = Arrays.asList(hostdb.getColorsForScheme(mColorScheme)); - mDefaultColors = hostdb.getDefaultColorsForScheme(mColorScheme); - mColorGrid = (GridView) findViewById(R.id.color_grid); - mColorGrid.setAdapter(new ColorsAdapter(true)); - mColorGrid.setOnItemClickListener(this); - mColorGrid.setSelection(0); - mFgSpinner = (Spinner) findViewById(R.id.fg); - mFgSpinner.setAdapter(new ColorsAdapter(false)); - mFgSpinner.setSelection(mDefaultColors[0]); - mFgSpinner.setOnItemSelectedListener(this); - mBgSpinner = (Spinner) findViewById(R.id.bg); - mBgSpinner.setAdapter(new ColorsAdapter(false)); - mBgSpinner.setSelection(mDefaultColors[1]); - mBgSpinner.setOnItemSelectedListener(this); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - - if (hostdb != null) { - hostdb.close(); - hostdb = null; - } - } - - @Override - protected void onResume() { - super.onResume(); - - if (hostdb == null) - hostdb = new HostDatabase(this); - } - - private class ColorsAdapter extends BaseAdapter { - private boolean mSquareViews; - - public ColorsAdapter(boolean squareViews) { - mSquareViews = squareViews; - } - - public View getView(int position, View convertView, ViewGroup parent) { - ColorView c; - - if (convertView == null) { - c = new ColorView(ColorsActivity.this, mSquareViews); - } - else { - c = (ColorView) convertView; - } - - c.setColor(mColorList.get(position)); - c.setNumber(position + 1); - return c; - } - - public int getCount() { - return mColorList.size(); - } - - public Object getItem(int position) { - return mColorList.get(position); - } - - public long getItemId(int position) { - return position; - } - } - - private class ColorView extends View { - private boolean mSquare; - - private Paint mTextPaint; - private Paint mShadowPaint; - - // Things we paint - private int mBackgroundColor; - private String mText; - - private int mAscent; - private int mWidthCenter; - private int mHeightCenter; - - public ColorView(Context context, boolean square) { - super(context); - mSquare = square; - mTextPaint = new Paint(); - mTextPaint.setAntiAlias(true); - mTextPaint.setTextSize(16); - mTextPaint.setColor(0xFFFFFFFF); - mTextPaint.setTextAlign(Paint.Align.CENTER); - mShadowPaint = new Paint(mTextPaint); - mShadowPaint.setStyle(Paint.Style.STROKE); - mShadowPaint.setStrokeCap(Paint.Cap.ROUND); - mShadowPaint.setStrokeJoin(Paint.Join.ROUND); - mShadowPaint.setStrokeWidth(4f); - mShadowPaint.setColor(0xFF000000); - setPadding(10, 10, 10, 10); - } - - public void setColor(int color) { - mBackgroundColor = color; - } - - public void setNumber(int number) { - mText = Integer.toString(number); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int width = measureWidth(widthMeasureSpec); - int height; - - if (mSquare) - height = width; - else - height = measureHeight(heightMeasureSpec); - - mAscent = (int) mTextPaint.ascent(); - mWidthCenter = width / 2; - mHeightCenter = height / 2 - mAscent / 2; - setMeasuredDimension(width, height); - } - - private int measureWidth(int measureSpec) { - int result = 0; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - if (specMode == MeasureSpec.EXACTLY) { - // We were told how big to be - result = specSize; - } - else { - // Measure the text - result = (int) mTextPaint.measureText(mText) + getPaddingLeft() - + getPaddingRight(); - - if (specMode == MeasureSpec.AT_MOST) { - // Respect AT_MOST value if that was what is called for by - // measureSpec - result = Math.min(result, specSize); - } - } - - return result; - } - - private int measureHeight(int measureSpec) { - int result = 0; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - mAscent = (int) mTextPaint.ascent(); - - if (specMode == MeasureSpec.EXACTLY) { - // We were told how big to be - result = specSize; - } - else { - // Measure the text (beware: ascent is a negative number) - result = (int)(-mAscent + mTextPaint.descent()) - + getPaddingTop() + getPaddingBottom(); - - if (specMode == MeasureSpec.AT_MOST) { - // Respect AT_MOST value if that was what is called for by - // measureSpec - result = Math.min(result, specSize); - } - } - - return result; - } - - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - canvas.drawColor(mBackgroundColor); - canvas.drawText(mText, mWidthCenter, mHeightCenter, mShadowPaint); - canvas.drawText(mText, mWidthCenter, mHeightCenter, mTextPaint); - } - } - - private void editColor(int colorNumber) { - mCurrentColor = colorNumber; - new UberColorPickerDialog(this, this, mColorList.get(colorNumber)).show(); - } - - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - editColor(position); - } - - public void onNothingSelected(AdapterView<?> arg0) { } - - public void colorChanged(int value) { - hostdb.setGlobalColor(mCurrentColor, value); - mColorList.set(mCurrentColor, value); - mColorGrid.invalidateViews(); - } - - public void onItemSelected(AdapterView<?> parent, View view, int position, - long id) { - boolean needUpdate = false; - - if (parent == mFgSpinner) { - if (position != mDefaultColors[0]) { - mDefaultColors[0] = position; - needUpdate = true; - } - } - else if (parent == mBgSpinner) { - if (position != mDefaultColors[1]) { - mDefaultColors[1] = position; - needUpdate = true; - } - } - - if (needUpdate) - hostdb.setDefaultColorsForScheme(mColorScheme, mDefaultColors[0], mDefaultColors[1]); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - MenuItem reset = menu.add(R.string.menu_colors_reset); - reset.setAlphabeticShortcut('r'); - reset.setNumericShortcut('1'); - reset.setIcon(android.R.drawable.ic_menu_revert); - reset.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem arg0) { - // Reset each individual color to defaults. - for (int i = 0; i < Colors.defaults.length; i++) { - if (mColorList.get(i) != Colors.defaults[i]) { - hostdb.setGlobalColor(i, Colors.defaults[i]); - mColorList.set(i, Colors.defaults[i]); - } - } - - mColorGrid.invalidateViews(); - // Reset the default FG/BG colors as well. - mFgSpinner.setSelection(HostDatabase.DEFAULT_FG_COLOR); - mBgSpinner.setSelection(HostDatabase.DEFAULT_BG_COLOR); - hostdb.setDefaultColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME, - HostDatabase.DEFAULT_FG_COLOR, HostDatabase.DEFAULT_BG_COLOR); - return true; - } - }); - return true; - } -}
--- a/src/com/five_ten_sg/connectbot/ConsoleActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1508 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import java.io.File; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import com.five_ten_sg.connectbot.bean.SelectionArea; -import com.five_ten_sg.connectbot.service.PromptHelper; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalKeyListener; -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.util.FileChooser; -import com.five_ten_sg.connectbot.util.FileChooserCallback; -import com.five_ten_sg.connectbot.util.PreferenceConstants; -import com.five_ten_sg.connectbot.util.TransferThread; -import android.app.Activity; -import android.app.AlertDialog; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.pm.ActivityInfo; -import android.content.res.Configuration; -import android.media.AudioManager; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.preference.PreferenceManager; -import android.text.ClipboardManager; -import android.text.InputType; -import android.text.method.PasswordTransformationMethod; -import android.text.method.SingleLineTransformationMethod; -import android.util.FloatMath; -import android.util.Log; -import android.view.GestureDetector; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MenuItem.OnMenuItemClickListener; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnKeyListener; -import android.view.View.OnLongClickListener; -import android.view.View.OnTouchListener; -import android.view.ViewConfiguration; -import android.view.WindowManager; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.view.inputmethod.InputMethodManager; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; -import android.widget.Toast; -import android.widget.ViewFlipper; -import de.mud.terminal.vt320; - -public class ConsoleActivity extends Activity implements FileChooserCallback { - public final static String TAG = "ConnectBot.ConsoleActivity"; - - protected static final int REQUEST_EDIT = 1; - - private static final int CLICK_TIME = 400; - private static final float MAX_CLICK_DISTANCE = 25f; - private static final int KEYBOARD_DISPLAY_TIME = 1500; - - // Direction to shift the ViewFlipper - private static final int SHIFT_LEFT = 0; - private static final int SHIFT_RIGHT = 1; - - protected ViewFlipper flip = null; - protected TerminalManager bound = null; - protected LayoutInflater inflater = null; - - private SharedPreferences prefs = null; - - // determines whether or not menuitem accelerators are bound - // otherwise they collide with an external keyboard's CTRL-char - private boolean hardKeyboard = false; - - // determines whether we are in the fullscreen mode - private static final int FULLSCREEN_ON = 1; - private static final int FULLSCREEN_OFF = 2; - - private int fullScreen; - - protected Uri requested; - - protected ClipboardManager clipboard; - private RelativeLayout stringPromptGroup; - protected EditText stringPrompt; - private TextView stringPromptInstructions; - - private RelativeLayout booleanPromptGroup; - private TextView booleanPrompt; - private Button booleanYes, booleanNo; - - private RelativeLayout keyboardGroup; - private Runnable keyboardGroupHider; - - private TextView empty; - - private Animation slide_left_in, slide_left_out, slide_right_in, slide_right_out, fade_stay_hidden, fade_out_delayed; - - private Animation keyboard_fade_in, keyboard_fade_out; - private float lastX, lastY; - - private InputMethodManager inputManager; - - private MenuItem disconnect, copy, paste, portForward, resize, urlscan, screenCapture, download, upload; - - protected TerminalBridge copySource = null; - private int lastTouchRow, lastTouchCol; - - private boolean forcedOrientation; - - private Handler handler = new Handler(); - - private ImageView mKeyboardButton; - - private ActionBarWrapper actionBar; - private boolean inActionBarMenu = false; - - private ServiceConnection connection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - bound = ((TerminalManager.TerminalBinder) service).getService(); - // let manager know about our event handling services - bound.disconnectHandler = disconnectHandler; - Log.d(TAG, String.format("Connected to TerminalManager and found bridges.size=%d", bound.bridges.size())); - bound.setResizeAllowed(true); - bound.hardKeyboardHidden = (getResources().getConfiguration().hardKeyboardHidden == - Configuration.HARDKEYBOARDHIDDEN_YES); - - // set fullscreen value - if (bound.getFullScreen() == 0) { - setFullScreen(FULLSCREEN_OFF); - } - else if (fullScreen != bound.getFullScreen()) - setFullScreen(bound.getFullScreen()); - - // clear out any existing bridges and record requested index - flip.removeAllViews(); - final String requestedNickname = (requested != null) ? requested.getFragment() : null; - int requestedIndex = -1; - TerminalBridge requestedBridge = bound.getConnectedBridge(requestedNickname); - - // If we didn't find the requested connection, try opening it - if (requestedNickname != null && requestedBridge == null) { - try { - Log.d(TAG, String.format("We couldnt find an existing bridge with URI=%s (nickname=%s), so creating one now", requested.toString(), requestedNickname)); - requestedBridge = bound.openConnection(requested); - } - catch (Exception e) { - Log.e(TAG, "Problem while trying to create new requested bridge from URI", e); - } - } - - // create views for all bridges on this service - for (TerminalBridge bridge : bound.bridges) { - final int currentIndex = addNewTerminalView(bridge); - - // check to see if this bridge was requested - if (bridge == requestedBridge) { - requestedIndex = currentIndex; - // store this bridge as default bridge - bound.defaultBridge = bridge; - } - } - - // if no bridge was requested, try using default bridge - if (requestedIndex < 0) { - requestedIndex = getFlipIndex(bound.defaultBridge); - - if (requestedIndex < 0) - requestedIndex = 0; - } - - setDisplayedTerminal(requestedIndex); - } - public void onServiceDisconnected(ComponentName className) { - // tell each bridge to forget about our prompt handler - synchronized (bound.bridges) { - for (TerminalBridge bridge : bound.bridges) - bridge.promptHelper.setHandler(null); - } - - flip.removeAllViews(); - updateEmptyVisible(); - bound = null; - } - }; - - protected Handler promptHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - // someone below us requested to display a prompt - updatePromptVisible(); - } - }; - - protected Handler disconnectHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - Log.d(TAG, "Someone sending HANDLE_DISCONNECT to parentHandler"); - // someone below us requested to display a password dialog - // they are sending nickname and requested - TerminalBridge bridge = (TerminalBridge)msg.obj; - - if (bridge.isAwaitingClose()) - closeBridge(bridge); - } - }; - - /** - * @param bridge - */ - private void closeBridge(final TerminalBridge bridge) { - synchronized (flip) { - final int flipIndex = getFlipIndex(bridge); - - if (flipIndex >= 0) { - if (flip.getDisplayedChild() == flipIndex) { - shiftCurrentTerminal(SHIFT_LEFT); - } - - flip.removeViewAt(flipIndex); - /* TODO Remove this workaround when ViewFlipper is fixed to listen - * to view removals. Android Issue 1784 - */ - final int numChildren = flip.getChildCount(); - - if (flip.getDisplayedChild() >= numChildren && - numChildren > 0) { - flip.setDisplayedChild(numChildren - 1); - } - - updateEmptyVisible(); - } - - // If we just closed the last bridge, go back to the previous activity. - if (flip.getChildCount() == 0) { - finish(); - } - } - } - - protected View findCurrentView(int id) { - View view = flip.getCurrentView(); - - if (view == null) return null; - - return view.findViewById(id); - } - - protected PromptHelper getCurrentPromptHelper() { - View view = findCurrentView(R.id.console_flip); - - if (!(view instanceof TerminalView)) return null; - - return ((TerminalView)view).bridge.promptHelper; - } - - protected void hideAllPrompts() { - stringPromptGroup.setVisibility(View.GONE); - booleanPromptGroup.setVisibility(View.GONE); - // adjust window back if size was changed during prompt input - View view = findCurrentView(R.id.console_flip); - - if (!(view instanceof TerminalView)) return; - - ((TerminalView)view).bridge.parentChanged((TerminalView)view); - } - - private void showEmulatedKeys() { - keyboardGroup.startAnimation(keyboard_fade_in); - keyboardGroup.setVisibility(View.VISIBLE); - actionBar.show(); - - if (keyboardGroupHider != null) - handler.removeCallbacks(keyboardGroupHider); - - keyboardGroupHider = new Runnable() { - public void run() { - if (keyboardGroup.getVisibility() == View.GONE || inActionBarMenu) - return; - - keyboardGroup.startAnimation(keyboard_fade_out); - keyboardGroup.setVisibility(View.GONE); - actionBar.hide(); - keyboardGroupHider = null; - } - }; - handler.postDelayed(keyboardGroupHider, KEYBOARD_DISPLAY_TIME); - } - - private void hideEmulatedKeys() { - if (keyboardGroupHider != null) - handler.removeCallbacks(keyboardGroupHider); - - keyboardGroup.setVisibility(View.GONE); - actionBar.hide(); - } - - // more like configureLaxMode -- enable network IO on UI thread - private void configureStrictMode() { - try { - Class.forName("android.os.StrictMode"); - StrictModeSetup.run(); - } - catch (ClassNotFoundException e) { - } - } - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - configureStrictMode(); - hardKeyboard = getResources().getConfiguration().keyboard == - Configuration.KEYBOARD_QWERTY; - this.setContentView(R.layout.act_console); - clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE); - prefs = PreferenceManager.getDefaultSharedPreferences(this); - // TODO find proper way to disable volume key beep if it exists. - setVolumeControlStream(AudioManager.STREAM_MUSIC); - // handle requested console from incoming intent - requested = getIntent().getData(); - inflater = LayoutInflater.from(this); - flip = (ViewFlipper)findViewById(R.id.console_flip); - empty = (TextView)findViewById(android.R.id.empty); - stringPromptGroup = (RelativeLayout) findViewById(R.id.console_password_group); - stringPromptInstructions = (TextView) findViewById(R.id.console_password_instructions); - stringPrompt = (EditText)findViewById(R.id.console_password); - stringPrompt.setOnKeyListener(new OnKeyListener() { - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_UP) return false; - - if (keyCode != KeyEvent.KEYCODE_ENTER) return false; - - // pass collected password down to current terminal - String value = stringPrompt.getText().toString(); - PromptHelper helper = getCurrentPromptHelper(); - - if (helper == null) return false; - - helper.setResponse(value); - // finally clear password for next user - stringPrompt.setText(""); - updatePromptVisible(); - return true; - } - }); - booleanPromptGroup = (RelativeLayout) findViewById(R.id.console_boolean_group); - booleanPrompt = (TextView)findViewById(R.id.console_prompt); - booleanYes = (Button)findViewById(R.id.console_prompt_yes); - booleanYes.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - PromptHelper helper = getCurrentPromptHelper(); - - if (helper == null) return; - - helper.setResponse(Boolean.TRUE); - updatePromptVisible(); - } - }); - booleanNo = (Button)findViewById(R.id.console_prompt_no); - booleanNo.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - PromptHelper helper = getCurrentPromptHelper(); - - if (helper == null) return; - - helper.setResponse(Boolean.FALSE); - updatePromptVisible(); - } - }); - // preload animations for terminal switching - slide_left_in = AnimationUtils.loadAnimation(this, R.anim.slide_left_in); - slide_left_out = AnimationUtils.loadAnimation(this, R.anim.slide_left_out); - slide_right_in = AnimationUtils.loadAnimation(this, R.anim.slide_right_in); - slide_right_out = AnimationUtils.loadAnimation(this, R.anim.slide_right_out); - fade_out_delayed = AnimationUtils.loadAnimation(this, R.anim.fade_out_delayed); - fade_stay_hidden = AnimationUtils.loadAnimation(this, R.anim.fade_stay_hidden); - // Preload animation for keyboard button - keyboard_fade_in = AnimationUtils.loadAnimation(this, R.anim.keyboard_fade_in); - keyboard_fade_out = AnimationUtils.loadAnimation(this, R.anim.keyboard_fade_out); - inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - keyboardGroup = (RelativeLayout) findViewById(R.id.keyboard_group); - mKeyboardButton = (ImageView) findViewById(R.id.button_keyboard); - mKeyboardButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) - return; - - inputManager.showSoftInput(flip, InputMethodManager.SHOW_FORCED); - hideEmulatedKeys(); - } - }); - final ImageView symButton = (ImageView) findViewById(R.id.button_sym); - symButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) return; - - TerminalView terminal = (TerminalView)flip; - terminal.bridge.showCharPickerDialog(); - keyboardGroup.setVisibility(View.GONE); - } - }); - symButton.setOnLongClickListener(new OnLongClickListener() { - public boolean onLongClick(View view) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) return false; - - TerminalView terminal = (TerminalView)flip; - terminal.bridge.showArrowsDialog(); - return true; - } - }); - final ImageView mInputButton = (ImageView) findViewById(R.id.button_input); - mInputButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) return; - - final TerminalView terminal = (TerminalView)flip; - Thread promptThread = new Thread(new Runnable() { - public void run() { - String inj = getCurrentPromptHelper().requestStringPrompt(null, ""); - terminal.bridge.injectString(inj); - } - }); - promptThread.setName("Prompt"); - promptThread.setDaemon(true); - promptThread.start(); - keyboardGroup.setVisibility(View.GONE); - } - }); - final ImageView ctrlButton = (ImageView) findViewById(R.id.button_ctrl); - ctrlButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) return; - - TerminalView terminal = (TerminalView)flip; - TerminalKeyListener handler = terminal.bridge.getKeyHandler(); - handler.metaPress(TerminalKeyListener.META_CTRL_ON); - hideEmulatedKeys(); - } - }); - ctrlButton.setOnLongClickListener(new OnLongClickListener() { - public boolean onLongClick(View view) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) return false; - - TerminalView terminal = (TerminalView)flip; - terminal.bridge.showCtrlDialog(); - return true; - } - }); - final ImageView escButton = (ImageView) findViewById(R.id.button_esc); - escButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) return; - - TerminalView terminal = (TerminalView)flip; - TerminalKeyListener handler = terminal.bridge.getKeyHandler(); - handler.sendEscape(); - hideEmulatedKeys(); - } - }); - escButton.setOnLongClickListener(new OnLongClickListener() { - public boolean onLongClick(View view) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) return false; - - TerminalView terminal = (TerminalView)flip; - terminal.bridge.showFKeysDialog(); - return true; - } - }); - actionBar = ActionBarWrapper.getActionBar(this); - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.hide(); - actionBar.addOnMenuVisibilityListener(new ActionBarWrapper.OnMenuVisibilityListener() { - public void onMenuVisibilityChanged(boolean isVisible) { - inActionBarMenu = isVisible; - - if (isVisible == false) { - hideEmulatedKeys(); - } - } - }); - // detect fling gestures to switch between terminals - final GestureDetector gestDetect = new GestureDetector(new GestureDetector.SimpleOnGestureListener() { - private float totalY = 0; - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - final float distx = e2.getRawX() - e1.getRawX(); - final float disty = e2.getRawY() - e1.getRawY(); - final int goalwidth = flip.getWidth() / 2; - - // need to slide across half of display to trigger console change - // make sure user kept a steady hand horizontally - if (Math.abs(disty) < (flip.getHeight() / 4)) { - if (distx > goalwidth) { - shiftCurrentTerminal(SHIFT_RIGHT); - return true; - } - - if (distx < -goalwidth) { - shiftCurrentTerminal(SHIFT_LEFT); - return true; - } - } - - return false; - } - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - // if copying, then ignore - if (copySource != null && copySource.isSelectingForCopy()) - return false; - - if (e1 == null || e2 == null) - return false; - - // if releasing then reset total scroll - if (e2.getAction() == MotionEvent.ACTION_UP) { - totalY = 0; - } - - // activate consider if within x tolerance - if (Math.abs(e1.getX() - e2.getX()) < ViewConfiguration.getTouchSlop() * 4) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) return false; - - TerminalView terminal = (TerminalView)flip; - // estimate how many rows we have scrolled through - // accumulate distance that doesn't trigger immediate scroll - totalY += distanceY; - final int moved = (int)(totalY / terminal.bridge.charHeight); - - // consume as scrollback only if towards right half of screen - if (e2.getX() > flip.getWidth() / 2) { - if (moved != 0) { - int base = terminal.bridge.buffer.getWindowBase(); - terminal.bridge.buffer.setWindowBase(base + moved); - totalY = 0; - return true; - } - } - else { - // otherwise consume as pgup/pgdown for every 5 lines - if (moved > 5) { - ((vt320)terminal.bridge.buffer).keyPressed(vt320.KEY_PAGE_DOWN, ' ', 0); - terminal.bridge.tryKeyVibrate(); - totalY = 0; - return true; - } - else if (moved < -5) { - ((vt320)terminal.bridge.buffer).keyPressed(vt320.KEY_PAGE_UP, ' ', 0); - terminal.bridge.tryKeyVibrate(); - totalY = 0; - return true; - } - } - } - - return false; - } - /* - * Enables longpress and popups menu - * - * @see - * android.view.GestureDetector.SimpleOnGestureListener# - * onLongPress(android.view.MotionEvent) - * - * @return void - */ - @Override - public void onLongPress(MotionEvent e) { - List<String> itemList = new ArrayList<String>(); - final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - - if (terminalView == null) return; - - final TerminalBridge bridge = terminalView.bridge; - - if (fullScreen == FULLSCREEN_ON) - itemList.add(ConsoleActivity.this - .getResources().getString(R.string.longpress_disable_full_screen_mode)); - else - itemList.add(ConsoleActivity.this - .getResources().getString(R.string.longpress_enable_full_screen_mode)); - - itemList.add(ConsoleActivity.this - .getResources().getString(R.string.longpress_change_font_size)); - - if (prefs.getBoolean(PreferenceConstants.EXTENDED_LONGPRESS, false)) { - itemList.add(ConsoleActivity.this - .getResources().getString(R.string.longpress_arrows_dialog)); - itemList.add(ConsoleActivity.this - .getResources().getString(R.string.longpress_fkeys_dialog)); - itemList.add(ConsoleActivity.this - .getResources().getString(R.string.longpress_ctrl_dialog)); - itemList.add(ConsoleActivity.this - .getResources().getString(R.string.longpress_sym_dialog)); - } - - if (itemList.size() > 0) { - AlertDialog.Builder builder = new AlertDialog.Builder(ConsoleActivity.this); - builder.setTitle(R.string.longpress_select_action); - builder.setItems(itemList.toArray(new CharSequence[itemList.size()]), - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - switch (item) { - case 0: - if (fullScreen == FULLSCREEN_ON) { - setFullScreen(FULLSCREEN_OFF); - } - else - setFullScreen(FULLSCREEN_ON); - - break; - - case 1: - bridge.showFontSizeDialog(); - break; - - case 2: - bridge.showArrowsDialog(); - break; - - case 3: - bridge.showFKeysDialog(); - break; - - case 4: - bridge.showCtrlDialog(); - break; - - case 5: - bridge.showCharPickerDialog(); - } - } - }); - AlertDialog alert = builder.create(); - alert.show(); - } - } - }); - flip.setLongClickable(true); - flip.setOnTouchListener(new OnTouchListener() { - public boolean onTouch(View v, MotionEvent event) { - // when copying, highlight the area - if (copySource != null && copySource.isSelectingForCopy()) { - int row = (int)FloatMath.floor(event.getY() / copySource.charHeight); - int col = (int)FloatMath.floor(event.getX() / copySource.charWidth); - SelectionArea area = copySource.getSelectionArea(); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - - // recording starting area - if (area.isSelectingOrigin()) { - area.setRow(row); - area.setColumn(col); - lastTouchRow = row; - lastTouchCol = col; - copySource.redraw(); - } - - return true; - - case MotionEvent.ACTION_MOVE: - - /* ignore when user hasn't moved since last time so - * we can fine-tune with directional pad - */ - if (row == lastTouchRow && col == lastTouchCol) - return true; - - // if the user moves, start the selection for other corner - area.finishSelectingOrigin(); - // update selected area - area.setRow(row); - area.setColumn(col); - lastTouchRow = row; - lastTouchCol = col; - copySource.redraw(); - return true; - - case MotionEvent.ACTION_UP: - - /* If they didn't move their finger, maybe they meant to - * select the rest of the text with the directional pad. - */ - if (area.getLeft() == area.getRight() && - area.getTop() == area.getBottom()) { - return true; - } - - // copy selected area to clipboard - String copiedText = area.copyFrom(copySource.buffer); - clipboard.setText(copiedText); - Toast.makeText(ConsoleActivity.this, getString(R.string.console_copy_done, copiedText.length()), Toast.LENGTH_LONG).show(); - - // fall through to clear state - case MotionEvent.ACTION_CANCEL: - // make sure we clear any highlighted area - area.reset(); - copySource.setSelectingForCopy(false); - copySource.redraw(); - return true; - } - } - - Configuration config = getResources().getConfiguration(); - - if (event.getAction() == MotionEvent.ACTION_DOWN) { - lastX = event.getX(); - lastY = event.getY(); - } - else if (event.getAction() == MotionEvent.ACTION_UP - && keyboardGroup.getVisibility() == View.GONE - && event.getEventTime() - event.getDownTime() < CLICK_TIME - && Math.abs(event.getX() - lastX) < MAX_CLICK_DISTANCE - && Math.abs(event.getY() - lastY) < MAX_CLICK_DISTANCE) { - showEmulatedKeys(); - } - - // pass any touch events back to BOTH detectors - TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - boolean rc = false; - if ((terminalView != null) && terminalView.mScaleDetector.onTouchEvent(event)) rc = true; - if (gestDetect.onTouchEvent(event)) rc = true; - return rc; - } - }); - } - - /** - * - */ - private void configureOrientation() { - String rotateDefault; - - if (getResources().getConfiguration().keyboard == Configuration.KEYBOARD_NOKEYS) - rotateDefault = PreferenceConstants.ROTATION_PORTRAIT; - else - rotateDefault = PreferenceConstants.ROTATION_LANDSCAPE; - - String rotate = prefs.getString(PreferenceConstants.ROTATION, rotateDefault); - - if (PreferenceConstants.ROTATION_DEFAULT.equals(rotate)) - rotate = rotateDefault; - - // request a forced orientation if requested by user - if (PreferenceConstants.ROTATION_LANDSCAPE.equals(rotate)) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - forcedOrientation = true; - } - else if (PreferenceConstants.ROTATION_PORTRAIT.equals(rotate)) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - forcedOrientation = true; - } - else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); - forcedOrientation = false; - } - } - - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - View view = findCurrentView(R.id.console_flip); - final boolean activeTerminal = (view instanceof TerminalView); - boolean sessionOpen = false; - boolean disconnected = false; - boolean canForwardPorts = false; - boolean canTransferFiles = false; - - if (activeTerminal) { - TerminalBridge bridge = ((TerminalView) view).bridge; - sessionOpen = bridge.isSessionOpen(); - disconnected = bridge.isDisconnected(); - canForwardPorts = bridge.canFowardPorts(); - canTransferFiles = bridge.canTransferFiles(); - } - - menu.setQwertyMode(true); - - if (!PreferenceConstants.PRE_HONEYCOMB) { - MenuItem ctrlKey = menu.add(getString(R.string.fullscreen)); - ctrlKey.setEnabled(activeTerminal); - ctrlKey.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - ctrlKey.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem menuItem) { - if (fullScreen == FULLSCREEN_ON) { - setFullScreen(FULLSCREEN_OFF); - } - else - setFullScreen(FULLSCREEN_ON); - - return true; - } - }); - } - - disconnect = menu.add(R.string.list_host_disconnect); - - if (hardKeyboard) - disconnect.setAlphabeticShortcut('w'); - - if (!sessionOpen && disconnected) - disconnect.setTitle(R.string.console_menu_close); - - disconnect.setEnabled(activeTerminal); - disconnect.setIcon(android.R.drawable.ic_menu_close_clear_cancel); - disconnect.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - // disconnect or close the currently visible session - TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - TerminalBridge bridge = terminalView.bridge; - bridge.dispatchDisconnect(true); - return true; - } - }); - copy = menu.add(R.string.console_menu_copy); - - if (hardKeyboard) - copy.setAlphabeticShortcut('c'); - - copy.setIcon(android.R.drawable.ic_menu_set_as); - copy.setEnabled(activeTerminal); - copy.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - // mark as copying and reset any previous bounds - TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - copySource = terminalView.bridge; - SelectionArea area = copySource.getSelectionArea(); - area.reset(); - area.setBounds(copySource.buffer.getColumns(), copySource.buffer.getRows()); - copySource.setSelectingForCopy(true); - // Make sure we show the initial selection - copySource.redraw(); - Toast.makeText(ConsoleActivity.this, getString(R.string.console_copy_start), Toast.LENGTH_LONG).show(); - return true; - } - }); - paste = menu.add(R.string.console_menu_paste); - - if (hardKeyboard) - paste.setAlphabeticShortcut('v'); - - paste.setIcon(android.R.drawable.ic_menu_edit); - paste.setEnabled(clipboard.hasText() && sessionOpen); - paste.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - // force insert of clipboard text into current console - TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - TerminalBridge bridge = terminalView.bridge; - // pull string from clipboard and generate all events to force down - String clip = clipboard.getText().toString(); - bridge.injectString(clip); - return true; - } - }); - resize = menu.add(R.string.console_menu_resize); - - if (hardKeyboard) - resize.setAlphabeticShortcut('r'); - - resize.setIcon(android.R.drawable.ic_menu_crop); - resize.setEnabled(activeTerminal); - resize.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - final View resizeView = inflater.inflate(R.layout.dia_resize, null, false); - ((EditText) resizeView.findViewById(R.id.width)).setText("80"); - ((EditText) resizeView.findViewById(R.id.height)).setText("25"); - new AlertDialog.Builder(ConsoleActivity.this) - .setView(resizeView) - .setPositiveButton(R.string.button_resize, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - int width, height; - - try { - width = Integer.parseInt(((EditText) resizeView - .findViewById(R.id.width)) - .getText().toString()); - height = Integer.parseInt(((EditText) resizeView - .findViewById(R.id.height)) - .getText().toString()); - } - catch (NumberFormatException nfe) { - // TODO change this to a real dialog where we can - // make the input boxes turn red to indicate an error. - return; - } - - if (width > 0 && height > 0) { - terminalView.forceSize(width, height); - } - else { - new AlertDialog.Builder(ConsoleActivity.this) - .setTitle(R.string.resize_error_title) - .setMessage(R.string.resize_error_width_height) - .setNegativeButton(R.string.button_close, null) - .show(); - } - } - }).setNeutralButton(R.string.button_resize_reset, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - terminalView.bridge.resetSize(terminalView); - } - }).setNegativeButton(android.R.string.cancel, null) - .create().show(); - return true; - } - }); - screenCapture = menu.add(R.string.console_menu_screencapture); - - if (hardKeyboard) - screenCapture.setAlphabeticShortcut('s'); - - screenCapture.setIcon(android.R.drawable.ic_menu_camera); - screenCapture.setEnabled(activeTerminal); - screenCapture.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - terminalView.bridge.captureScreen(); - return true; - } - }); - portForward = menu.add(R.string.console_menu_portforwards); - - if (hardKeyboard) - portForward.setAlphabeticShortcut('f'); - - portForward.setIcon(android.R.drawable.ic_menu_manage); - portForward.setEnabled(sessionOpen && canForwardPorts); - portForward.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - TerminalBridge bridge = terminalView.bridge; - Intent intent = new Intent(ConsoleActivity.this, PortForwardListActivity.class); - intent.putExtra(Intent.EXTRA_TITLE, bridge.host.getId()); - ConsoleActivity.this.startActivityForResult(intent, REQUEST_EDIT); - return true; - } - }); - urlscan = menu.add(R.string.console_menu_urlscan); - - if (hardKeyboard) - urlscan.setAlphabeticShortcut('l'); - - urlscan.setIcon(android.R.drawable.ic_menu_search); - urlscan.setEnabled(activeTerminal); - urlscan.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - View flip = findCurrentView(R.id.console_flip); - - if (flip == null) return true; - - TerminalView terminal = (TerminalView)flip; - TerminalKeyListener handler = terminal.bridge.getKeyHandler(); - handler.urlScan(terminal); - return true; - } - }); - download = menu.add(R.string.console_menu_download); - download.setAlphabeticShortcut('d'); - download.setEnabled(sessionOpen && canTransferFiles); - download.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - final String downloadFolder = prefs.getString(PreferenceConstants.DOWNLOAD_FOLDER, ""); - final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - final TerminalBridge bridge = terminalView.bridge; - final EditText textField = new EditText(ConsoleActivity.this); - new AlertDialog.Builder(ConsoleActivity.this) - .setTitle(R.string.transfer_select_remote_download_title) - .setMessage(R.string.transfer_select_remote_download_desc) - .setView(textField) - .setPositiveButton(R.string.transfer_button_download, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - TransferThread transfer = new TransferThread(ConsoleActivity.this, handler); - - if (!prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) - transfer.setProgressDialogMessage(getString(R.string.transfer_downloading)); - - transfer.download(bridge, textField.getText().toString(), null, downloadFolder); - } - }).setNegativeButton(android.R.string.cancel, null).create().show(); - return true; - } - }); - upload = menu.add(R.string.console_menu_upload); - upload.setAlphabeticShortcut('u'); - upload.setEnabled(sessionOpen && canTransferFiles); - upload.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - FileChooser.selectFile(ConsoleActivity.this, ConsoleActivity.this, - FileChooser.REQUEST_CODE_SELECT_FILE, - getString(R.string.file_chooser_select_file, getString(R.string.select_for_upload))); - return true; - } - }); - return true; - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - super.onActivityResult(requestCode, resultCode, intent); - - switch (requestCode) { - case FileChooser.REQUEST_CODE_SELECT_FILE: - if (resultCode == RESULT_OK && intent != null) { - Uri uri = intent.getData(); - - try { - if (uri != null) { - fileSelected(new File(URI.create(uri.toString()))); - } - else { - String filename = intent.getDataString(); - - if (filename != null) { - fileSelected(new File(URI.create(filename))); - } - } - } - catch (IllegalArgumentException e) { - Log.e(TAG, "Couldn't read from selected file", e); - } - } - - break; - } - } - - public void fileSelected(final File f) { - String destFileName; - String uploadFolder = prefs.getString(PreferenceConstants.REMOTE_UPLOAD_FOLDER, null); - final TransferThread transfer = new TransferThread(ConsoleActivity.this, handler); - Log.d(TAG, "File chooser returned " + f); - - if (uploadFolder == null) - uploadFolder = ""; - - if (!uploadFolder.equals("") && uploadFolder.charAt(uploadFolder.length() - 1) != '/') - destFileName = uploadFolder + "/" + f.getName(); - else - destFileName = uploadFolder + f.getName(); - - if (prefs.getBoolean(PreferenceConstants.UPLOAD_DESTINATION_PROMPT, true)) { - final EditText fileDest = new EditText(ConsoleActivity.this); - fileDest.setSingleLine(); - fileDest.setText(destFileName); - new AlertDialog.Builder(ConsoleActivity.this) - .setTitle(R.string.transfer_select_remote_upload_dest_title) - .setMessage(getResources().getString(R.string.transfer_select_remote_upload_dest_desc) + "\n" + f.getPath()) - .setView(fileDest) - .setPositiveButton(R.string.transfer_button_upload, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - if (!prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) - transfer.setProgressDialogMessage(getString(R.string.transfer_uploading)); - - TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - TerminalBridge bridge = terminalView.bridge; - File uf = new File(fileDest.getText().toString()); - String name = "", parent = ""; - - if (uf.getParent() != null) - parent = uf.getParent().toString(); - - if (uf.getName() != null) - name = uf.getName().toString(); - - transfer.upload(bridge, f.toString(), name, parent); - } - }).setNegativeButton(android.R.string.cancel, null).create().show(); - } - else { - if (!prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) - transfer.setProgressDialogMessage(getString(R.string.transfer_uploading)); - - TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - TerminalBridge bridge = terminalView.bridge; - transfer.upload(bridge, f.toString(), null, uploadFolder); - } - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - setVolumeControlStream(AudioManager.STREAM_NOTIFICATION); - final View view = findCurrentView(R.id.console_flip); - boolean activeTerminal = (view instanceof TerminalView); - boolean sessionOpen = false; - boolean disconnected = false; - boolean canForwardPorts = false; - boolean canTransferFiles = false; - - if (activeTerminal) { - TerminalBridge bridge = ((TerminalView) view).bridge; - sessionOpen = bridge.isSessionOpen(); - disconnected = bridge.isDisconnected(); - canForwardPorts = bridge.canFowardPorts(); - canTransferFiles = bridge.canTransferFiles(); - } - - disconnect.setEnabled(activeTerminal); - - if (sessionOpen || !disconnected) - disconnect.setTitle(R.string.list_host_disconnect); - else - disconnect.setTitle(R.string.console_menu_close); - - copy.setEnabled(activeTerminal); - paste.setEnabled(clipboard.hasText() && sessionOpen); - portForward.setEnabled(sessionOpen && canForwardPorts); - urlscan.setEnabled(activeTerminal); - resize.setEnabled(activeTerminal); - download.setEnabled(sessionOpen && canTransferFiles); - upload.setEnabled(sessionOpen && canTransferFiles); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - Intent intent = new Intent(this, HostListActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - return true; - - default: - return super.onOptionsItemSelected(item); - } - } - - @Override - public void onOptionsMenuClosed(Menu menu) { - super.onOptionsMenuClosed(menu); - setVolumeControlStream(AudioManager.STREAM_MUSIC); - } - - @Override - public void onStart() { - super.onStart(); - // connect with manager service to find all bridges - // when connected it will insert all views - bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - - if (getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) { - this.mKeyboardButton.setVisibility(View.GONE); - } - } - - @Override - public void onPause() { - super.onPause(); - Log.d(TAG, "onPause called"); - - if (forcedOrientation && bound != null) - bound.setResizeAllowed(false); - } - - @Override - public void onResume() { - super.onResume(); - Log.d(TAG, "onResume called"); - - // Make sure we don't let the screen fall asleep. - // This also keeps the Wi-Fi chipset from disconnecting us. - if (prefs.getBoolean(PreferenceConstants.KEEP_ALIVE, true)) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - else { - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - - configureOrientation(); - - if (forcedOrientation && bound != null) - bound.setResizeAllowed(true); - } - - /* (non-Javadoc) - * @see android.app.Activity#onNewIntent(android.content.Intent) - */ - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - Log.d(TAG, "onNewIntent called"); - requested = intent.getData(); - - if (requested == null) { - Log.e(TAG, "Got null intent data in onNewIntent()"); - return; - } - - if (bound == null) { - Log.e(TAG, "We're not bound in onNewIntent()"); - return; - } - - TerminalBridge requestedBridge = bound.getConnectedBridge(requested.getFragment()); - int requestedIndex = 0; - - synchronized (flip) { - if (requestedBridge == null) { - // If we didn't find the requested connection, try opening it - try { - Log.d(TAG, String.format("We couldnt find an existing bridge with URI=%s (nickname=%s)," + - "so creating one now", requested.toString(), requested.getFragment())); - requestedBridge = bound.openConnection(requested); - } - catch (Exception e) { - Log.e(TAG, "Problem while trying to create new requested bridge from URI", e); - // TODO: We should display an error dialog here. - return; - } - - requestedIndex = addNewTerminalView(requestedBridge); - } - else { - final int flipIndex = getFlipIndex(requestedBridge); - - if (flipIndex > requestedIndex) { - requestedIndex = flipIndex; - } - } - - setDisplayedTerminal(requestedIndex); - } - } - - @Override - public void onStop() { - super.onStop(); - unbindService(connection); - } - - protected void shiftCurrentTerminal(final int direction) { - View overlay; - - synchronized (flip) { - boolean shouldAnimate = flip.getChildCount() > 1; - - // Only show animation if there is something else to go to. - if (shouldAnimate) { - // keep current overlay from popping up again - overlay = findCurrentView(R.id.terminal_overlay); - - if (overlay != null) - overlay.startAnimation(fade_stay_hidden); - - if (direction == SHIFT_LEFT) { - flip.setInAnimation(slide_left_in); - flip.setOutAnimation(slide_left_out); - flip.showNext(); - } - else if (direction == SHIFT_RIGHT) { - flip.setInAnimation(slide_right_in); - flip.setOutAnimation(slide_right_out); - flip.showPrevious(); - } - } - - updateDefault(); - - if (shouldAnimate) { - // show overlay on new slide and start fade - overlay = findCurrentView(R.id.terminal_overlay); - - if (overlay != null) - overlay.startAnimation(fade_out_delayed); - } - - updatePromptVisible(); - } - } - - /** - * Save the currently shown {@link TerminalView} as the default. This is - * saved back down into {@link TerminalManager} where we can read it again - * later. - */ - private void updateDefault() { - // update the current default terminal - View view = findCurrentView(R.id.console_flip); - - if (!(view instanceof TerminalView)) return; - - TerminalView terminal = (TerminalView)view; - - if (bound != null) bound.defaultBridge = terminal.bridge; - - // tell the bridge monitor it has the topmost visible window now. - if (terminal.bridge.monitor != null) terminal.bridge.monitor.activate(); - } - - protected void updateEmptyVisible() { - // update visibility of empty status message - empty.setVisibility((flip.getChildCount() == 0) ? View.VISIBLE : View.GONE); - } - - /** - * Show any prompts requested by the currently visible {@link TerminalView}. - */ - protected void updatePromptVisible() { - // check if our currently-visible terminalbridge is requesting any prompt services - View view = findCurrentView(R.id.console_flip); - // Hide all the prompts in case a prompt request was canceled - hideAllPrompts(); - - if (!(view instanceof TerminalView)) { - // we dont have an active view, so hide any prompts - return; - } - - PromptHelper prompt = ((TerminalView)view).bridge.promptHelper; - - if (String.class.equals(prompt.promptRequested)) { - stringPromptGroup.setVisibility(View.VISIBLE); - String instructions = prompt.promptInstructions; - boolean password = prompt.passwordRequested; - - if (instructions != null && instructions.length() > 0) { - stringPromptInstructions.setVisibility(View.VISIBLE); - stringPromptInstructions.setText(instructions); - } - else - stringPromptInstructions.setVisibility(View.GONE); - - if (password) { - stringPrompt.setInputType(InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_VARIATION_PASSWORD); - stringPrompt.setTransformationMethod(PasswordTransformationMethod.getInstance()); - } - else { - stringPrompt.setInputType(InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); - stringPrompt.setTransformationMethod(SingleLineTransformationMethod.getInstance()); - } - - stringPrompt.setText(""); - stringPrompt.setHint(prompt.promptHint); - stringPrompt.requestFocus(); - } - else if (Boolean.class.equals(prompt.promptRequested)) { - booleanPromptGroup.setVisibility(View.VISIBLE); - booleanPrompt.setText(prompt.promptHint); - booleanYes.requestFocus(); - } - else { - hideAllPrompts(); - view.requestFocus(); - } - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - Log.d(TAG, String.format("onConfigurationChanged; requestedOrientation=%d, newConfig.orientation=%d", getRequestedOrientation(), newConfig.orientation)); - - if (bound != null) { - if (forcedOrientation && - (newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE && - getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) || - (newConfig.orientation != Configuration.ORIENTATION_PORTRAIT && - getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)) - bound.setResizeAllowed(false); - else - bound.setResizeAllowed(true); - - bound.hardKeyboardHidden = (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES); - mKeyboardButton.setVisibility(bound.hardKeyboardHidden ? View.VISIBLE : View.GONE); - } - } - - /** - * Adds a new TerminalBridge to the current set of views in our ViewFlipper. - * - * @param bridge TerminalBridge to add to our ViewFlipper - * @return the child index of the new view in the ViewFlipper - */ - private int addNewTerminalView(TerminalBridge bridge) { - // let them know about our prompt handler services - bridge.promptHelper.setHandler(promptHandler); - // inflate each terminal view - RelativeLayout view = (RelativeLayout)inflater.inflate(R.layout.item_terminal, flip, false); - // set the terminal overlay text - TextView overlay = (TextView)view.findViewById(R.id.terminal_overlay); - overlay.setText(bridge.host.getNickname()); - // and add our terminal view control, using index to place behind overlay - TerminalView terminal = new TerminalView(ConsoleActivity.this, bridge); - terminal.setId(R.id.console_flip); - view.addView(terminal, 0); - - synchronized (flip) { - // finally attach to the flipper - flip.addView(view); - return flip.getChildCount() - 1; - } - } - - private int getFlipIndex(TerminalBridge bridge) { - synchronized (flip) { - final int children = flip.getChildCount(); - - for (int i = 0; i < children; i++) { - final View view = flip.getChildAt(i).findViewById(R.id.console_flip); - - if (view == null || !(view instanceof TerminalView)) { - // How did that happen? - continue; - } - - final TerminalView tv = (TerminalView) view; - - if (tv.bridge == bridge) { - return i; - } - } - } - - return -1; - } - - /** - * Displays the child in the ViewFlipper at the requestedIndex and updates the prompts. - * - * @param requestedIndex the index of the terminal view to display - */ - private void setDisplayedTerminal(int requestedIndex) { - synchronized (flip) { - try { - // show the requested bridge if found, also fade out overlay - flip.setDisplayedChild(requestedIndex); - flip.getCurrentView().findViewById(R.id.terminal_overlay) - .startAnimation(fade_out_delayed); - } - catch (NullPointerException npe) { - Log.d(TAG, "View went away when we were about to display it", npe); - } - - updatePromptVisible(); - updateEmptyVisible(); - } - } - - private void setFullScreen(int fullScreen) { - if (fullScreen != this.fullScreen) { - if (fullScreen == FULLSCREEN_ON) { - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - else { - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - - this.fullScreen = fullScreen; - - if (bound != null) - bound.setFullScreen(this.fullScreen); - } - } -}
--- a/src/com/five_ten_sg/connectbot/GeneratePubkeyActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,321 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.PrivateKey; -import java.security.PublicKey; - -import com.five_ten_sg.connectbot.bean.PubkeyBean; -import com.five_ten_sg.connectbot.util.EntropyDialog; -import com.five_ten_sg.connectbot.util.EntropyView; -import com.five_ten_sg.connectbot.util.OnEntropyGatheredListener; -import com.five_ten_sg.connectbot.util.PubkeyDatabase; -import com.five_ten_sg.connectbot.util.PubkeyUtils; -import android.app.Activity; -import android.app.Dialog; -import android.app.ProgressDialog; -import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnFocusChangeListener; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.EditText; -import android.widget.RadioGroup; -import android.widget.RadioGroup.OnCheckedChangeListener; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; - -import ch.ethz.ssh2.crypto.SecureRandomFix; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; - -public class GeneratePubkeyActivity extends Activity implements OnEntropyGatheredListener { - public final static String TAG = "ConnectBot.GeneratePubkeyActivity"; - - private static final int RSA_MINIMUM_BITS = 768; - final static int DEFAULT_BITS = 2048; - final static int DSA_BITS = 1024; - final static int[] ECDSA_SIZES = ECDSASHA2Verify.getCurveSizes(); - final static int ECDSA_DEFAULT_BITS = ECDSA_SIZES[0]; - - private LayoutInflater inflater = null; - - private EditText nickname; - private RadioGroup keyTypeGroup; - private SeekBar bitsSlider; - private EditText bitsText; - private CheckBox unlockAtStartup; - private CheckBox confirmUse; - private Button save; - private Dialog entropyDialog; - private ProgressDialog progress; - - private EditText password1, password2; - - private String keyType = PubkeyDatabase.KEY_TYPE_RSA; - private int minBits = RSA_MINIMUM_BITS; - private int bits = DEFAULT_BITS; - - private byte[] entropy; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - setContentView(R.layout.act_generatepubkey); - nickname = (EditText) findViewById(R.id.nickname); - keyTypeGroup = (RadioGroup) findViewById(R.id.key_type); - bitsText = (EditText) findViewById(R.id.bits); - bitsSlider = (SeekBar) findViewById(R.id.bits_slider); - password1 = (EditText) findViewById(R.id.password1); - password2 = (EditText) findViewById(R.id.password2); - unlockAtStartup = (CheckBox) findViewById(R.id.unlock_at_startup); - confirmUse = (CheckBox) findViewById(R.id.confirm_use); - save = (Button) findViewById(R.id.save); - inflater = LayoutInflater.from(this); - nickname.addTextChangedListener(textChecker); - password1.addTextChangedListener(textChecker); - password2.addTextChangedListener(textChecker); - keyTypeGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() { - public void onCheckedChanged(RadioGroup group, int checkedId) { - if (checkedId == R.id.rsa) { - minBits = RSA_MINIMUM_BITS; - bitsSlider.setEnabled(true); - bitsSlider.setProgress(DEFAULT_BITS - minBits); - bitsText.setText(String.valueOf(DEFAULT_BITS)); - bitsText.setEnabled(true); - keyType = PubkeyDatabase.KEY_TYPE_RSA; - } - else if (checkedId == R.id.dsa) { - // DSA keys can only be 1024 bits - bitsSlider.setEnabled(false); - bitsSlider.setProgress(DSA_BITS - minBits); - bitsText.setText(String.valueOf(DSA_BITS)); - bitsText.setEnabled(false); - keyType = PubkeyDatabase.KEY_TYPE_DSA; - } - else if (checkedId == R.id.ec) { - minBits = ECDSA_DEFAULT_BITS; - bitsSlider.setEnabled(true); - bitsSlider.setProgress(ECDSA_DEFAULT_BITS - minBits); - bitsText.setText(String.valueOf(ECDSA_DEFAULT_BITS)); - bitsText.setEnabled(true); - keyType = PubkeyDatabase.KEY_TYPE_EC; - } - } - }); - bitsSlider.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { - public void onProgressChanged(SeekBar seekBar, int progress, - boolean fromTouch) { - if (PubkeyDatabase.KEY_TYPE_EC.equals(keyType)) { - bits = getClosestFieldSize(progress + minBits); - seekBar.setProgress(bits - minBits); - } - else { - // Stay evenly divisible by 8 because it looks nicer to have - // 2048 than 2043 bits. - final int ourProgress = progress - (progress % 8); - bits = minBits + ourProgress; - } - - bitsText.setText(String.valueOf(bits)); - } - public void onStartTrackingTouch(SeekBar seekBar) { - // We don't care about the start. - } - public void onStopTrackingTouch(SeekBar seekBar) { - // We don't care about the stop. - } - }); - bitsText.setOnFocusChangeListener(new OnFocusChangeListener() { - public void onFocusChange(View v, boolean hasFocus) { - if (!hasFocus) { - final boolean isEc = PubkeyDatabase.KEY_TYPE_EC.equals(keyType); - - try { - bits = Integer.parseInt(bitsText.getText().toString()); - - if (bits < minBits) { - bits = minBits; - bitsText.setText(String.valueOf(bits)); - } - - if (isEc) { - bits = getClosestFieldSize(bits); - } - } - catch (NumberFormatException nfe) { - bits = isEc ? ECDSA_DEFAULT_BITS : DEFAULT_BITS; - bitsText.setText(String.valueOf(bits)); - } - - bitsSlider.setProgress(bits - minBits); - } - } - }); - save.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - GeneratePubkeyActivity.this.save.setEnabled(false); - GeneratePubkeyActivity.this.startEntropyGather(); - } - }); - } - - private void checkEntries() { - boolean allowSave = true; - - if (!password1.getText().toString().equals(password2.getText().toString())) - allowSave = false; - - if (nickname.getText().length() == 0) - allowSave = false; - - save.setEnabled(allowSave); - } - - private void startEntropyGather() { - final View entropyView = inflater.inflate(R.layout.dia_gatherentropy, null, false); - ((EntropyView)entropyView.findViewById(R.id.entropy)).addOnEntropyGatheredListener(GeneratePubkeyActivity.this); - entropyDialog = new EntropyDialog(GeneratePubkeyActivity.this, entropyView); - entropyDialog.show(); - } - - public void onEntropyGathered(byte[] entropy) { - // For some reason the entropy dialog was aborted, exit activity - if (entropy == null) { - finish(); - return; - } - - this.entropy = entropy.clone(); - int numSetBits = 0; - - for (int i = 0; i < 20; i++) - numSetBits += measureNumberOfSetBits(this.entropy[i]); - - Log.d(TAG, "Entropy distribution=" + (int)(100.0 * numSetBits / 160.0) + "%"); - Log.d(TAG, "entropy gathered; attemping to generate key..."); - startKeyGen(); - } - - private void startKeyGen() { - progress = new ProgressDialog(GeneratePubkeyActivity.this); - progress.setMessage(GeneratePubkeyActivity.this.getResources().getText(R.string.pubkey_generating)); - progress.setIndeterminate(true); - progress.setCancelable(false); - progress.show(); - Thread keyGenThread = new Thread(mKeyGen); - keyGenThread.setName("KeyGen"); - keyGenThread.start(); - } - - final private Runnable mKeyGen = new Runnable() { - public void run() { - try { - boolean encrypted = false; - int tmpbits = bits; - - if (keyType == PubkeyDatabase.KEY_TYPE_DSA) - tmpbits = DSA_BITS; - - SecureRandomFix random = new SecureRandomFix(); - // Work around JVM bug - random.nextInt(); - random.setSeed(entropy); - KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(keyType); - keyPairGen.initialize(tmpbits, random); - KeyPair pair = keyPairGen.generateKeyPair(); - PrivateKey priv = pair.getPrivate(); - PublicKey pub = pair.getPublic(); - String secret = password1.getText().toString(); - - if (secret.length() > 0) - encrypted = true; - - Log.d(TAG, "private: " + PubkeyUtils.formatKey(priv)); - Log.d(TAG, "public: " + PubkeyUtils.formatKey(pub)); - PubkeyBean pubkey = new PubkeyBean(); - pubkey.setNickname(nickname.getText().toString()); - pubkey.setType(keyType); - pubkey.setPrivateKey(PubkeyUtils.getEncodedPrivate(priv, secret)); - pubkey.setPublicKey(pub.getEncoded()); - pubkey.setEncrypted(encrypted); - pubkey.setStartup(unlockAtStartup.isChecked()); - pubkey.setConfirmUse(confirmUse.isChecked()); - PubkeyDatabase pubkeydb = new PubkeyDatabase(GeneratePubkeyActivity.this); - pubkeydb.savePubkey(pubkey); - pubkeydb.close(); - } - catch (Exception e) { - Log.e(TAG, "Could not generate key pair"); - e.printStackTrace(); - } - - GeneratePubkeyActivity.this.runOnUiThread(new Runnable() { - public void run() { - progress.dismiss(); - GeneratePubkeyActivity.this.finish(); - } - }); - } - }; - - final private TextWatcher textChecker = new TextWatcher() { - public void afterTextChanged(Editable s) {} - public void beforeTextChanged(CharSequence s, int start, int count, - int after) {} - public void onTextChanged(CharSequence s, int start, int before, - int count) { - checkEntries(); - } - }; - - private int measureNumberOfSetBits(byte b) { - int numSetBits = 0; - - for (int i = 0; i < 8; i++) { - if ((b & 1) == 1) - numSetBits++; - - b >>= 1; - } - - return numSetBits; - } - - private int getClosestFieldSize(int bits) { - int outBits = ECDSA_DEFAULT_BITS; - int distance = Math.abs(bits - ECDSA_DEFAULT_BITS); - - for (int i = 1; i < ECDSA_SIZES.length; i++) { - int thisDistance = Math.abs(bits - ECDSA_SIZES[i]); - - if (thisDistance < distance) { - distance = thisDistance; - outBits = ECDSA_SIZES[i]; - } - } - - return outBits; - } -}
--- a/src/com/five_ten_sg/connectbot/HelpActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import java.io.IOException; - -import android.app.Activity; -import android.content.Intent; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.TextView; - -/** - * @author Kenny Root - * - */ -public class HelpActivity extends Activity { - public final static String TAG = "ConnectBot.HelpActivity"; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - setContentView(R.layout.act_help); - this.setTitle(String.format("%s: %s", - getResources().getText(R.string.app_name), - getResources().getText(R.string.title_help))); - LinearLayout content = (LinearLayout)this.findViewById(R.id.topics); - - String[] topics = getResources().getStringArray(R.array.list_wizard_topics); - for (final String topic : topics) { - Button button = new Button(this); - button.setText(topic); - button.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - Intent intent = new Intent(HelpActivity.this, HelpTopicActivity.class); - intent.putExtra(Intent.EXTRA_TITLE, topic); - HelpActivity.this.startActivity(intent); - } - }); - content.addView(button); - } - } -}
--- a/src/com/five_ten_sg/connectbot/HelpTopicActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import com.five_ten_sg.connectbot.util.HelpTopicView; -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; - -/** - * @author Kenny Root - * - */ -public class HelpTopicActivity extends Activity { - public final static String TAG = "ConnectBot.HelpActivity"; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - setContentView(R.layout.act_help_topic); - String topic = getIntent().getStringExtra(Intent.EXTRA_TITLE); - this.setTitle(String.format("%s: %s - %s", - getResources().getText(R.string.app_name), - getResources().getText(R.string.title_help), - topic)); - HelpTopicView helpTopic = (HelpTopicView) findViewById(R.id.topic_text); - helpTopic.setTopic(topic); - } -}
--- a/src/com/five_ten_sg/connectbot/HostEditorActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,445 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.util.HostDatabase; -import com.five_ten_sg.connectbot.util.PubkeyDatabase; -import android.content.ComponentName; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.os.Bundle; -import android.os.IBinder; -import android.preference.CheckBoxPreference; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceActivity; -import android.util.Log; - -public class HostEditorActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener { - public class CursorPreferenceHack implements SharedPreferences { - protected final String table; - protected final long id; - - protected Map<String, String> values = new HashMap<String, String>(); - - public CursorPreferenceHack(String table, long id) { - this.table = table; - this.id = id; - cacheValues(); - } - - protected final void cacheValues() { - // fill a cursor and cache the values locally - // this makes sure we dont have any floating cursor to dispose later - SQLiteDatabase db = hostdb.getReadableDatabase(); - Cursor cursor = db.query(table, null, "_id = ?", - new String[] { String.valueOf(id) }, null, null, null); - - if (cursor.moveToFirst()) { - for (int i = 0; i < cursor.getColumnCount(); i++) { - String key = cursor.getColumnName(i); - - if (key.equals(HostDatabase.FIELD_HOST_HOSTKEY)) continue; - - String value = cursor.getString(i); - values.put(key, value); - } - } - - cursor.close(); - db.close(); - } - - public boolean contains(String key) { - return values.containsKey(key); - } - - public class Editor implements SharedPreferences.Editor { - - private ContentValues update = new ContentValues(); - - public SharedPreferences.Editor clear() { - Log.d(this.getClass().toString(), "clear()"); - update = new ContentValues(); - return this; - } - - public boolean commit() { - //Log.d(this.getClass().toString(), "commit() changes back to database"); - SQLiteDatabase db = hostdb.getWritableDatabase(); - db.update(table, update, "_id = ?", new String[] { String.valueOf(id) }); - db.close(); - // make sure we refresh the parent cached values - cacheValues(); - - // and update any listeners - for (OnSharedPreferenceChangeListener listener : listeners) { - listener.onSharedPreferenceChanged(CursorPreferenceHack.this, null); - } - - return true; - } - - // Gingerbread compatibility - public void apply() { - commit(); - } - - public android.content.SharedPreferences.Editor putBoolean(String key, boolean value) { - return this.putString(key, Boolean.toString(value)); - } - - public android.content.SharedPreferences.Editor putFloat(String key, float value) { - return this.putString(key, Float.toString(value)); - } - - public android.content.SharedPreferences.Editor putInt(String key, int value) { - return this.putString(key, Integer.toString(value)); - } - - public android.content.SharedPreferences.Editor putLong(String key, long value) { - return this.putString(key, Long.toString(value)); - } - - public android.content.SharedPreferences.Editor putString(String key, String value) { - //Log.d(this.getClass().toString(), String.format("Editor.putString(key=%s, value=%s)", key, value)); - update.put(key, value); - return this; - } - - public android.content.SharedPreferences.Editor remove(String key) { - //Log.d(this.getClass().toString(), String.format("Editor.remove(key=%s)", key)); - update.remove(key); - return this; - } - - public android.content.SharedPreferences.Editor putStringSet(String key, Set<String> value) { - throw new UnsupportedOperationException("HostEditor Prefs do not support Set<String>"); - } - } - - - public Editor edit() { - //Log.d(this.getClass().toString(), "edit()"); - return new Editor(); - } - - public Map<String, ?> getAll() { - return values; - } - - public boolean getBoolean(String key, boolean defValue) { - return Boolean.valueOf(this.getString(key, Boolean.toString(defValue))); - } - - public float getFloat(String key, float defValue) { - return Float.valueOf(this.getString(key, Float.toString(defValue))); - } - - public int getInt(String key, int defValue) { - return Integer.valueOf(this.getString(key, Integer.toString(defValue))); - } - - public long getLong(String key, long defValue) { - return Long.valueOf(this.getString(key, Long.toString(defValue))); - } - - public String getString(String key, String defValue) { - //Log.d(this.getClass().toString(), String.format("getString(key=%s, defValue=%s)", key, defValue)); - if (!values.containsKey(key)) return defValue; - - return values.get(key); - } - - public Set<String> getStringSet(String key, Set<String> defValue) { - throw new ClassCastException("HostEditor Prefs do not support Set<String>"); - } - - protected List<OnSharedPreferenceChangeListener> listeners = new LinkedList<OnSharedPreferenceChangeListener>(); - - public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { - listeners.add(listener); - } - - public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { - listeners.remove(listener); - } - - } - - @Override - public SharedPreferences getSharedPreferences(String name, int mode) { - //Log.d(this.getClass().toString(), String.format("getSharedPreferences(name=%s)", name)); - return this.pref; - } - - protected static final String TAG = "ConnectBot.HostEditorActivity"; - - protected HostDatabase hostdb = null; - private PubkeyDatabase pubkeydb = null; - - private CursorPreferenceHack pref; - private ServiceConnection connection; - private Map<String, CharSequence> summaries = new HashMap<String, CharSequence>(); - - private HostBean host; - private boolean enableSSHFeatures; - private boolean enable5250Features; - private boolean enableAsyncFeatures; - - protected TerminalBridge hostBridge; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - long hostId = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1); - // TODO: we could pass through a specific ContentProvider uri here - //this.getPreferenceManager().setSharedPreferencesName(uri); - this.hostdb = new HostDatabase(this); - this.pubkeydb = new PubkeyDatabase(this); - host = hostdb.findHostById(hostId); - enableSSHFeatures = host.isSSH(); - enable5250Features = host.is5250(); - enableAsyncFeatures = host.isAsync(); - connection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService(); - hostBridge = bound.getConnectedBridge(host); - } - public void onServiceDisconnected(ComponentName name) { - hostBridge = null; - } - }; - this.pref = new CursorPreferenceHack(HostDatabase.TABLE_HOSTS, hostId); - this.pref.registerOnSharedPreferenceChangeListener(this); - this.addPreferencesFromResource(R.xml.host_prefs); - // get all the text summaries - getSummaries(); - // disable all preferences that are not applicable to this host - findPreference(HostDatabase.FIELD_HOST_PUBKEYID).setEnabled(enableSSHFeatures); - findPreference(HostDatabase.FIELD_HOST_USEAUTHAGENT).setEnabled(enableSSHFeatures); - findPreference(HostDatabase.FIELD_HOST_POSTLOGIN).setEnabled(!enable5250Features); - findPreference(HostDatabase.FIELD_HOST_COMPRESSION).setEnabled(enableSSHFeatures); - findPreference(HostDatabase.FIELD_HOST_HTTPPROXY).setEnabled(enableAsyncFeatures); - findPreference(HostDatabase.FIELD_HOST_WANTSESSION).setEnabled(enableSSHFeatures); - findPreference(HostDatabase.FIELD_HOST_USERNAME).setEnabled(enableSSHFeatures || enable5250Features); - findPreference(HostDatabase.FIELD_HOST_EMULATION).setEnabled(!enable5250Features); - findPreference(HostDatabase.CATEGORY_5250).setEnabled(enable5250Features); - findPreference(HostDatabase.CATEGORY_X11).setEnabled(enableSSHFeatures); - // add all existing pubkeys to our listpreference for user to choose from - // TODO: may be an issue here when this activity is recycled after adding a new pubkey - // TODO: should consider moving into onStart, but we dont have a good way of resetting the listpref after filling once - ListPreference pubkeyPref = (ListPreference)findPreference(HostDatabase.FIELD_HOST_PUBKEYID); - List<CharSequence> pubkeyNicks = new LinkedList<CharSequence> (Arrays.asList(pubkeyPref.getEntries())); - pubkeyNicks.addAll(pubkeydb.allValues(PubkeyDatabase.FIELD_PUBKEY_NICKNAME)); - pubkeyPref.setEntries(pubkeyNicks.toArray(new CharSequence[pubkeyNicks.size()])); - List<CharSequence> pubkeyIds = new LinkedList<CharSequence> (Arrays.asList(pubkeyPref.getEntryValues())); - pubkeyIds.addAll(pubkeydb.allValues("_id")); - pubkeyPref.setEntryValues(pubkeyIds.toArray(new CharSequence[pubkeyIds.size()])); - // Populate the character set encoding list with all available - final ListPreference charsetPref = (ListPreference)findPreference(HostDatabase.FIELD_HOST_ENCODING); - - if (CharsetHolder.isInitialized()) { - initCharsetPref(charsetPref); - } - else { - String[] currentCharsetPref = new String[1]; - currentCharsetPref[0] = charsetPref.getValue(); - charsetPref.setEntryValues(currentCharsetPref); - charsetPref.setEntries(currentCharsetPref); - new Thread(new Runnable() { - public void run() { - initCharsetPref(charsetPref); - } - }).start(); - } - - this.updateSummaries(); - } - - @Override - public void onStart() { - super.onStart(); - bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - - if (this.hostdb == null) - this.hostdb = new HostDatabase(this); - - if (this.pubkeydb == null) - this.pubkeydb = new PubkeyDatabase(this); - } - - @Override - public void onStop() { - super.onStop(); - unbindService(connection); - - if (this.hostdb != null) { - this.hostdb.close(); - this.hostdb = null; - } - - if (this.pubkeydb != null) { - this.pubkeydb.close(); - this.pubkeydb = null; - } - } - - private void getSummaries() { - // get all the original text summaries - for (String key : this.pref.values.keySet()) { - Preference pref = this.findPreference(key); - - if (pref == null) continue; - - if (pref instanceof CheckBoxPreference) continue; - - CharSequence value = pref.getSummary(); - summaries.put(key, value); - } - } - - private void updateSummaries() { - // for all text preferences, set hint as current database value if it is non-empty - for (String key : this.pref.values.keySet()) { - Preference pref = this.findPreference(key); - - if (pref == null) continue; - - if (pref instanceof CheckBoxPreference) continue; - - CharSequence value = this.pref.getString(key, ""); - - if (key.equals(HostDatabase.FIELD_HOST_PUBKEYID)) { - try { - int pubkeyId = Integer.parseInt(value.toString()); - - if (pubkeyId >= 0) - pref.setSummary(pubkeydb.getNickname(pubkeyId)); - else if (pubkeyId == HostDatabase.PUBKEYID_ANY) - pref.setSummary(R.string.list_pubkeyids_any); - else if (pubkeyId == HostDatabase.PUBKEYID_NEVER) - pref.setSummary(R.string.list_pubkeyids_none); - - continue; - } - catch (NumberFormatException nfe) { - // Fall through. - } - } - else if ((pref instanceof ListPreference) && (value != null)) { - ListPreference listPref = (ListPreference) pref; - int entryIndex = listPref.findIndexOfValue(value.toString()); - - if (entryIndex >= 0) value = listPref.getEntries()[entryIndex]; - } - - if ((value == null) || (value.length() == 0)) value = summaries.get(key); - - pref.setSummary(value); - } - } - - private void initCharsetPref(final ListPreference charsetPref) { - charsetPref.setEntryValues(CharsetHolder.getCharsetIds()); - charsetPref.setEntries(CharsetHolder.getCharsetNames()); - } - - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - // update values on changed preference - this.updateSummaries(); - - // Our CursorPreferenceHack always send null keys, so try to set charset anyway - if (hostBridge != null) - hostBridge.setCharset(sharedPreferences - .getString(HostDatabase.FIELD_HOST_ENCODING, HostDatabase.ENCODING_DEFAULT)); - } - - public static class CharsetHolder { - private static boolean initialized = false; - - private static CharSequence[] charsetIds; - private static CharSequence[] charsetNames; - - public static CharSequence[] getCharsetNames() { - if (charsetNames == null) - initialize(); - - return charsetNames; - } - - public static CharSequence[] getCharsetIds() { - if (charsetIds == null) - initialize(); - - return charsetIds; - } - - private synchronized static void initialize() { - if (initialized) - return; - - List<CharSequence> charsetIdsList = new LinkedList<CharSequence>(); - List<CharSequence> charsetNamesList = new LinkedList<CharSequence>(); - - for (Entry<String, Charset> entry : Charset.availableCharsets().entrySet()) { - Charset c = entry.getValue(); - - if (c.canEncode() && c.isRegistered()) { - String key = entry.getKey(); - - if (key.startsWith("cp")) { - // Custom CP437 charset changes - charsetIdsList.add("CP437"); - charsetNamesList.add("CP437"); - } - - charsetIdsList.add(entry.getKey()); - charsetNamesList.add(c.displayName()); - } - } - - charsetIds = charsetIdsList.toArray(new CharSequence[charsetIdsList.size()]); - charsetNames = charsetNamesList.toArray(new CharSequence[charsetNamesList.size()]); - initialized = true; - } - - public static boolean isInitialized() { - return initialized; - } - } -}
--- a/src/com/five_ten_sg/connectbot/HostListActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,665 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - - -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.transport.TransportFactory; -import com.five_ten_sg.connectbot.util.HostDatabase; -import com.five_ten_sg.connectbot.util.PreferenceConstants; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.File; -import java.util.HashMap; -import java.util.List; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.ListActivity; -import android.content.ComponentName; -import android.content.ContentValues; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.Intent.ShortcutIconResource; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.content.res.ColorStateList; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Environment; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.ContextMenu; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MenuItem.OnMenuItemClickListener; -import android.view.View; -import android.view.View.OnKeyListener; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.Spinner; -import android.widget.TextView; - -public class HostListActivity extends ListActivity { - protected static final String TAG = "ConnectBot.HostListActivity"; - public final static int REQUEST_EDIT = 1; - public final static int REQUEST_EULA = 2; - - protected TerminalManager bound = null; - - protected HostDatabase hostdb; - private List<HostBean> hosts; - protected LayoutInflater inflater = null; - - protected boolean sortedByColor = false; - - private MenuItem sortcolor; - - private MenuItem sortlast; - - private Spinner transportSpinner; - private TextView quickconnect; - - private SharedPreferences prefs = null; - - protected boolean makingShortcut = false; - - protected Handler updateHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - HostListActivity.this.updateList(); - } - }; - - private ServiceConnection connection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - bound = ((TerminalManager.TerminalBinder) service).getService(); - // update our listview binder to find the service - updateList(); - } - public void onServiceDisconnected(ComponentName className) { - bound = null; - updateList(); - } - }; - - @Override - public void onStart() { - super.onStart(); - // start the terminal manager service - this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - - if (this.hostdb == null) - this.hostdb = new HostDatabase(this); - } - - @Override - public void onStop() { - super.onStop(); - this.unbindService(connection); - - if (this.hostdb != null) { - this.hostdb.close(); - this.hostdb = null; - } - } - - @Override - public void onResume() { - super.onResume(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_EULA) { - if (resultCode == Activity.RESULT_OK) { - // yay they agreed, so store that info - Editor editor = prefs.edit(); - editor.putBoolean(PreferenceConstants.EULA, true); - editor.commit(); - } - else { - // user didnt agree, so close - this.finish(); - } - } - else if (requestCode == REQUEST_EDIT) { - updateList(); - } - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - setContentView(R.layout.act_hostlist); - this.setTitle(String.format("%s: %s", - getResources().getText(R.string.app_name), - getResources().getText(R.string.title_hosts_list))); - this.prefs = PreferenceManager.getDefaultSharedPreferences(this); - - // detect HTC Dream and apply special preferences - if (Build.MANUFACTURER.equals("HTC") && Build.DEVICE.equals("dream")) { - if (!prefs.contains(PreferenceConstants.SHIFT_FKEYS) && - !prefs.contains(PreferenceConstants.CTRL_FKEYS)) { - Editor editor = prefs.edit(); - editor.putBoolean(PreferenceConstants.SHIFT_FKEYS, true); - editor.putBoolean(PreferenceConstants.CTRL_FKEYS, true); - editor.commit(); - } - } - - makingShortcut = Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction()) - || Intent.ACTION_PICK.equals(getIntent().getAction()); - - // connect with hosts database, read deployment file, and populate list - hostdb = new HostDatabase(this); - createDeploymentHosts(); // build hosts from a deployment text file - updateList(); - - // check for eula agreement, which might be set from the deployment file - boolean agreed = prefs.getBoolean(PreferenceConstants.EULA, false); - if (!agreed) { - startActivityForResult(new Intent(this, WizardActivity.class), REQUEST_EULA); - } - - // show the list - sortedByColor = prefs.getBoolean(PreferenceConstants.SORT_BY_COLOR, false); - registerForContextMenu(getListView()); - getListView().setOnItemClickListener(new OnItemClickListener() { - - public synchronized void onItemClick(AdapterView<?> parent, View view, int position, long id) { - // launch off to console details - HostBean host = (HostBean) getListView().getItemAtPosition(position); - Uri uri = host.getUri(); - Intent contents = new Intent(Intent.ACTION_VIEW, uri); - contents.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - - if (makingShortcut) { - // create shortcut if requested - ShortcutIconResource icon = Intent.ShortcutIconResource.fromContext(HostListActivity.this, R.drawable.icon); - Intent intent = new Intent(); - intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, contents); - intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, host.getNickname()); - intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon); - setResult(RESULT_OK, intent); - finish(); - } - else { - // otherwise just launch activity to show this host - startActivity(contents); - } - } - }); - quickconnect = (TextView) this.findViewById(R.id.front_quickconnect); - quickconnect.setVisibility(makingShortcut ? View.GONE : View.VISIBLE); - quickconnect.setOnKeyListener(new OnKeyListener() { - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_UP) return false; - - if (keyCode != KeyEvent.KEYCODE_ENTER) return false; - - return startConsoleActivity(); - } - }); - transportSpinner = (Spinner)findViewById(R.id.transport_selection); - transportSpinner.setVisibility(makingShortcut ? View.GONE : View.VISIBLE); - ArrayAdapter<String> transportSelection = new ArrayAdapter<String> (this, - android.R.layout.simple_spinner_item, TransportFactory.getTransportNames()); - transportSelection.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - transportSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - public void onItemSelected(AdapterView<?> arg0, View view, int position, long id) { - String formatHint = TransportFactory.getFormatHint( - (String) transportSpinner.getSelectedItem(), - HostListActivity.this); - quickconnect.setHint(formatHint); - quickconnect.setError(null); - quickconnect.requestFocus(); - } - public void onNothingSelected(AdapterView<?> arg0) { } - }); - transportSpinner.setAdapter(transportSelection); - this.inflater = LayoutInflater.from(this); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - - // don't offer menus when creating shortcut - if (makingShortcut) return true; - - sortcolor.setVisible(!sortedByColor); - sortlast.setVisible(sortedByColor); - return true; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - - // don't offer menus when creating shortcut - if (makingShortcut) return true; - - // add host, ssh keys, about - sortcolor = menu.add(R.string.list_menu_sortcolor); - sortcolor.setIcon(android.R.drawable.ic_menu_share); - sortcolor.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - sortedByColor = true; - updateList(); - return true; - } - }); - sortlast = menu.add(R.string.list_menu_sortname); - sortlast.setIcon(android.R.drawable.ic_menu_share); - sortlast.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - sortedByColor = false; - updateList(); - return true; - } - }); - MenuItem keys = menu.add(R.string.list_menu_pubkeys); - keys.setIcon(android.R.drawable.ic_lock_lock); - keys.setIntent(new Intent(HostListActivity.this, PubkeyListActivity.class)); - MenuItem colors = menu.add(R.string.title_colors); - colors.setIcon(android.R.drawable.ic_menu_slideshow); - colors.setIntent(new Intent(HostListActivity.this, ColorsActivity.class)); - MenuItem settings = menu.add(R.string.list_menu_settings); - settings.setIcon(android.R.drawable.ic_menu_preferences); - settings.setIntent(new Intent(HostListActivity.this, SettingsActivity.class)); - MenuItem help = menu.add(R.string.title_help); - help.setIcon(android.R.drawable.ic_menu_help); - help.setIntent(new Intent(HostListActivity.this, HelpActivity.class)); - return true; - } - - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - // create menu to handle hosts - // create menu to handle deleting and sharing lists - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - final HostBean host = (HostBean) this.getListView().getItemAtPosition(info.position); - menu.setHeaderTitle(host.getNickname()); - // edit, disconnect, delete - MenuItem connect = menu.add(R.string.list_host_disconnect); - final TerminalBridge bridge = bound.getConnectedBridge(host); - connect.setEnabled((bridge != null)); - connect.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - bridge.dispatchDisconnect(true); - updateHandler.sendEmptyMessage(-1); - return true; - } - }); - MenuItem edit = menu.add(R.string.list_host_edit); - edit.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - Intent intent = new Intent(HostListActivity.this, HostEditorActivity.class); - intent.putExtra(Intent.EXTRA_TITLE, host.getId()); - HostListActivity.this.startActivityForResult(intent, REQUEST_EDIT); - return true; - } - }); - MenuItem portForwards = menu.add(R.string.list_host_portforwards); - portForwards.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - Intent intent = new Intent(HostListActivity.this, PortForwardListActivity.class); - intent.putExtra(Intent.EXTRA_TITLE, host.getId()); - HostListActivity.this.startActivityForResult(intent, REQUEST_EDIT); - return true; - } - }); - - if (!TransportFactory.canForwardPorts(host.getProtocol())) - portForwards.setEnabled(false); - - MenuItem delete = menu.add(R.string.list_host_delete); - delete.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - // prompt user to make sure they really want this - new AlertDialog.Builder(HostListActivity.this) - .setMessage(getString(R.string.delete_message, host.getNickname())) - .setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - // make sure we disconnect - if (bridge != null) - bridge.dispatchDisconnect(true); - - hostdb.deleteHost(host); - updateHandler.sendEmptyMessage(-1); - } - }) - .setNegativeButton(R.string.delete_neg, null).create().show(); - return true; - } - }); - } - - /** - * @param text - * @return - */ - private boolean startConsoleActivity() { - Uri uri = TransportFactory.getUri((String) transportSpinner - .getSelectedItem(), quickconnect.getText().toString()); - - if (uri == null) { - quickconnect.setError(getString(R.string.list_format_error, - TransportFactory.getFormatHint( - (String) transportSpinner.getSelectedItem(), - HostListActivity.this))); - return false; - } - - HostBean host = TransportFactory.findHost(hostdb, uri); - - if (host == null) { - host = TransportFactory.getTransport(uri.getScheme()).createHost(uri); - host.setColor(HostDatabase.COLOR_GRAY); - host.setPubkeyId(HostDatabase.PUBKEYID_ANY); - hostdb.saveHost(host); - } - - Intent intent = new Intent(HostListActivity.this, ConsoleActivity.class); - intent.setData(uri); - startActivity(intent); - return true; - } - - private void createDeploymentHosts() { - try { - String fn = Environment.getExternalStorageDirectory().getAbsolutePath() + - File.separator + "deployment.connections"; - BufferedReader reader = new BufferedReader(new FileReader(fn)); - String line = null; - - while ((line = reader.readLine()) != null) { - if (line.length() == 0) continue; // empty - - if (line.substring(0, 1).equals("#")) continue; // comment - - if (!line.contains("://")) continue; // invalid uri - - Uri uri = Uri.parse(line); - ContentValues values = null; - - while ((line = reader.readLine()).length() > 0) { - String [] parts = line.split("="); - - if (parts.length != 2) continue; - - if (values == null) values = new ContentValues(); - - values.put(parts[0].trim(), parts[1].trim()); - } - - if (uri.getScheme().equals("global")) { - Editor editor = prefs.edit(); - HashMap<String, String> types = new HashMap<String, String>(); - types.put("memkeys", "boolean"); - types.put("connPersist", "boolean"); - types.put("emulation", "string"); - types.put("scrollback", "string"); - types.put("rotation", "string"); - types.put("shiftfkeys", "boolean"); - types.put("ctrlfkeys", "boolean"); - types.put("keymode", "string"); - types.put("camera", "string"); - types.put("volup", "string"); - types.put("voldn", "string"); - types.put("search", "string"); - types.put("ptt", "string"); - types.put("keepalive", "boolean"); - types.put("wifilock", "boolean"); - types.put("bumpyarrows", "boolean"); - types.put("eula", "boolean"); - types.put("extended_longpress", "boolean"); - types.put("ctrl_string", "string"); - types.put("picker_string", "string"); - types.put("picker_keep_open", "boolean"); - types.put("list_custom_keymap", "string"); - types.put("bell", "boolean"); - types.put("bellVolume", "float"); - types.put("bellVibrate", "boolean"); - types.put("bellNotification", "boolean"); - types.put("screen_capture_folder", "string"); - types.put("screen_capture_popup", "boolean"); - types.put("file_dialog", "string"); - types.put("download_folder", "string"); - types.put("remote_upload_folder", "string"); - types.put("upload_dest_prompt", "boolean"); - types.put("background_file_transfer", "boolean"); - types.put("debug_keycodes", "boolean"); - - for (String key : values.keySet()) { - if (types.containsKey(key)) { - String t = types.get(key); - String sv = values.getAsString(key); - if (t.equals("float")) { - editor.putFloat(key, Float.parseFloat(sv)); - } - else if (t.equals("boolean")) { - editor.putBoolean(key, Boolean.parseBoolean(sv)); - } - else if (t.equals("string")) { - editor.putString(key, sv); - } - } - } - - editor.commit(); - } - else { - HostBean host = TransportFactory.findHost(hostdb, uri); - - if (host == null) { - host = TransportFactory.getTransport(uri.getScheme()).createHost(uri); - host.setColor(HostDatabase.COLOR_GRAY); - host.setPubkeyId(HostDatabase.PUBKEYID_ANY); - hostdb.saveHost(host); - } - - host = TransportFactory.findHost(hostdb, uri); - - if (host == null) continue; - - if (values == null) continue; - - SQLiteDatabase db = hostdb.getWritableDatabase(); - db.update(HostDatabase.TABLE_HOSTS, values, "_id = ?", new String[] { String.valueOf(host.getId()) }); - db.close(); - } - } - - reader.close(); - (new File(fn)).delete(); - } - catch (Exception e) { - Log.d(TAG, "Deployment scan failed.", e); - } - } - - protected void updateList() { - if (prefs.getBoolean(PreferenceConstants.SORT_BY_COLOR, false) != sortedByColor) { - Editor editor = prefs.edit(); - editor.putBoolean(PreferenceConstants.SORT_BY_COLOR, sortedByColor); - editor.commit(); - } - - if (hostdb == null) - hostdb = new HostDatabase(this); - - hosts = hostdb.getHosts(sortedByColor); - - // Don't lose hosts that are connected via shortcuts but not in the database. - if (bound != null) { - for (TerminalBridge bridge : bound.bridges) { - if (!hosts.contains(bridge.host)) - hosts.add(0, bridge.host); - } - } - - HostAdapter adapter = new HostAdapter(this, hosts, bound); - this.setListAdapter(adapter); - } - - class HostAdapter extends ArrayAdapter<HostBean> { - private List<HostBean> hosts; - private final TerminalManager manager; - private final ColorStateList red, green, blue; - - public final static int STATE_UNKNOWN = 1, STATE_CONNECTED = 2, STATE_DISCONNECTED = 3; - - class ViewHolder { - public TextView nickname; - public TextView caption; - public ImageView icon; - } - - public HostAdapter(Context context, List<HostBean> hosts, TerminalManager manager) { - super(context, R.layout.item_host, hosts); - this.hosts = hosts; - this.manager = manager; - red = context.getResources().getColorStateList(R.color.red); - green = context.getResources().getColorStateList(R.color.green); - blue = context.getResources().getColorStateList(R.color.blue); - } - - /** - * Check if we're connected to a terminal with the given host. - */ - private int getConnectedState(HostBean host) { - // always disconnected if we dont have backend service - if (this.manager == null) - return STATE_UNKNOWN; - - if (manager.getConnectedBridge(host) != null) - return STATE_CONNECTED; - - if (manager.disconnected.contains(host)) - return STATE_DISCONNECTED; - - return STATE_UNKNOWN; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder holder; - - if (convertView == null) { - convertView = inflater.inflate(R.layout.item_host, null, false); - holder = new ViewHolder(); - holder.nickname = (TextView)convertView.findViewById(android.R.id.text1); - holder.caption = (TextView)convertView.findViewById(android.R.id.text2); - holder.icon = (ImageView)convertView.findViewById(android.R.id.icon); - convertView.setTag(holder); - } - else - holder = (ViewHolder) convertView.getTag(); - - HostBean host = hosts.get(position); - - if (host == null) { - // Well, something bad happened. We can't continue. - Log.e("HostAdapter", "Host bean is null!"); - holder.nickname.setText("Error during lookup"); - holder.caption.setText("see 'adb logcat' for more"); - return convertView; - } - - holder.nickname.setText(host.getNickname()); - - switch (this.getConnectedState(host)) { - case STATE_UNKNOWN: - holder.icon.setImageState(new int[] { }, true); - break; - - case STATE_CONNECTED: - holder.icon.setImageState(new int[] { android.R.attr.state_checked }, true); - break; - - case STATE_DISCONNECTED: - holder.icon.setImageState(new int[] { android.R.attr.state_expanded }, true); - break; - } - - ColorStateList chosen = null; - - if (HostDatabase.COLOR_RED.equals(host.getColor())) - chosen = this.red; - else if (HostDatabase.COLOR_GREEN.equals(host.getColor())) - chosen = this.green; - else if (HostDatabase.COLOR_BLUE.equals(host.getColor())) - chosen = this.blue; - - Context context = convertView.getContext(); - - if (chosen != null) { - // set color normally if not selected - holder.nickname.setTextColor(chosen); - holder.caption.setTextColor(chosen); - } - else { - // selected, so revert back to default black text - holder.nickname.setTextAppearance(context, android.R.attr.textAppearanceLarge); - holder.caption.setTextAppearance(context, android.R.attr.textAppearanceSmall); - } - - long now = System.currentTimeMillis() / 1000; - String nice = context.getString(R.string.bind_never); - - if (host.getLastConnect() > 0) { - int minutes = (int)((now - host.getLastConnect()) / 60); - - if (minutes >= 60) { - int hours = (minutes / 60); - - if (hours >= 24) { - int days = (hours / 24); - nice = context.getString(R.string.bind_days, days); - } - else - nice = context.getString(R.string.bind_hours, hours); - } - else - nice = context.getString(R.string.bind_minutes, minutes); - } - - holder.caption.setText(nice); - return convertView; - } - } -}
--- a/src/com/five_ten_sg/connectbot/PortForwardListActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,406 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import java.util.List; - -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.bean.PortForwardBean; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.util.HostDatabase; -import android.app.AlertDialog; -import android.app.ListActivity; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.res.Resources; -import android.database.SQLException; -import android.graphics.Paint; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.util.Log; -import android.view.ContextMenu; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MenuItem.OnMenuItemClickListener; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.ListView; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -/** - * List all portForwards for a particular host and provide a way for users to add more portForwards, - * edit existing portForwards, and delete portForwards. - * - * @author Kenny Root - */ -public class PortForwardListActivity extends ListActivity { - public final static String TAG = "ConnectBot.PortForwardListActivity"; - - private static final int LISTENER_CYCLE_TIME = 500; - - protected HostDatabase hostdb; - - private List<PortForwardBean> portForwards; - - private ServiceConnection connection = null; - protected TerminalBridge hostBridge = null; - protected LayoutInflater inflater = null; - - private HostBean host; - - @Override - public void onStart() { - super.onStart(); - this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - - if (this.hostdb == null) - this.hostdb = new HostDatabase(this); - } - - @Override - public void onStop() { - super.onStop(); - this.unbindService(connection); - - if (this.hostdb != null) { - this.hostdb.close(); - this.hostdb = null; - } - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - long hostId = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1); - setContentView(R.layout.act_portforwardlist); - // connect with hosts database and populate list - this.hostdb = new HostDatabase(this); - host = hostdb.findHostById(hostId); - { - final String nickname = host != null ? host.getNickname() : null; - final Resources resources = getResources(); - - if (nickname != null) { - this.setTitle(String.format("%s: %s (%s)", - resources.getText(R.string.app_name), - resources.getText(R.string.title_port_forwards_list), - nickname)); - } - else { - this.setTitle(String.format("%s: %s", - resources.getText(R.string.app_name), - resources.getText(R.string.title_port_forwards_list))); - } - } - connection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService(); - hostBridge = bound.getConnectedBridge(host); - updateHandler.sendEmptyMessage(-1); - } - public void onServiceDisconnected(ComponentName name) { - hostBridge = null; - } - }; - this.updateList(); - this.registerForContextMenu(this.getListView()); - this.getListView().setOnItemClickListener(new OnItemClickListener() { - public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { - ListView lv = PortForwardListActivity.this.getListView(); - PortForwardBean pfb = (PortForwardBean) lv.getItemAtPosition(position); - - if (hostBridge != null) { - if (pfb.isEnabled()) - hostBridge.disablePortForward(pfb); - else { - if (!hostBridge.enablePortForward(pfb)) - Toast.makeText(PortForwardListActivity.this, getString(R.string.portforward_problem), Toast.LENGTH_LONG).show(); - } - - updateHandler.sendEmptyMessage(-1); - } - } - }); - this.inflater = LayoutInflater.from(this); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - MenuItem add = menu.add(R.string.portforward_menu_add); - add.setIcon(android.R.drawable.ic_menu_add); - add.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - // build dialog to prompt user about updating - final View portForwardView = inflater.inflate(R.layout.dia_portforward, null, false); - final EditText destEdit = (EditText) portForwardView.findViewById(R.id.portforward_destination); - final Spinner typeSpinner = (Spinner)portForwardView.findViewById(R.id.portforward_type); - typeSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { - public void onItemSelected(AdapterView<?> value, View view, - int position, long id) { - destEdit.setEnabled(position != 2); - } - public void onNothingSelected(AdapterView<?> arg0) { - } - }); - new AlertDialog.Builder(PortForwardListActivity.this) - .setView(portForwardView) - .setPositiveButton(R.string.portforward_pos, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - try { - final EditText nicknameEdit = (EditText) portForwardView.findViewById(R.id.nickname); - final EditText sourcePortEdit = (EditText) portForwardView.findViewById(R.id.portforward_source); - String type = HostDatabase.PORTFORWARD_LOCAL; - - switch (typeSpinner.getSelectedItemPosition()) { - case 0: - type = HostDatabase.PORTFORWARD_LOCAL; - break; - - case 1: - type = HostDatabase.PORTFORWARD_REMOTE; - break; - - case 2: - type = HostDatabase.PORTFORWARD_DYNAMIC5; - break; - } - - PortForwardBean pfb = new PortForwardBean( - host != null ? host.getId() : -1, - nicknameEdit.getText().toString(), type, - sourcePortEdit.getText().toString(), - destEdit.getText().toString()); - - if (hostBridge != null) { - hostBridge.addPortForward(pfb); - hostBridge.enablePortForward(pfb); - } - - if (host != null && !hostdb.savePortForward(pfb)) - throw new SQLException("Could not save port forward"); - - updateHandler.sendEmptyMessage(-1); - } - catch (Exception e) { - Log.e(TAG, "Could not update port forward", e); - // TODO Show failure dialog. - } - } - }) - .setNegativeButton(R.string.delete_neg, null).create().show(); - return true; - } - }); - return true; - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - // Create menu to handle deleting and editing port forward - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - final PortForwardBean pfb = (PortForwardBean) this.getListView().getItemAtPosition(info.position); - menu.setHeaderTitle(pfb.getNickname()); - MenuItem edit = menu.add(R.string.portforward_edit); - edit.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - final View editTunnelView = inflater.inflate(R.layout.dia_portforward, null, false); - final Spinner typeSpinner = (Spinner) editTunnelView.findViewById(R.id.portforward_type); - - if (HostDatabase.PORTFORWARD_LOCAL.equals(pfb.getType())) - typeSpinner.setSelection(0); - else if (HostDatabase.PORTFORWARD_REMOTE.equals(pfb.getType())) - typeSpinner.setSelection(1); - else - typeSpinner.setSelection(2); - - final EditText nicknameEdit = (EditText) editTunnelView.findViewById(R.id.nickname); - nicknameEdit.setText(pfb.getNickname()); - final EditText sourcePortEdit = (EditText) editTunnelView.findViewById(R.id.portforward_source); - sourcePortEdit.setText(String.valueOf(pfb.getSourcePort())); - final EditText destEdit = (EditText) editTunnelView.findViewById(R.id.portforward_destination); - - if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(pfb.getType())) { - destEdit.setEnabled(false); - } - else { - destEdit.setText(String.format("%s:%d", pfb.getDestAddr(), pfb.getDestPort())); - } - - typeSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { - public void onItemSelected(AdapterView<?> value, View view, - int position, long id) { - destEdit.setEnabled(position != 2); - } - public void onNothingSelected(AdapterView<?> arg0) { - } - }); - new AlertDialog.Builder(PortForwardListActivity.this) - .setView(editTunnelView) - .setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - try { - if (hostBridge != null) - hostBridge.disablePortForward(pfb); - - pfb.setNickname(nicknameEdit.getText().toString()); - - switch (typeSpinner.getSelectedItemPosition()) { - case 0: - pfb.setType(HostDatabase.PORTFORWARD_LOCAL); - break; - - case 1: - pfb.setType(HostDatabase.PORTFORWARD_REMOTE); - break; - - case 2: - pfb.setType(HostDatabase.PORTFORWARD_DYNAMIC5); - break; - } - - pfb.setSourcePort(Integer.parseInt(sourcePortEdit.getText().toString())); - pfb.setDest(destEdit.getText().toString()); - - // Use the new settings for the existing connection. - if (hostBridge != null) - updateHandler.postDelayed(new Runnable() { - public void run() { - hostBridge.enablePortForward(pfb); - updateHandler.sendEmptyMessage(-1); - } - }, LISTENER_CYCLE_TIME); - - if (!hostdb.savePortForward(pfb)) - throw new SQLException("Could not save port forward"); - - updateHandler.sendEmptyMessage(-1); - } - catch (Exception e) { - Log.e(TAG, "Could not update port forward", e); - // TODO Show failure dialog. - } - } - }) - .setNegativeButton(android.R.string.cancel, null).create().show(); - return true; - } - }); - MenuItem delete = menu.add(R.string.portforward_delete); - delete.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - // prompt user to make sure they really want this - new AlertDialog.Builder(PortForwardListActivity.this) - .setMessage(getString(R.string.delete_message, pfb.getNickname())) - .setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - try { - // Delete the port forward from the host if needed. - if (hostBridge != null) - hostBridge.removePortForward(pfb); - - hostdb.deletePortForward(pfb); - } - catch (Exception e) { - Log.e(TAG, "Could not delete port forward", e); - } - - updateHandler.sendEmptyMessage(-1); - } - }) - .setNegativeButton(R.string.delete_neg, null).create().show(); - return true; - } - }); - } - - protected Handler updateHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - PortForwardListActivity.this.updateList(); - } - }; - - protected void updateList() { - if (hostBridge != null) { - this.portForwards = hostBridge.getPortForwards(); - } - else { - if (this.hostdb == null) return; - - this.portForwards = this.hostdb.getPortForwardsForHost(host); - } - - PortForwardAdapter adapter = new PortForwardAdapter(this, portForwards); - this.setListAdapter(adapter); - } - - class PortForwardAdapter extends ArrayAdapter<PortForwardBean> { - class ViewHolder { - public TextView nickname; - public TextView caption; - } - - private List<PortForwardBean> portForwards; - - public PortForwardAdapter(Context context, List<PortForwardBean> portForwards) { - super(context, R.layout.item_portforward, portForwards); - this.portForwards = portForwards; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder holder; - - if (convertView == null) { - convertView = inflater.inflate(R.layout.item_portforward, null, false); - holder = new ViewHolder(); - holder.nickname = (TextView)convertView.findViewById(android.R.id.text1); - holder.caption = (TextView)convertView.findViewById(android.R.id.text2); - convertView.setTag(holder); - } - else - holder = (ViewHolder) convertView.getTag(); - - PortForwardBean pfb = portForwards.get(position); - holder.nickname.setText(pfb.getNickname()); - holder.caption.setText(pfb.getDescription()); - - if (hostBridge != null && !pfb.isEnabled()) { - holder.nickname.setPaintFlags(holder.nickname.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); - holder.caption.setPaintFlags(holder.caption.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); - } - - return convertView; - } - } -}
--- a/src/com/five_ten_sg/connectbot/PubkeyListActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,674 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.util.EventListener; -import java.util.List; - -import com.five_ten_sg.connectbot.bean.PubkeyBean; -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.util.FileChooser; -import com.five_ten_sg.connectbot.util.FileChooserCallback; -import com.five_ten_sg.connectbot.util.PubkeyDatabase; -import com.five_ten_sg.connectbot.util.PubkeyUtils; -import android.app.AlertDialog; -import android.app.ListActivity; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.Environment; -import android.os.IBinder; -import android.text.ClipboardManager; -import android.util.Log; -import android.view.ContextMenu; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MenuItem.OnMenuItemClickListener; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.TableRow; -import android.widget.TextView; -import android.widget.Toast; - -import ch.ethz.ssh2.crypto.Base64; -import ch.ethz.ssh2.crypto.PEMDecoder; -import ch.ethz.ssh2.crypto.PEMStructure; - -/** - * List public keys in database by nickname and describe their properties. Allow users to import, - * generate, rename, and delete key pairs. - * - * @author Kenny Root - */ -public class PubkeyListActivity extends ListActivity implements EventListener, FileChooserCallback { - - public final static String TAG = "ConnectBot.PubkeyListActivity"; - - private static final int MAX_KEYFILE_SIZE = 8192; - private static final int KEYTYPE_PUBLIC = 0; - private static final int KEYTYPE_PRIVATE = 1; - - protected PubkeyDatabase pubkeydb; - private List<PubkeyBean> pubkeys; - - protected ClipboardManager clipboard; - - protected LayoutInflater inflater = null; - - protected TerminalManager bound = null; - - private MenuItem onstartToggle = null; - private MenuItem confirmUse = null; - - private ServiceConnection connection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - bound = ((TerminalManager.TerminalBinder) service).getService(); - // update our listview binder to find the service - updateList(); - } - public void onServiceDisconnected(ComponentName className) { - bound = null; - updateList(); - } - }; - - @Override - public void onStart() { - super.onStart(); - bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - - if (pubkeydb == null) - pubkeydb = new PubkeyDatabase(this); - } - - @Override - public void onStop() { - super.onStop(); - unbindService(connection); - - if (pubkeydb != null) { - pubkeydb.close(); - pubkeydb = null; - } - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - setContentView(R.layout.act_pubkeylist); - this.setTitle(String.format("%s: %s", - getResources().getText(R.string.app_name), - getResources().getText(R.string.title_pubkey_list))); - // connect with hosts database and populate list - pubkeydb = new PubkeyDatabase(this); - updateList(); - registerForContextMenu(getListView()); - getListView().setOnItemClickListener(new OnItemClickListener() { - public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { - PubkeyBean pubkey = (PubkeyBean) getListView().getItemAtPosition(position); - boolean loaded = bound.isKeyLoaded(pubkey.getNickname()); - - // handle toggling key in-memory on/off - if (loaded) { - bound.removeKey(pubkey.getNickname()); - updateList(); - } - else { - handleAddKey(pubkey); - } - } - }); - clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE); - inflater = LayoutInflater.from(this); - } - - /** - * Read given file into memory as <code>byte[]</code>. - */ - protected static byte[] readRaw(File file) throws Exception { - InputStream is = new FileInputStream(file); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - int bytesRead; - byte[] buffer = new byte[1024]; - - while ((bytesRead = is.read(buffer)) != -1) { - os.write(buffer, 0, bytesRead); - } - - os.flush(); - os.close(); - is.close(); - return os.toByteArray(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - MenuItem generatekey = menu.add(R.string.pubkey_generate); - generatekey.setIcon(android.R.drawable.ic_menu_manage); - generatekey.setIntent(new Intent(PubkeyListActivity.this, GeneratePubkeyActivity.class)); - MenuItem importkey = menu.add(R.string.pubkey_import); - importkey.setIcon(android.R.drawable.ic_menu_upload); - importkey.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - FileChooser.selectFile(PubkeyListActivity.this, PubkeyListActivity.this, - FileChooser.REQUEST_CODE_SELECT_FILE, - getString(R.string.file_chooser_select_file, getString(R.string.select_for_key_import))); - return true; - } - }); - return true; - } - - protected void handleAddKey(final PubkeyBean pubkey) { - if (pubkey.isEncrypted()) { - final View view = inflater.inflate(R.layout.dia_password, null); - final EditText passwordField = (EditText)view.findViewById(android.R.id.text1); - new AlertDialog.Builder(PubkeyListActivity.this) - .setView(view) - .setPositiveButton(R.string.pubkey_unlock, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - handleAddKey(pubkey, passwordField.getText().toString()); - } - }) - .setNegativeButton(android.R.string.cancel, null).create().show(); - } - else { - handleAddKey(pubkey, null); - } - } - - protected void handleAddKey(PubkeyBean keybean, String password) { - KeyPair pair = null; - - if (PubkeyDatabase.KEY_TYPE_IMPORTED.equals(keybean.getType())) { - // load specific key using pem format - try { - pair = PEMDecoder.decode(new String(keybean.getPrivateKey()).toCharArray(), password); - } - catch (Exception e) { - String message = getResources().getString(R.string.pubkey_failed_add, keybean.getNickname()); - Log.e(TAG, message, e); - Toast.makeText(PubkeyListActivity.this, message, Toast.LENGTH_LONG).show(); - } - } - else { - // load using internal generated format - try { - PrivateKey privKey = PubkeyUtils.decodePrivate(keybean.getPrivateKey(), keybean.getType(), password); - PublicKey pubKey = PubkeyUtils.decodePublic(keybean.getPublicKey(), keybean.getType()); - Log.d(TAG, "Unlocked key " + PubkeyUtils.formatKey(pubKey)); - pair = new KeyPair(pubKey, privKey); - } - catch (Exception e) { - String message = getResources().getString(R.string.pubkey_failed_add, keybean.getNickname()); - Log.e(TAG, message, e); - Toast.makeText(PubkeyListActivity.this, message, Toast.LENGTH_LONG).show(); - return; - } - } - - if (pair == null) return; - - Log.d(TAG, String.format("Unlocked key '%s'", keybean.getNickname())); - // save this key in memory - bound.addKey(keybean, pair, true); - updateList(); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - // Create menu to handle deleting and editing pubkey - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - final PubkeyBean pubkey = (PubkeyBean) getListView().getItemAtPosition(info.position); - menu.setHeaderTitle(pubkey.getNickname()); - // TODO: option load/unload key from in-memory list - // prompt for password as needed for passworded keys - // cant change password or clipboard imported keys - final boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType()); - final boolean loaded = bound.isKeyLoaded(pubkey.getNickname()); - MenuItem load = menu.add(loaded ? R.string.pubkey_memory_unload : R.string.pubkey_memory_load); - load.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - if (loaded) { - bound.removeKey(pubkey.getNickname()); - updateList(); - } - else { - handleAddKey(pubkey); - //bound.addKey(nickname, trileadKey); - } - - return true; - } - }); - onstartToggle = menu.add(R.string.pubkey_load_on_start); - onstartToggle.setVisible(!pubkey.isEncrypted()); - onstartToggle.setCheckable(true); - onstartToggle.setChecked(pubkey.isStartup()); - onstartToggle.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - // toggle onstart status - pubkey.setStartup(!pubkey.isStartup()); - pubkeydb.savePubkey(pubkey); - updateList(); - return true; - } - }); - MenuItem changePassword = menu.add(R.string.pubkey_change_password); - changePassword.setVisible(!imported); - changePassword.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - final View changePasswordView = inflater.inflate(R.layout.dia_changepassword, null, false); - ((TableRow)changePasswordView.findViewById(R.id.old_password_prompt)) - .setVisibility(pubkey.isEncrypted() ? View.VISIBLE : View.GONE); - new AlertDialog.Builder(PubkeyListActivity.this) - .setView(changePasswordView) - .setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - String oldPassword = ((EditText)changePasswordView.findViewById(R.id.old_password)).getText().toString(); - String password1 = ((EditText)changePasswordView.findViewById(R.id.password1)).getText().toString(); - String password2 = ((EditText)changePasswordView.findViewById(R.id.password2)).getText().toString(); - - if (!password1.equals(password2)) { - new AlertDialog.Builder(PubkeyListActivity.this) - .setMessage(R.string.alert_passwords_do_not_match_msg) - .setPositiveButton(android.R.string.ok, null) - .create().show(); - return; - } - - try { - if (!pubkey.changePassword(oldPassword, password1)) - new AlertDialog.Builder(PubkeyListActivity.this) - .setMessage(R.string.alert_wrong_password_msg) - .setPositiveButton(android.R.string.ok, null) - .create().show(); - else { - pubkeydb.savePubkey(pubkey); - updateList(); - } - } - catch (Exception e) { - Log.e(TAG, "Could not change private key password", e); - new AlertDialog.Builder(PubkeyListActivity.this) - .setMessage(R.string.alert_key_corrupted_msg) - .setPositiveButton(android.R.string.ok, null) - .create().show(); - } - } - }) - .setNegativeButton(android.R.string.cancel, null).create().show(); - return true; - } - }); - confirmUse = menu.add(R.string.pubkey_confirm_use); - confirmUse.setCheckable(true); - confirmUse.setChecked(pubkey.isConfirmUse()); - confirmUse.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - // toggle confirm use - pubkey.setConfirmUse(!pubkey.isConfirmUse()); - pubkeydb.savePubkey(pubkey); - updateList(); - return true; - } - }); - MenuItem copyPublicToClipboard = menu.add(R.string.pubkey_copy_public); - copyPublicToClipboard.setVisible(!imported); - copyPublicToClipboard.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - try { - PublicKey pk = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); - String openSSHPubkey = PubkeyUtils.convertToOpenSSHFormat(pk, pubkey.getNickname()); - clipboard.setText(openSSHPubkey); - } - catch (Exception e) { - e.printStackTrace(); - } - - return true; - } - }); - MenuItem exportPublic = menu.add(R.string.pubkey_export_public); - exportPublic.setVisible(!imported); - exportPublic.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - String keyString = PubkeyUtils.getPubkeyString(pubkey); - - if (keyString != null) - saveKeyToFile(keyString, pubkey.getNickname(), KEYTYPE_PUBLIC); - - return true; - } - }); - MenuItem copyPrivateToClipboard = menu.add(R.string.pubkey_copy_private); - copyPrivateToClipboard.setVisible(!pubkey.isEncrypted() || imported); - copyPrivateToClipboard.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - String keyString = PubkeyUtils.getPrivkeyString(pubkey, null); - - if (keyString != null) - clipboard.setText(keyString); - - return true; - } - }); - MenuItem exportPrivate = menu.add(R.string.pubkey_export_private); - exportPrivate.setVisible(!pubkey.isEncrypted() || imported); - exportPrivate.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - /* if (pubkey.isEncrypted()) { - final View view = inflater.inflate(R.layout.dia_password, null); - final EditText passwordField = (EditText)view.findViewById(android.R.id.text1); - - new AlertDialog.Builder(PubkeyListActivity.this) - .setView(view) - .setPositiveButton(R.string.pubkey_unlock, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - String keyString = PubkeyUtils.getPrivkeyString(pubkey, passwordField.getText().toString()); - if (keyString != null) - saveKeyToFile(keyString, pubkey.getNickname(), KEYTYPE_PRIVATE); - } - }) - .setNegativeButton(android.R.string.cancel, null).create().show(); - } else { */ - String keyString = PubkeyUtils.getPrivkeyString(pubkey, null); - - if (keyString != null) - saveKeyToFile(keyString, pubkey.getNickname(), KEYTYPE_PRIVATE); - -// } - return true; - } - }); - MenuItem delete = menu.add(R.string.pubkey_delete); - delete.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - // prompt user to make sure they really want this - new AlertDialog.Builder(PubkeyListActivity.this) - .setMessage(getString(R.string.delete_message, pubkey.getNickname())) - .setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - // dont forget to remove from in-memory - if (loaded) - bound.removeKey(pubkey.getNickname()); - - // delete from backend database and update gui - pubkeydb.deletePubkey(pubkey); - updateList(); - } - }) - .setNegativeButton(R.string.delete_neg, null).create().show(); - return true; - } - }); - } - - protected void updateList() { - if (pubkeydb == null) return; - - pubkeys = pubkeydb.allPubkeys(); - PubkeyAdapter adapter = new PubkeyAdapter(this, pubkeys); - this.setListAdapter(adapter); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - super.onActivityResult(requestCode, resultCode, intent); - - switch (requestCode) { - case FileChooser.REQUEST_CODE_SELECT_FILE: - if (resultCode == RESULT_OK && intent != null) { - File file = FileChooser.getSelectedFile(intent); - - if (file != null) - readKeyFromFile(file); - } - - break; - } - } - - /** - * @param name - */ - private void readKeyFromFile(File file) { - PubkeyBean pubkey = new PubkeyBean(); - // find the exact file selected - pubkey.setNickname(file.getName()); - - if (file.length() > MAX_KEYFILE_SIZE) { - Toast.makeText(PubkeyListActivity.this, - R.string.pubkey_import_parse_problem, - Toast.LENGTH_LONG).show(); - return; - } - - // parse the actual key once to check if its encrypted - // then save original file contents into our database - try { - byte[] raw = readRaw(file); - String data = new String(raw); - - if (data.startsWith(PubkeyUtils.PKCS8_START)) { - int start = data.indexOf(PubkeyUtils.PKCS8_START) + PubkeyUtils.PKCS8_START.length(); - int end = data.indexOf(PubkeyUtils.PKCS8_END); - - if (end > start) { - char[] encoded = data.substring(start, end - 1).toCharArray(); - Log.d(TAG, "encoded: " + new String(encoded)); - byte[] decoded = Base64.decode(encoded); - KeyPair kp = PubkeyUtils.recoverKeyPair(decoded); - pubkey.setType(kp.getPrivate().getAlgorithm()); - pubkey.setPrivateKey(kp.getPrivate().getEncoded()); - pubkey.setPublicKey(kp.getPublic().getEncoded()); - } - else { - Log.e(TAG, "Problem parsing PKCS#8 file; corrupt?"); - Toast.makeText(PubkeyListActivity.this, - R.string.pubkey_import_parse_problem, - Toast.LENGTH_LONG).show(); - } - } - else { - PEMStructure struct = PEMDecoder.parsePEM(new String(raw).toCharArray()); - pubkey.setEncrypted(PEMDecoder.isPEMEncrypted(struct)); - pubkey.setType(PubkeyDatabase.KEY_TYPE_IMPORTED); - pubkey.setPrivateKey(raw); - } - - // write new value into database - if (pubkeydb == null) - pubkeydb = new PubkeyDatabase(this); - - pubkeydb.savePubkey(pubkey); - updateList(); - } - catch (Exception e) { - Log.e(TAG, "Problem parsing imported private key", e); - Toast.makeText(PubkeyListActivity.this, R.string.pubkey_import_parse_problem, Toast.LENGTH_LONG).show(); - } - } - - private void saveKeyToFile(final String keyString, final String nickName, int keyType) { - final int titleId, messageId, successId, errorId; - final String errorString; - - if (keyType == KEYTYPE_PRIVATE) { - titleId = R.string.pubkey_private_save_as; - messageId = R.string.pubkey_private_save_as_desc; - successId = R.string.pubkey_private_export_success; - errorId = R.string.pubkey_private_export_problem; - errorString = "Error exporting private key"; - } - else { - titleId = R.string.pubkey_public_save_as; - messageId = R.string.pubkey_public_save_as_desc; - errorId = R.string.pubkey_public_export_problem; - successId = R.string.pubkey_public_export_success; - errorString = "Error exporting public key"; - } - - final String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath(); - final EditText fileName = new EditText(PubkeyListActivity.this); - fileName.setSingleLine(); - - if (nickName != null) { - if (keyType == KEYTYPE_PRIVATE) - fileName.setText(sdcard + File.separator + nickName.trim()); - else - fileName.setText(sdcard + File.separator + nickName.trim() + ".pub"); - } - - new AlertDialog.Builder(PubkeyListActivity.this) - .setTitle(titleId) - .setMessage(messageId) - .setView(fileName) - .setPositiveButton(R.string.save, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - File keyFile = new File(fileName.getText().toString()); - - if (!keyFile.exists()) { - try { - keyFile.createNewFile(); - } - catch (IOException e) { - Log.e(TAG, errorString); - Toast.makeText(PubkeyListActivity.this, - errorId, - Toast.LENGTH_LONG).show(); - return; - } - } - - FileOutputStream fout = null; - - try { - fout = new FileOutputStream(keyFile); - fout.write(keyString.getBytes(), 0, keyString.getBytes().length); - fout.flush(); - } - catch (Exception e) { - Log.e(TAG, errorString); - Toast.makeText(PubkeyListActivity.this, - errorId, - Toast.LENGTH_LONG).show(); - return; - } - - Toast.makeText(PubkeyListActivity.this, - getResources().getString(successId, keyFile.getPath().toString()), - Toast.LENGTH_LONG).show(); - } - }).setNegativeButton(android.R.string.cancel, null).create().show(); - } - - public void fileSelected(File f) { - Log.d(TAG, "File chooser returned " + f); - readKeyFromFile(f); - } - - class PubkeyAdapter extends ArrayAdapter<PubkeyBean> { - private List<PubkeyBean> pubkeys; - - class ViewHolder { - public TextView nickname; - public TextView caption; - public ImageView icon; - } - - public PubkeyAdapter(Context context, List<PubkeyBean> pubkeys) { - super(context, R.layout.item_pubkey, pubkeys); - this.pubkeys = pubkeys; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder holder; - - if (convertView == null) { - convertView = inflater.inflate(R.layout.item_pubkey, null, false); - holder = new ViewHolder(); - holder.nickname = (TextView) convertView.findViewById(android.R.id.text1); - holder.caption = (TextView) convertView.findViewById(android.R.id.text2); - holder.icon = (ImageView) convertView.findViewById(android.R.id.icon1); - convertView.setTag(holder); - } - else - holder = (ViewHolder) convertView.getTag(); - - PubkeyBean pubkey = pubkeys.get(position); - holder.nickname.setText(pubkey.getNickname()); - boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType()); - - if (imported) { - try { - PEMStructure struct = PEMDecoder.parsePEM(new String(pubkey.getPrivateKey()).toCharArray()); - String type = (struct.pemType == PEMDecoder.PEM_RSA_PRIVATE_KEY) ? "RSA" : - (struct.pemType == PEMDecoder.PEM_DSA_PRIVATE_KEY) ? "DSA" : "EC"; - holder.caption.setText(String.format("%s unknown-bit", type)); - } - catch (IOException e) { - Log.e(TAG, "Error decoding IMPORTED public key at " + pubkey.getId(), e); - } - } - else { - try { - holder.caption.setText(pubkey.getDescription()); - } - catch (Exception e) { - Log.e(TAG, "Error decoding public key at " + pubkey.getId(), e); - holder.caption.setText(R.string.pubkey_unknown_format); - } - } - - if (bound == null) { - holder.icon.setVisibility(View.GONE); - } - else { - holder.icon.setVisibility(View.VISIBLE); - - if (bound.isKeyLoaded(pubkey.getNickname())) - holder.icon.setImageState(new int[] { android.R.attr.state_checked }, true); - else - holder.icon.setImageState(new int[] { }, true); - } - - return convertView; - } - } -}
--- a/src/com/five_ten_sg/connectbot/SettingsActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import com.five_ten_sg.connectbot.util.PreferenceConstants; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.PreferenceActivity; -import android.preference.PreferenceManager; -import android.util.Log; - -public class SettingsActivity extends PreferenceActivity { - private static final String TAG = "ConnectBot.Settings"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - try { - addPreferencesFromResource(R.xml.preferences); - } - catch (ClassCastException e) { - Log.e(TAG, "Shared preferences are corrupt! Resetting to default values."); - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - // Blow away all the preferences - SharedPreferences.Editor editor = preferences.edit(); - editor.clear(); - editor.commit(); - PreferenceManager.setDefaultValues(this, R.xml.preferences, true); - // Since they were able to get to the Settings activity, they already agreed to the EULA - editor = preferences.edit(); - editor.putBoolean(PreferenceConstants.EULA, true); - editor.commit(); - addPreferencesFromResource(R.xml.preferences); - } - - // TODO: add parse checking here to make sure we have integer value for scrollback - } - -}
--- a/src/com/five_ten_sg/connectbot/StrictModeSetup.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.five_ten_sg.connectbot; -import android.annotation.TargetApi; -import android.os.StrictMode; -@TargetApi(9) -public class StrictModeSetup { - public static void run() { - StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX); - } -}
--- a/src/com/five_ten_sg/connectbot/TerminalView.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,459 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.five_ten_sg.connectbot.bean.SelectionArea; -import com.five_ten_sg.connectbot.service.FontSizeChangedListener; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalKeyListener; -import android.app.Activity; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ResolveInfo; -import android.database.Cursor; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PixelXorXfermode; -import android.graphics.RectF; -import android.net.Uri; -import android.os.AsyncTask; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; -import android.view.inputmethod.BaseInputConnection; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputConnection; -import android.view.ScaleGestureDetector; -import android.widget.Toast; -import de.mud.terminal.VDUBuffer; - -/** - * User interface {@link View} for showing a TerminalBridge in an - * {@link Activity}. Handles drawing bitmap updates and passing keystrokes down - * to terminal. - * - * @author jsharkey - */ -public class TerminalView extends View implements FontSizeChangedListener { - public final static String TAG = "ConnectBot.TerminalView"; - - private final Context context; - public final TerminalBridge bridge; - private final Paint paint; - private final Paint cursorPaint; - private final Paint cursorStrokePaint; - - // Cursor paints to distinguish modes - private Path ctrlCursor, altCursor, shiftCursor; - private RectF tempSrc, tempDst; - private Matrix scaleMatrix; - private static final Matrix.ScaleToFit scaleType = Matrix.ScaleToFit.FILL; - - private Toast notification = null; - private String lastNotification = null; - private volatile boolean notifications = true; - - // Related to Accessibility Features - private boolean mAccessibilityInitialized = false; - private boolean mAccessibilityActive = true; - private Object[] mAccessibilityLock = new Object[0]; - private StringBuffer mAccessibilityBuffer; - private Pattern mControlCodes = null; - private Matcher mCodeMatcher = null; - private AccessibilityEventSender mEventSender = null; - - - private static final String BACKSPACE_CODE = "\\x08\\x1b\\[K"; - private static final String CONTROL_CODE_PATTERN = "\\x1b\\[K[^m]+[m|:]"; - - private static final int ACCESSIBILITY_EVENT_THRESHOLD = 1000; - private static final String SCREENREADER_INTENT_ACTION = "android.accessibilityservice.AccessibilityService"; - private static final String SCREENREADER_INTENT_CATEGORY = "android.accessibilityservice.category.FEEDBACK_SPOKEN"; - - public ScaleGestureDetector mScaleDetector; - - public TerminalView(Context context, TerminalBridge bridge) { - super(context); - this.context = context; - this.bridge = bridge; - paint = new Paint(); - setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); - setFocusable(true); - setFocusableInTouchMode(true); - cursorPaint = new Paint(); - cursorPaint.setColor(bridge.color[bridge.defaultFg]); - cursorPaint.setXfermode(new PixelXorXfermode(bridge.color[bridge.defaultBg])); - cursorPaint.setAntiAlias(true); - cursorStrokePaint = new Paint(cursorPaint); - cursorStrokePaint.setStrokeWidth(0.1f); - cursorStrokePaint.setStyle(Paint.Style.STROKE); - /* - * Set up our cursor indicators on a 1x1 Path object which we can later - * transform to our character width and height - */ - // TODO make this into a resource somehow - shiftCursor = new Path(); - shiftCursor.lineTo(0.5f, 0.33f); - shiftCursor.lineTo(1.0f, 0.0f); - altCursor = new Path(); - altCursor.moveTo(0.0f, 1.0f); - altCursor.lineTo(0.5f, 0.66f); - altCursor.lineTo(1.0f, 1.0f); - ctrlCursor = new Path(); - ctrlCursor.moveTo(0.0f, 0.25f); - ctrlCursor.lineTo(1.0f, 0.5f); - ctrlCursor.lineTo(0.0f, 0.75f); - // For creating the transform when the terminal resizes - tempSrc = new RectF(); - tempSrc.set(0.0f, 0.0f, 1.0f, 1.0f); - tempDst = new RectF(); - scaleMatrix = new Matrix(); - bridge.addFontSizeChangedListener(this); - // connect our view up to the bridge - setOnKeyListener(bridge.getKeyHandler()); - mAccessibilityBuffer = new StringBuffer(); - // Enable accessibility features if a screen reader is active. - new AccessibilityStateTester().execute((Void) null); - mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); - } - - public void destroy() { - // tell bridge to destroy its bitmap - bridge.parentDestroyed(); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - bridge.parentChanged(this); - scaleCursors(); - } - - public void onFontSizeChanged(float size) { - scaleCursors(); - } - - private void scaleCursors() { - // Create a scale matrix to scale our 1x1 representation of the cursor - tempDst.set(0.0f, 0.0f, bridge.charWidth, bridge.charHeight); - scaleMatrix.setRectToRect(tempSrc, tempDst, scaleType); - } - - @Override - public void onDraw(Canvas canvas) { - if (bridge.bitmap != null) { - // draw the bitmap - bridge.onDraw(); - // draw the bridge bitmap if it exists - canvas.drawBitmap(bridge.bitmap, 0, 0, paint); - - // also draw cursor if visible - if (bridge.buffer.isCursorVisible()) { - int cursorColumn = bridge.buffer.getCursorColumn(); - final int cursorRow = bridge.buffer.getCursorRow(); - final int columns = bridge.buffer.getColumns(); - - if (cursorColumn == columns) - cursorColumn = columns - 1; - - if (cursorColumn < 0 || cursorRow < 0) - return; - - int currentAttribute = bridge.buffer.getAttributes( - cursorColumn, cursorRow); - boolean onWideCharacter = (currentAttribute & VDUBuffer.FULLWIDTH) != 0; - int x = cursorColumn * bridge.charWidth; - int y = (bridge.buffer.getCursorRow() - + bridge.buffer.screenBase - bridge.buffer.windowBase) - * bridge.charHeight; - // Save the current clip and translation - canvas.save(); - canvas.translate(x, y); - canvas.clipRect(0, 0, - bridge.charWidth * (onWideCharacter ? 2 : 1), - bridge.charHeight); - canvas.drawPaint(cursorPaint); - final int deadKey = bridge.getKeyHandler().getDeadKey(); - - if (deadKey != 0) { - canvas.drawText(new char[] { (char)deadKey }, 0, 1, 0, 0, cursorStrokePaint); - } - - // Make sure we scale our decorations to the correct size. - canvas.concat(scaleMatrix); - int metaState = bridge.getKeyHandler().getMetaState(); - - if ((metaState & TerminalKeyListener.META_SHIFT_ON) != 0) - canvas.drawPath(shiftCursor, cursorStrokePaint); - else if ((metaState & TerminalKeyListener.META_SHIFT_LOCK) != 0) - canvas.drawPath(shiftCursor, cursorPaint); - - if ((metaState & TerminalKeyListener.META_ALT_ON) != 0) - canvas.drawPath(altCursor, cursorStrokePaint); - else if ((metaState & TerminalKeyListener.META_ALT_LOCK) != 0) - canvas.drawPath(altCursor, cursorPaint); - - if ((metaState & TerminalKeyListener.META_CTRL_ON) != 0) - canvas.drawPath(ctrlCursor, cursorStrokePaint); - else if ((metaState & TerminalKeyListener.META_CTRL_LOCK) != 0) - canvas.drawPath(ctrlCursor, cursorPaint); - - // Restore previous clip region - canvas.restore(); - } - - // draw any highlighted area - if (bridge.isSelectingForCopy()) { - SelectionArea area = bridge.getSelectionArea(); - canvas.save(Canvas.CLIP_SAVE_FLAG); - canvas.clipRect( - area.getLeft() * bridge.charWidth, - area.getTop() * bridge.charHeight, - (area.getRight() + 1) * bridge.charWidth, - (area.getBottom() + 1) * bridge.charHeight - ); - canvas.drawPaint(cursorPaint); - canvas.restore(); - } - } - } - - public void notifyUser(String message) { - try { - // ignore if don't want notifications - if (!notifications) return; - // Don't keep telling the user the same thing. - if (lastNotification != null && lastNotification.equals(message)) return; - // create or use old toast - if (notification == null) { - notification = Toast.makeText(context, message, Toast.LENGTH_SHORT); - } - else { - notification.setText(message); - } - notification.show(); - lastNotification = message; - } - catch (Exception e) { - Log.e(TAG, "Problem while trying to notify user", e); - } - } - - /** - * Ask the {@link TerminalBridge} we're connected to to resize to a specific size. - * @param width - * @param height - */ - public void forceSize(int width, int height) { - bridge.resizeComputed(width, height, getWidth(), getHeight()); - } - - /** - * Sets the ability for the TerminalView to display Toast notifications to the user. - * @param value whether to enable notifications or not - */ - public void setNotifications(boolean value) { - notifications = value; - } - - @Override - public boolean onCheckIsTextEditor() { - return true; - } - - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - outAttrs.imeOptions |= - EditorInfo.IME_FLAG_NO_EXTRACT_UI | - EditorInfo.IME_FLAG_NO_ENTER_ACTION | - EditorInfo.IME_ACTION_NONE; - outAttrs.inputType = EditorInfo.TYPE_NULL; - return new BaseInputConnection(this, false) { - @Override - public boolean deleteSurroundingText(int leftLength, int rightLength) { - if (rightLength == 0 && leftLength == 0) { - return this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); - } - - for (int i = 0; i < leftLength; i++) { - this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); - } - - // TODO: forward delete - return true; - } - }; - } - - public void propagateConsoleText(char[] rawText, int length) { - if (mAccessibilityActive) { - synchronized (mAccessibilityLock) { - mAccessibilityBuffer.append(rawText, 0, length); - } - - if (mAccessibilityInitialized) { - if (mEventSender != null) { - removeCallbacks(mEventSender); - } - else { - mEventSender = new AccessibilityEventSender(); - } - - postDelayed(mEventSender, ACCESSIBILITY_EVENT_THRESHOLD); - } - } - } - - private class AccessibilityEventSender implements Runnable { - public void run() { - synchronized (mAccessibilityLock) { - if (mCodeMatcher == null) { - mCodeMatcher = mControlCodes.matcher(mAccessibilityBuffer); - } - else { - mCodeMatcher.reset(mAccessibilityBuffer); - } - - // Strip all control codes out. - mAccessibilityBuffer = new StringBuffer(mCodeMatcher.replaceAll(" ")); - // Apply Backspaces using backspace character sequence - int i = mAccessibilityBuffer.indexOf(BACKSPACE_CODE); - - while (i != -1) { - mAccessibilityBuffer = mAccessibilityBuffer.replace(i == 0 ? 0 : i - 1, i - + BACKSPACE_CODE.length(), ""); - i = mAccessibilityBuffer.indexOf(BACKSPACE_CODE); - } - - if (mAccessibilityBuffer.length() > 0) { - AccessibilityEvent event = AccessibilityEvent.obtain( - AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); - event.setFromIndex(0); - event.setAddedCount(mAccessibilityBuffer.length()); - event.getText().add(mAccessibilityBuffer); - sendAccessibilityEventUnchecked(event); - mAccessibilityBuffer.setLength(0); - } - } - } - } - - private class AccessibilityStateTester extends AsyncTask<Void, Void, Boolean> { - @Override - protected Boolean doInBackground(Void... params) { - /* - * Presumably if the accessibility manager is not enabled, we don't - * need to send accessibility events. - */ - final AccessibilityManager accessibility = (AccessibilityManager) context - .getSystemService(Context.ACCESSIBILITY_SERVICE); - - if (!accessibility.isEnabled()) { - return false; - } - - /* - * Restrict the set of intents to only accessibility services that - * have the category FEEDBACK_SPOKEN (aka, screen readers). - */ - final Intent screenReaderIntent = new Intent(SCREENREADER_INTENT_ACTION); - screenReaderIntent.addCategory(SCREENREADER_INTENT_CATEGORY); - final ContentResolver cr = context.getContentResolver(); - final List<ResolveInfo> screenReaders = context.getPackageManager().queryIntentServices( - screenReaderIntent, 0); - boolean foundScreenReader = false; - final int N = screenReaders.size(); - - for (int i = 0; i < N; i++) { - final ResolveInfo screenReader = screenReaders.get(i); - /* - * All screen readers are expected to implement a content - * provider that responds to: - * content://<nameofpackage>.providers.StatusProvider - */ - final Cursor cursor = cr.query( - Uri.parse("content://" + screenReader.serviceInfo.packageName - + ".providers.StatusProvider"), null, null, null, null); - - if (cursor != null && cursor.moveToFirst()) { - /* - * These content providers use a special cursor that only has - * one element, an integer that is 1 if the screen reader is - * running. - */ - final int status = cursor.getInt(0); - cursor.close(); - - if (status == 1) { - foundScreenReader = true; - break; - } - } - } - - if (foundScreenReader) { - mControlCodes = Pattern.compile(CONTROL_CODE_PATTERN); - } - - return foundScreenReader; - } - - @Override - protected void onPostExecute(Boolean result) { - mAccessibilityActive = result; - mAccessibilityInitialized = true; - - if (result) { - mEventSender = new AccessibilityEventSender(); - postDelayed(mEventSender, ACCESSIBILITY_EVENT_THRESHOLD); - } - else { - mAccessibilityBuffer = null; - } - } - } - - private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { - @Override - public boolean onScale(ScaleGestureDetector detector) { - float mScaleFactor = detector.getScaleFactor(); - - if (mScaleFactor > 1.1) { - bridge.increaseFontSize(); - return true; - } - else if (mScaleFactor < 0.9) { - bridge.decreaseFontSize(); - return true; - } - - return (false); - } - } - -}
--- a/src/com/five_ten_sg/connectbot/WizardActivity.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot; - -import com.five_ten_sg.connectbot.util.HelpTopicView; -import android.app.Activity; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.TextView; -import android.widget.ViewFlipper; - -/** - * Show a series of wizard-like steps to the user, which might include an EULA, - * program credits, and helpful hints. - * - * @author jsharkey - */ -public class WizardActivity extends Activity { - protected ViewFlipper flipper = null; - private Button next, prev; - private static final String TAG = "ConnectBot.WizardActivity"; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.act_wizard); - this.flipper = (ViewFlipper) findViewById(R.id.wizard_flipper); - // inflate the layout for EULA step - LayoutInflater inflater = LayoutInflater.from(this); - View helpView = inflater.inflate(R.layout.wiz_eula, this.flipper, false); - this.flipper.addView(helpView); - // Add a view for each help topic we want the user to see. - String[] topics = getResources().getStringArray(R.array.list_wizard_topics); - - for (String topic : topics) { - flipper.addView(new HelpTopicView(this).setTopic(topic)); - } - - next = (Button)this.findViewById(R.id.action_next); - next.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - if (isLastDisplayed()) { - // user walked past end of wizard, so return okay - WizardActivity.this.setResult(Activity.RESULT_OK); - WizardActivity.this.finish(); - } - else { - // show next step and update buttons - flipper.showNext(); - updateButtons(); - } - } - }); - prev = (Button)this.findViewById(R.id.action_prev); - prev.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - if (isFirstDisplayed()) { - // user walked past beginning of wizard, so return that they cancelled - WizardActivity.this.setResult(Activity.RESULT_CANCELED); - WizardActivity.this.finish(); - } - else { - // show previous step and update buttons - flipper.showPrevious(); - updateButtons(); - } - } - }); - this.updateButtons(); - } - - protected boolean isFirstDisplayed() { - return (flipper.getDisplayedChild() == 0); - } - - protected boolean isLastDisplayed() { - return (flipper.getDisplayedChild() == flipper.getChildCount() - 1); - } - - protected void updateButtons() { - boolean eula = (flipper.getDisplayedChild() == 0); - next.setText(eula ? getString(R.string.wizard_agree) : getString(R.string.wizard_next)); - prev.setText(eula ? getString(R.string.delete_neg) : getString(R.string.wizard_back)); - } -}
--- a/src/com/five_ten_sg/connectbot/bean/AbstractBean.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.bean; - -import java.util.Map.Entry; - -import com.five_ten_sg.connectbot.util.XmlBuilder; -import android.content.ContentValues; - -/** - * @author Kenny Root - * - */ -abstract class AbstractBean { - public abstract ContentValues getValues(); - public abstract String getBeanName(); - - public String toXML() { - XmlBuilder xml = new XmlBuilder(); - xml.append(String.format("<%s>", getBeanName())); - ContentValues values = getValues(); - - for (Entry<String, Object> entry : values.valueSet()) { - Object value = entry.getValue(); - - if (value != null) - xml.append(entry.getKey(), value); - } - - xml.append(String.format("</%s>", getBeanName())); - return xml.toString(); - } -}
--- a/src/com/five_ten_sg/connectbot/bean/HostBean.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,454 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.bean; - -import com.five_ten_sg.connectbot.util.HostDatabase; -import android.content.ContentValues; -import android.net.Uri; - -/** - * @author Kenny Root - * - */ -public class HostBean extends AbstractBean { - public static final String BEAN_NAME = "host"; - - /* Database fields */ - private long id = -1; - private String nickname = null; - private String username = null; - private String hostname = null; - private int port = 22; - private String protocol = "ssh"; - private String hostKeyAlgo = null; - private byte[] hostKey = null; - private long lastConnect = -1; - private String color; - private boolean useKeys = true; - private String useAuthAgent = HostDatabase.AUTHAGENT_NO; - private String postLogin = null; - private long pubkeyId = -1; - private String delKey = HostDatabase.DELKEY_DEL; - private float fontSize = -1; - private boolean fixedSize = false; - private int fixedWidth = 80; - private int fixedHeight = 25; - private boolean wantSession = true; - private boolean compression = false; - private String httpproxy = null; - private String encoding = HostDatabase.ENCODING_DEFAULT; - private boolean stayConnected = false; - private boolean wantX11Forward = false; - private String x11Host = "localhost"; - private int x11Port = 6000; - private String monitor = null; - private String hostemulation = null; - private String encryption5250 = null; - private String library = null; - private String initialMenu = null; - private String program = null; - - public HostBean() { - } - - @Override - public String getBeanName() { - return BEAN_NAME; - } - - public HostBean(String nickname, String protocol, String username, String hostname, int port) { - this.nickname = nickname; - this.protocol = protocol; - this.username = username; - this.hostname = hostname; - this.port = port; - } - - public boolean isSSH() { - return protocol.equals("ssh"); - } - - public boolean is5250() { - return protocol.equals("tn5250"); - } - - public boolean isTelnet() { - return protocol.equals("telnet"); - } - - public boolean isAsync() { - return isSSH() || isTelnet(); - } - - public void setId(long id) { - this.id = id; - } - public long getId() { - return id; - } - public void setNickname(String nickname) { - this.nickname = nickname; - } - public String getNickname() { - return nickname; - } - public void setUsername(String username) { - this.username = username; - } - public String getUsername() { - return username; - } - public void setHostname(String hostname) { - this.hostname = hostname; - } - public String getHostname() { - return hostname; - } - public void setPort(int port) { - this.port = port; - } - public int getPort() { - return port; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public String getProtocol() { - return protocol; - } - - public void setHostKeyAlgo(String hostKeyAlgo) { - this.hostKeyAlgo = hostKeyAlgo; - } - public String getHostKeyAlgo() { - return hostKeyAlgo; - } - public void setHostKey(byte[] hostKey) { - if (hostKey == null) - this.hostKey = null; - else - this.hostKey = hostKey.clone(); - } - public byte[] getHostKey() { - if (hostKey == null) - return null; - else - return hostKey.clone(); - } - public void setLastConnect(long lastConnect) { - this.lastConnect = lastConnect; - } - public long getLastConnect() { - return lastConnect; - } - public void setColor(String color) { - this.color = color; - } - public String getColor() { - return color; - } - public void setUseKeys(boolean useKeys) { - this.useKeys = useKeys; - } - public boolean getUseKeys() { - return useKeys; - } - public void setUseAuthAgent(String useAuthAgent) { - this.useAuthAgent = useAuthAgent; - } - public String getUseAuthAgent() { - return useAuthAgent; - } - public void setPostLogin(String postLogin) { - this.postLogin = postLogin; - } - public String getPostLogin() { - return postLogin; - } - public void setPubkeyId(long pubkeyId) { - this.pubkeyId = pubkeyId; - } - public long getPubkeyId() { - return pubkeyId; - } - public void setWantSession(boolean wantSession) { - this.wantSession = wantSession; - } - public boolean getWantSession() { - return wantSession; - } - public void setDelKey(String delKey) { - this.delKey = delKey; - } - public String getDelKey() { - return delKey; - } - public void setFontSize(float fontSize) { - this.fontSize = fontSize; - } - public float getFontSize() { - return fontSize; - } - public void setFixedSize(boolean fixedSize) { - this.fixedSize = fixedSize; - } - public boolean getFixedSize() { - return fixedSize; - } - public void setFixedWidth(int fixedWidth) { - this.fixedWidth = fixedWidth; - } - public int getFixedWidth() { - return fixedWidth; - } - public void setFixedHeight(int fixedHeight) { - this.fixedHeight = fixedHeight; - } - public int getFixedHeight() { - return fixedHeight; - } - public void setCompression(boolean compression) { - this.compression = compression; - } - public boolean getCompression() { - return compression; - } - public void setHttpproxy(String httpproxy) { - this.httpproxy = httpproxy; - } - public String getHttpproxy() { - return httpproxy; - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public String getEncoding() { - return this.encoding; - } - - public void setStayConnected(boolean stayConnected) { - this.stayConnected = stayConnected; - } - - public boolean getStayConnected() { - return stayConnected; - } - - public String getDescription() { - String description = String.format("%s@%s", username, hostname); - - if (port != 22) - description += String.format(":%d", port); - - return description; - } - - public boolean getWantX11Forward() { - return this.wantX11Forward; - } - - public void setWantX11Forward(boolean wantX11Forward) { - this.wantX11Forward = wantX11Forward; - } - - public String getX11Host() { - return this.x11Host; - } - - public void setX11Host(String x11Host) { - this.x11Host = x11Host; - } - - public int getX11Port() { - return this.x11Port; - } - - public void setX11Port(int x11Port) { - this.x11Port = x11Port; - } - - public String getMonitor() { - return this.monitor; - } - - public void setMonitor(String monitor) { - this.monitor = monitor; - } - - public String getHostEmulation() { - return this.hostemulation; - } - - public void setHostEmulation(String hostemulation) { - this.hostemulation = hostemulation; - } - - public String getEncryption5250() { - return this.encryption5250; - } - - public void setEncryption5250(String encryption5250) { - this.encryption5250 = encryption5250; - } - - public String getLibrary() { - return this.library; - } - - public void setLibrary(String library) { - this.library = library; - } - - public String getInitialMenu() { - return this.initialMenu; - } - - public void setInitialMenu(String initialMenu) { - this.initialMenu = initialMenu; - } - - public String getProgram() { - return this.program; - } - - public void setProgram(String program) { - this.program = program; - } - - @Override - public ContentValues getValues() { - ContentValues values = new ContentValues(); - values.put(HostDatabase.FIELD_HOST_NICKNAME, nickname); - values.put(HostDatabase.FIELD_HOST_PROTOCOL, protocol); - values.put(HostDatabase.FIELD_HOST_USERNAME, username); - values.put(HostDatabase.FIELD_HOST_HOSTNAME, hostname); - values.put(HostDatabase.FIELD_HOST_PORT, port); - values.put(HostDatabase.FIELD_HOST_HOSTKEYALGO, hostKeyAlgo); - values.put(HostDatabase.FIELD_HOST_HOSTKEY, hostKey); - values.put(HostDatabase.FIELD_HOST_LASTCONNECT, lastConnect); - values.put(HostDatabase.FIELD_HOST_COLOR, color); - values.put(HostDatabase.FIELD_HOST_USEKEYS, Boolean.toString(useKeys)); - values.put(HostDatabase.FIELD_HOST_USEAUTHAGENT, useAuthAgent); - values.put(HostDatabase.FIELD_HOST_POSTLOGIN, postLogin); - values.put(HostDatabase.FIELD_HOST_PUBKEYID, pubkeyId); - values.put(HostDatabase.FIELD_HOST_WANTSESSION, Boolean.toString(wantSession)); - values.put(HostDatabase.FIELD_HOST_DELKEY, delKey); - values.put(HostDatabase.FIELD_HOST_FONTSIZE, fontSize); - values.put(HostDatabase.FIELD_HOST_FIXEDSIZE, Boolean.toString(fixedSize)); - values.put(HostDatabase.FIELD_HOST_FIXEDWIDTH, fixedWidth); - values.put(HostDatabase.FIELD_HOST_FIXEDHEIGHT, fixedHeight); - values.put(HostDatabase.FIELD_HOST_COMPRESSION, Boolean.toString(compression)); - values.put(HostDatabase.FIELD_HOST_HTTPPROXY, httpproxy); - values.put(HostDatabase.FIELD_HOST_ENCODING, encoding); - values.put(HostDatabase.FIELD_HOST_STAYCONNECTED, stayConnected); - values.put(HostDatabase.FIELD_HOST_WANTX11FORWARD, wantX11Forward); - values.put(HostDatabase.FIELD_HOST_X11HOST, x11Host); - values.put(HostDatabase.FIELD_HOST_X11PORT, x11Port); - values.put(HostDatabase.FIELD_HOST_MONITOR, monitor); - values.put(HostDatabase.FIELD_HOST_EMULATION, hostemulation); - values.put(HostDatabase.FIELD_HOST_ENCRYPTION5250, encryption5250); - values.put(HostDatabase.FIELD_HOST_LIBRARY5250, library); - values.put(HostDatabase.FIELD_HOST_MENU5250, initialMenu); - values.put(HostDatabase.FIELD_HOST_PROGRAM5250, program); - return values; - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof HostBean)) - return false; - - HostBean host = (HostBean)o; - - if (id != -1 && host.getId() != -1) - return host.getId() == id; - - if (nickname == null) { - if (host.getNickname() != null) - return false; - } - else if (!nickname.equals(host.getNickname())) - return false; - - if (protocol == null) { - if (host.getProtocol() != null) - return false; - } - else if (!protocol.equals(host.getProtocol())) - return false; - - if (username == null) { - if (host.getUsername() != null) - return false; - } - else if (!username.equals(host.getUsername())) - return false; - - if (hostname == null) { - if (host.getHostname() != null) - return false; - } - else if (!hostname.equals(host.getHostname())) - return false; - - if (port != host.getPort()) - return false; - - return true; - } - - @Override - public int hashCode() { - int hash = 7; - - if (id != -1) - return (int)id; - - hash = 31 * hash + (null == nickname ? 0 : nickname.hashCode()); - hash = 31 * hash + (null == protocol ? 0 : protocol.hashCode()); - hash = 31 * hash + (null == username ? 0 : username.hashCode()); - hash = 31 * hash + (null == hostname ? 0 : hostname.hashCode()); - hash = 31 * hash + port; - return hash; - } - - /** - * @return URI identifying this HostBean - */ - public Uri getUri() { - StringBuilder sb = new StringBuilder(); - sb.append(protocol) - .append("://"); - - if (username != null) - sb.append(Uri.encode(username)) - .append('@'); - - sb.append(Uri.encode(hostname)) - .append(':') - .append(port) - .append("/#") - .append(nickname); - return Uri.parse(sb.toString()); - } - -}
--- a/src/com/five_ten_sg/connectbot/bean/PortForwardBean.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,240 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.bean; - -import com.five_ten_sg.connectbot.util.HostDatabase; -import android.content.ContentValues; - - -/** - * @author Kenny Root - * - */ -public class PortForwardBean extends AbstractBean { - public static final String BEAN_NAME = "portforward"; - - /* Database fields */ - private long id = -1; - private long hostId = -1; - private String nickname = null; - private String type = null; - private int sourcePort = -1; - private String destAddr = null; - private int destPort = -1; - - /* Transient values */ - private boolean enabled = false; - private Object identifier = null; - - /** - * @param id database ID of port forward - * @param nickname Nickname to use to identify port forward - * @param type One of the port forward types from {@link HostDatabase} - * @param sourcePort Source port number - * @param destAddr Destination hostname or IP address - * @param destPort Destination port number - */ - public PortForwardBean(long id, long hostId, String nickname, String type, int sourcePort, String destAddr, int destPort) { - this.id = id; - this.hostId = hostId; - this.nickname = nickname; - this.type = type; - this.sourcePort = sourcePort; - this.destAddr = destAddr; - this.destPort = destPort; - } - - /** - * @param type One of the port forward types from {@link HostDatabase} - * @param source Source port number - * @param dest Destination is "host:port" format - */ - public PortForwardBean(long hostId, String nickname, String type, String source, String dest) { - this.hostId = hostId; - this.nickname = nickname; - this.type = type; - this.sourcePort = Integer.parseInt(source); - setDest(dest); - } - - @Override - public String getBeanName() { - return BEAN_NAME; - } - - /** - * @param id the id to set - */ - public void setId(long id) { - this.id = id; - } - - /** - * @return the id - */ - public long getId() { - return id; - } - - /** - * @param nickname the nickname to set - */ - public void setNickname(String nickname) { - this.nickname = nickname; - } - - /** - * @return the nickname - */ - public String getNickname() { - return nickname; - } - - /** - * @param type the type to set - */ - public void setType(String type) { - this.type = type; - } - - /** - * @return the type - */ - public String getType() { - return type; - } - - /** - * @param sourcePort the sourcePort to set - */ - public void setSourcePort(int sourcePort) { - this.sourcePort = sourcePort; - } - - /** - * @return the sourcePort - */ - public int getSourcePort() { - return sourcePort; - } - - /** - * @param dest The destination in "host:port" format - */ - public final void setDest(String dest) { - String[] destSplit = dest.split(":"); - this.destAddr = destSplit[0]; - - if (destSplit.length > 1) - this.destPort = Integer.parseInt(destSplit[1]); - } - - /** - * @param destAddr the destAddr to set - */ - public void setDestAddr(String destAddr) { - this.destAddr = destAddr; - } - - /** - * @return the destAddr - */ - public String getDestAddr() { - return destAddr; - } - - /** - * @param destPort the destPort to set - */ - public void setDestPort(int destPort) { - this.destPort = destPort; - } - - /** - * @return the destPort - */ - public int getDestPort() { - return destPort; - } - - /** - * @param enabled the enabled to set - */ - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - /** - * @return the enabled - */ - public boolean isEnabled() { - return enabled; - } - - /** - * @param identifier the identifier of this particular type to set - */ - public void setIdentifier(Object identifier) { - this.identifier = identifier; - } - - /** - * @return the identifier used by this particular type - */ - public Object getIdentifier() { - return identifier; - } - - /** - * @return human readable description of the port forward - */ - public CharSequence getDescription() { - String description = "Unknown type"; - - if (HostDatabase.PORTFORWARD_LOCAL.equals(type)) { - description = String.format("Local port %d to %s:%d", sourcePort, destAddr, destPort); - } - else if (HostDatabase.PORTFORWARD_REMOTE.equals(type)) { - description = String.format("Remote port %d to %s:%d", sourcePort, destAddr, destPort); - /* I don't think we need the SOCKS4 type. - } else if (HostDatabase.PORTFORWARD_DYNAMIC4.equals(type)) { - description = String.format("Dynamic port %d (SOCKS4)", sourcePort); - */ - } - else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(type)) { - description = String.format("Dynamic port %d (SOCKS)", sourcePort); - } - - return description; - } - - /** - * @return - */ - @Override - public ContentValues getValues() { - ContentValues values = new ContentValues(); - values.put(HostDatabase.FIELD_PORTFORWARD_HOSTID, hostId); - values.put(HostDatabase.FIELD_PORTFORWARD_NICKNAME, nickname); - values.put(HostDatabase.FIELD_PORTFORWARD_TYPE, type); - values.put(HostDatabase.FIELD_PORTFORWARD_SOURCEPORT, sourcePort); - values.put(HostDatabase.FIELD_PORTFORWARD_DESTADDR, destAddr); - values.put(HostDatabase.FIELD_PORTFORWARD_DESTPORT, destPort); - return values; - } -}
--- a/src/com/five_ten_sg/connectbot/bean/PubkeyBean.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,232 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.bean; - -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; - -import com.five_ten_sg.connectbot.util.PubkeyDatabase; -import com.five_ten_sg.connectbot.util.PubkeyUtils; -import android.content.ContentValues; - -/** - * @author Kenny Root - * - */ -public class PubkeyBean extends AbstractBean { - public static final String BEAN_NAME = "pubkey"; - - /* Database fields */ - private long id; - private String nickname; - private String type; - private byte[] privateKey; - private byte[] publicKey; - private boolean encrypted = false; - private boolean startup = false; - private boolean confirmUse = false; - private int lifetime = 0; - - /* Transient values */ - private transient boolean unlocked = false; - private transient Object unlockedPrivate = null; - private transient String description; - - @Override - public String getBeanName() { - return BEAN_NAME; - } - - public void setId(long id) { - this.id = id; - } - - public long getId() { - return id; - } - - public void setNickname(String nickname) { - this.nickname = nickname; - } - - public String getNickname() { - return nickname; - } - - public void setType(String type) { - this.type = type; - } - - public String getType() { - return type; - } - - public void setPrivateKey(byte[] privateKey) { - if (privateKey == null) - this.privateKey = null; - else - this.privateKey = privateKey.clone(); - } - - public byte[] getPrivateKey() { - if (privateKey == null) - return null; - else - return privateKey.clone(); - } - - public void setPublicKey(byte[] encoded) { - if (encoded == null) - publicKey = null; - else - publicKey = encoded.clone(); - } - - public byte[] getPublicKey() { - if (publicKey == null) - return null; - else - return publicKey.clone(); - } - - public void setEncrypted(boolean encrypted) { - this.encrypted = encrypted; - } - - public boolean isEncrypted() { - return encrypted; - } - - public void setStartup(boolean startup) { - this.startup = startup; - } - - public boolean isStartup() { - return startup; - } - - public void setConfirmUse(boolean confirmUse) { - this.confirmUse = confirmUse; - } - - public boolean isConfirmUse() { - return confirmUse; - } - - public void setLifetime(int lifetime) { - this.lifetime = lifetime; - } - - public int getLifetime() { - return lifetime; - } - - public void setUnlocked(boolean unlocked) { - this.unlocked = unlocked; - } - - public boolean isUnlocked() { - return unlocked; - } - - public void setUnlockedPrivate(Object unlockedPrivate) { - this.unlockedPrivate = unlockedPrivate; - } - - public Object getUnlockedPrivate() { - return unlockedPrivate; - } - - public String getDescription() { - if (description == null) { - final StringBuilder sb = new StringBuilder(); - - try { - final PublicKey pubKey = PubkeyUtils.decodePublic(publicKey, type); - - if (PubkeyDatabase.KEY_TYPE_RSA.equals(type)) { - int bits = ((RSAPublicKey) pubKey).getModulus().bitLength(); - sb.append("RSA "); - sb.append(bits); - sb.append("-bit"); - } - else if (PubkeyDatabase.KEY_TYPE_DSA.equals(type)) { - sb.append("DSA 1024-bit"); - } - else if (PubkeyDatabase.KEY_TYPE_EC.equals(type)) { - int bits = ((ECPublicKey) pubKey).getParams().getCurve().getField() - .getFieldSize(); - sb.append("EC "); - sb.append(bits); - sb.append("-bit"); - } - else { - sb.append("Unknown Key Type"); - } - } - catch (NoSuchAlgorithmException e) { - sb.append("Unknown Key Type"); - } - catch (InvalidKeySpecException e) { - sb.append("Unknown Key Type"); - } - - if (encrypted) sb.append(" (encrypted)"); - - description = sb.toString(); - } - - return description; - } - - /* (non-Javadoc) - * @see com.five_ten_sg.connectbot.bean.AbstractBean#getValues() - */ - @Override - public ContentValues getValues() { - ContentValues values = new ContentValues(); - values.put(PubkeyDatabase.FIELD_PUBKEY_NICKNAME, nickname); - values.put(PubkeyDatabase.FIELD_PUBKEY_TYPE, type); - values.put(PubkeyDatabase.FIELD_PUBKEY_PRIVATE, privateKey); - values.put(PubkeyDatabase.FIELD_PUBKEY_PUBLIC, publicKey); - values.put(PubkeyDatabase.FIELD_PUBKEY_ENCRYPTED, encrypted ? 1 : 0); - values.put(PubkeyDatabase.FIELD_PUBKEY_STARTUP, startup ? 1 : 0); - values.put(PubkeyDatabase.FIELD_PUBKEY_CONFIRMUSE, confirmUse ? 1 : 0); - values.put(PubkeyDatabase.FIELD_PUBKEY_LIFETIME, lifetime); - return values; - } - - public boolean changePassword(String oldPassword, String newPassword) throws Exception { - PrivateKey priv; - - try { - priv = PubkeyUtils.decodePrivate(getPrivateKey(), getType(), oldPassword); - } - catch (Exception e) { - return false; - } - - setPrivateKey(PubkeyUtils.getEncodedPrivate(priv, newPassword)); - setEncrypted(newPassword.length() > 0); - return true; - } -}
--- a/src/com/five_ten_sg/connectbot/bean/SelectionArea.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,198 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.bean; - -import de.mud.terminal.VDUBuffer; - -/** - * @author Kenny Root - * Keep track of a selection area for the terminal copying mechanism. - * If the orientation is flipped one way, swap the bottom and top or - * left and right to keep it in the correct orientation. - */ -public class SelectionArea { - private int top; - private int bottom; - private int left; - private int right; - private int maxColumns; - private int maxRows; - private boolean selectingOrigin; - - public SelectionArea() { - reset(); - } - - public final void reset() { - top = left = bottom = right = 0; - selectingOrigin = true; - } - - /** - * @param columns - * @param rows - */ - public void setBounds(int columns, int rows) { - maxColumns = columns - 1; - maxRows = rows - 1; - } - - private int checkBounds(int value, int max) { - if (value < 0) - return 0; - else if (value > max) - return max; - else - return value; - } - - public boolean isSelectingOrigin() { - return selectingOrigin; - } - - public void finishSelectingOrigin() { - selectingOrigin = false; - } - - public void decrementRow() { - if (selectingOrigin) - setTop(top - 1); - else - setBottom(bottom - 1); - } - - public void incrementRow() { - if (selectingOrigin) - setTop(top + 1); - else - setBottom(bottom + 1); - } - - public void setRow(int row) { - if (selectingOrigin) - setTop(row); - else - setBottom(row); - } - - private void setTop(int top) { - this.top = bottom = checkBounds(top, maxRows); - } - - public int getTop() { - return Math.min(top, bottom); - } - - private void setBottom(int bottom) { - this.bottom = checkBounds(bottom, maxRows); - } - - public int getBottom() { - return Math.max(top, bottom); - } - - public void decrementColumn() { - if (selectingOrigin) - setLeft(left - 1); - else - setRight(right - 1); - } - - public void incrementColumn() { - if (selectingOrigin) - setLeft(left + 1); - else - setRight(right + 1); - } - - public void setColumn(int column) { - if (selectingOrigin) - setLeft(column); - else - setRight(column); - } - - private void setLeft(int left) { - this.left = right = checkBounds(left, maxColumns); - } - - public int getLeft() { - return Math.min(left, right); - } - - private void setRight(int right) { - this.right = checkBounds(right, maxColumns); - } - - public int getRight() { - return Math.max(left, right); - } - - public String copyFrom(VDUBuffer vb) { - int size = (getRight() - getLeft() + 1) * (getBottom() - getTop() + 1); - StringBuffer buffer = new StringBuffer(size); - - for (int y = getTop(); y <= getBottom(); y++) { - int lastNonSpace = buffer.length(); - - for (int x = getLeft(); x <= getRight(); x++) { - // only copy printable chars - char c = vb.getChar(x, y); - - if (!Character.isDefined(c) || - (Character.isISOControl(c) && c != '\t')) - c = ' '; - - if (c != ' ') - lastNonSpace = buffer.length(); - - buffer.append(c); - } - - // Don't leave a bunch of spaces in our copy buffer. - if (buffer.length() > lastNonSpace) - buffer.delete(lastNonSpace + 1, buffer.length()); - - if (y != bottom) - buffer.append("\n"); - } - - return buffer.toString(); - } - - @Override - public String toString() { - StringBuilder buffer = new StringBuilder(); - buffer.append("SelectionArea[top="); - buffer.append(top); - buffer.append(", bottom="); - buffer.append(bottom); - buffer.append(", left="); - buffer.append(left); - buffer.append(", right="); - buffer.append(right); - buffer.append(", maxColumns="); - buffer.append(maxColumns); - buffer.append(", maxRows="); - buffer.append(maxRows); - buffer.append(", isSelectingOrigin="); - buffer.append(isSelectingOrigin()); - buffer.append("]"); - return buffer.toString(); - } -}
--- a/src/com/five_ten_sg/connectbot/service/AuthAgentService.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -package com.five_ten_sg.connectbot.service; - -import java.io.IOException; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.DSAPublicKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.service.TerminalManager.KeyHolder; -import android.app.Service; -import android.content.ComponentName; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -import com.madgag.ssh.android.authagent.AndroidAuthAgent; -import ch.ethz.ssh2.crypto.SecureRandomFix; -import ch.ethz.ssh2.signature.DSASHA1Verify; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; -import ch.ethz.ssh2.signature.RSASHA1Verify; - - -public class AuthAgentService extends Service { - private static final String TAG = "ConnectBot.AuthAgentService"; - protected TerminalManager manager; - final Lock lock = new ReentrantLock(); - final Condition managerReady = lock.newCondition(); - - private ServiceConnection connection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - Log.d(TAG, "Terminal manager available! Hurrah"); - manager = ((TerminalManager.TerminalBinder) service).getService(); - lock.lock(); - - try { - managerReady.signal(); - } - finally { - lock.unlock(); - } - } - public void onServiceDisconnected(ComponentName className) { - manager = null; - Log.d(TAG, "Terminal manager gone..."); - } - }; - - @Override - public IBinder onBind(Intent intent) { - Log.d(TAG, "onBind() called"); - bindService(new Intent(this, TerminalManager.class), connection, BIND_AUTO_CREATE); - return mBinder; - } - - private final AndroidAuthAgent.Stub mBinder = new AndroidAuthAgent.Stub() { - public Map getIdentities() throws RemoteException { - Log.d(TAG, "getIdentities() called"); - waitForTerminalManager(); - Log.d(TAG, "getIdentities() manager.loadedKeypairs : " + manager.loadedKeypairs); - return sshEncodedPubKeysFrom(manager.loadedKeypairs); - } - public byte[] sign(byte[] publicKey, byte[] data) throws RemoteException { - Log.d(TAG, "sign() called"); - waitForTerminalManager(); - KeyPair pair = keyPairFor(publicKey); - Log.d(TAG, "sign() - signing keypair found : " + pair); - - if (pair == null) { - return null; - } - - PrivateKey privKey = pair.getPrivate(); - - if (privKey instanceof RSAPrivateKey) { - return sshEncodedSignatureFor(data, (RSAPrivateKey) privKey); - } - else if (privKey instanceof DSAPrivateKey) { - return sshEncodedSignatureFor(data, (DSAPrivateKey) privKey); - } - else if (privKey instanceof ECPrivateKey) { - return sshEncodedSignatureFor(data, (ECPrivateKey) privKey); - } - - return null; - } - private void waitForTerminalManager() throws RemoteException { - lock.lock(); - - try { - while (manager == null) { - Log.d(TAG, "Waiting for TerminalManager..."); - managerReady.await(); - } - } - catch (InterruptedException e) { - throw new RemoteException(); - } - finally { - lock.unlock(); - } - - Log.d(TAG, "Got TerminalManager : " + manager); - } - private Map<String, byte[]> sshEncodedPubKeysFrom(Map<String, KeyHolder> keypairs) { - Map<String, byte[]> pubkeys = new HashMap<String, byte[]> (keypairs.size()); - - for (Entry<String, KeyHolder> entry : keypairs.entrySet()) { - byte[] encodedKey = sshEncodedPubKeyFrom(entry.getValue().pair); - - if (encodedKey != null) { - pubkeys.put(entry.getKey(), encodedKey); - } - } - - return pubkeys; - } - private byte[] sshEncodedPubKeyFrom(KeyPair pair) { - try { - PrivateKey privKey = pair.getPrivate(); - - if (privKey instanceof RSAPrivateKey) { - RSAPublicKey pubkey = (RSAPublicKey)pair.getPublic(); - return RSASHA1Verify.encodeSSHRSAPublicKey(pubkey); - } - else if (privKey instanceof DSAPrivateKey) { - DSAPublicKey pubkey = (DSAPublicKey)pair.getPublic(); - return DSASHA1Verify.encodeSSHDSAPublicKey(pubkey); - } - else if (privKey instanceof ECPrivateKey) { - ECPublicKey pubkey = (ECPublicKey) pair.getPublic(); - return ECDSASHA2Verify.encodeSSHECDSAPublicKey(pubkey); - } - } - catch (IOException e) { - Log.e(TAG, "Couldn't encode " + pair, e); - } - - return null; - } - private byte[] sshEncodedSignatureFor(byte[] data, RSAPrivateKey privKey) { - try { - byte[] signature = RSASHA1Verify.generateSignature(data, privKey); - return RSASHA1Verify.encodeSSHRSASignature(signature); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - private byte[] sshEncodedSignatureFor(byte[] data, DSAPrivateKey privKey) { - try { - byte[] signature = DSASHA1Verify.generateSignature(data, privKey, new SecureRandomFix()); - return DSASHA1Verify.encodeSSHDSASignature(signature); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - private byte[] sshEncodedSignatureFor(byte[] data, ECPrivateKey privKey) { - try { - byte[] signature = ECDSASHA2Verify.generateSignature(data, privKey); - return ECDSASHA2Verify.encodeSSHECDSASignature(signature, privKey.getParams()); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - private KeyPair keyPairFor(byte[] publicKey) { - String nickname = manager.getKeyNickname(publicKey); - - if (nickname == null) { - Log.w(TAG, "No key-pair found for public-key."); - return null; - } - - // check manager.loadedKeypairs.get(nickname).bean.isConfirmUse() and promptForPubkeyUse(nickname) ? - return manager.getKey(nickname); - } - }; -}
--- a/src/com/five_ten_sg/connectbot/service/BackupAgent.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2010 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.service; - -import java.io.IOException; - -import com.five_ten_sg.connectbot.util.HostDatabase; -import com.five_ten_sg.connectbot.util.PreferenceConstants; -import com.five_ten_sg.connectbot.util.PubkeyDatabase; -import android.app.backup.BackupAgentHelper; -import android.app.backup.BackupDataInput; -import android.app.backup.BackupDataOutput; -import android.app.backup.FileBackupHelper; -import android.app.backup.SharedPreferencesBackupHelper; -import android.os.ParcelFileDescriptor; -import android.util.Log; - -/** - * @author kroot - * - */ -public class BackupAgent extends BackupAgentHelper { - @Override - public void onCreate() { - Log.d("ConnectBot.BackupAgent", "onCreate called"); - SharedPreferencesBackupHelper prefs = new SharedPreferencesBackupHelper(this, getPackageName() + "_preferences"); - addHelper(PreferenceConstants.BACKUP_PREF_KEY, prefs); - FileBackupHelper hosts = new FileBackupHelper(this, "../databases/" + HostDatabase.DB_NAME); - addHelper(HostDatabase.DB_NAME, hosts); - FileBackupHelper pubkeys = new FileBackupHelper(this, "../databases/" + PubkeyDatabase.DB_NAME); - addHelper(PubkeyDatabase.DB_NAME, pubkeys); - } - - @Override - public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) throws IOException { - synchronized (HostDatabase.dbLock) { - super.onBackup(oldState, data, newState); - } - } - - @Override - public void onRestore(BackupDataInput data, int appVersionCode, - ParcelFileDescriptor newState) throws IOException { - Log.d("ConnectBot.BackupAgent", "onRestore called"); - - synchronized (HostDatabase.dbLock) { - Log.d("ConnectBot.BackupAgent", "onRestore in-lock"); - super.onRestore(data, appVersionCode, newState); - } - } -}
--- a/src/com/five_ten_sg/connectbot/service/BridgeDisconnectedListener.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.service; - -public interface BridgeDisconnectedListener { - public void onDisconnected(TerminalBridge bridge); -}
--- a/src/com/five_ten_sg/connectbot/service/ConnectionNotifier.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2010 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.service; - -import com.five_ten_sg.connectbot.ConsoleActivity; -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.util.HostDatabase; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.Color; - -/** - * @author Kenny Root - * - * Based on the concept from jasta's blog post. - */ -public class ConnectionNotifier { - private static final int ONLINE_NOTIFICATION = 1; - private static final int ACTIVITY_NOTIFICATION = 2; - - protected NotificationManager getNotificationManager(Context context) { - return (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); - } - - protected Notification newNotification(Context context) { - Notification notification = new Notification(); - notification.icon = R.drawable.notification_icon; - notification.when = System.currentTimeMillis(); - return notification; - } - - protected Notification newActivityNotification(Context context, HostBean host) { - Notification notification = newNotification(context); - Resources res = context.getResources(); - String contentText = res.getString( - R.string.notification_text, host.getNickname()); - Intent notificationIntent = new Intent(context, ConsoleActivity.class); - notificationIntent.setAction(Intent.ACTION_VIEW); - notificationIntent.setData(host.getUri()); - PendingIntent contentIntent = PendingIntent.getActivity(context, 0, - notificationIntent, 0); - notification.setLatestEventInfo(context, res.getString(R.string.app_name), contentText, contentIntent); - notification.flags = Notification.FLAG_AUTO_CANCEL; - notification.flags |= Notification.DEFAULT_LIGHTS; - - if (HostDatabase.COLOR_RED.equals(host.getColor())) - notification.ledARGB = Color.RED; - else if (HostDatabase.COLOR_GREEN.equals(host.getColor())) - notification.ledARGB = Color.GREEN; - else if (HostDatabase.COLOR_BLUE.equals(host.getColor())) - notification.ledARGB = Color.BLUE; - else - notification.ledARGB = Color.WHITE; - - notification.ledOnMS = 300; - notification.ledOffMS = 1000; - notification.flags |= Notification.FLAG_SHOW_LIGHTS; - return notification; - } - - protected Notification newRunningNotification(Context context) { - Notification notification = newNotification(context); - notification.flags = Notification.FLAG_ONGOING_EVENT - | Notification.FLAG_NO_CLEAR; - notification.when = 0; - notification.contentIntent = PendingIntent.getActivity(context, - ONLINE_NOTIFICATION, - new Intent(context, ConsoleActivity.class), 0); - Resources res = context.getResources(); - notification.setLatestEventInfo(context, - res.getString(R.string.app_name), - res.getString(R.string.app_is_running), - notification.contentIntent); - return notification; - } - - public void showActivityNotification(Service context, HostBean host) { - getNotificationManager(context).notify(ACTIVITY_NOTIFICATION, newActivityNotification(context, host)); - } - - public void hideActivityNotification(Service context) { - getNotificationManager(context).cancel(ACTIVITY_NOTIFICATION); - } - - public void showRunningNotification(Service context) { - context.startForeground(ONLINE_NOTIFICATION, newRunningNotification(context)); - } - - public void hideRunningNotification(Service context) { - context.stopForeground(true); - } -}
--- a/src/com/five_ten_sg/connectbot/service/ConnectivityReceiver.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -/** - * - */ -package com.five_ten_sg.connectbot.service; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.NetworkInfo.State; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.WifiLock; -import android.util.Log; - -/** - * @author kroot - * - */ -public class ConnectivityReceiver extends BroadcastReceiver { - private static final String TAG = "ConnectBot.ConnectivityManager"; - - private boolean mIsConnected = false; - - final private TerminalManager mTerminalManager; - - final private WifiLock mWifiLock; - - private int mNetworkRef = 0; - - private boolean mLockingWifi; - - private Object[] mLock = new Object[0]; - - public ConnectivityReceiver(TerminalManager manager, boolean lockingWifi) { - mTerminalManager = manager; - final ConnectivityManager cm = - (ConnectivityManager) manager.getSystemService(Context.CONNECTIVITY_SERVICE); - final WifiManager wm = (WifiManager) manager.getSystemService(Context.WIFI_SERVICE); - mWifiLock = wm.createWifiLock(TAG); - final NetworkInfo info = cm.getActiveNetworkInfo(); - - if (info != null) { - mIsConnected = (info.getState() == State.CONNECTED); - } - - mLockingWifi = lockingWifi; - final IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - manager.registerReceiver(this, filter); - } - - /* (non-Javadoc) - * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent) - */ - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - - if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { - Log.w(TAG, "onReceived() called: " + intent); - return; - } - - boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); - boolean isFailover = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false); - Log.d(TAG, "onReceived() called; noConnectivity? " + noConnectivity + "; isFailover? " + isFailover); - - if (noConnectivity && !isFailover && mIsConnected) { - mIsConnected = false; - mTerminalManager.onConnectivityLost(); - } - else if (!mIsConnected) { - NetworkInfo info = (NetworkInfo) intent.getExtras() - .get(ConnectivityManager.EXTRA_NETWORK_INFO); - - if (mIsConnected = (info.getState() == State.CONNECTED)) { - mTerminalManager.onConnectivityRestored(); - } - } - } - - /** - * - */ - public void cleanup() { - if (mWifiLock.isHeld()) - mWifiLock.release(); - - mTerminalManager.unregisterReceiver(this); - } - - /** - * Increase the number of things using the network. Acquire a Wi-Fi lock - * if necessary. - */ - public void incRef() { - synchronized (mLock) { - mNetworkRef += 1; - acquireWifiLockIfNecessaryLocked(); - } - } - - /** - * Decrease the number of things using the network. Release the Wi-Fi lock - * if necessary. - */ - public void decRef() { - synchronized (mLock) { - mNetworkRef -= 1; - releaseWifiLockIfNecessaryLocked(); - } - } - - /** - * @param mLockingWifi - */ - public void setWantWifiLock(boolean lockingWifi) { - synchronized (mLock) { - mLockingWifi = lockingWifi; - - if (mLockingWifi) { - acquireWifiLockIfNecessaryLocked(); - } - else { - releaseWifiLockIfNecessaryLocked(); - } - } - } - - private void acquireWifiLockIfNecessaryLocked() { - if (mLockingWifi && mNetworkRef > 0 && !mWifiLock.isHeld()) { - mWifiLock.acquire(); - } - } - - private void releaseWifiLockIfNecessaryLocked() { - if (mNetworkRef == 0 && mWifiLock.isHeld()) { - mWifiLock.release(); - } - } - - /** - * @return whether we're connected to a network - */ - public boolean isConnected() { - return mIsConnected; - } -}
--- a/src/com/five_ten_sg/connectbot/service/FontSizeChangedListener.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.service; - -/** - * @author Kenny Root - * - */ -public interface FontSizeChangedListener { - - /** - * @param size - * new font size - */ - void onFontSizeChanged(float size); -}
--- a/src/com/five_ten_sg/connectbot/service/PromptHelper.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.service; - -import java.util.concurrent.Semaphore; - -import android.os.Handler; -import android.os.Message; - -/** - * Helps provide a relay for prompts and responses between a possible user - * interface and some underlying service. - * - * @author jsharkey - */ -public class PromptHelper { - private final Object tag; - - private Handler handler = null; - - private Semaphore promptToken; - private Semaphore promptResponse; - - public String promptInstructions = null; - public String promptHint = null; - public Object promptRequested = null; - public boolean passwordRequested = true; - - private Object response = null; - - public PromptHelper(Object tag) { - this.tag = tag; - // Threads must acquire this before they can send a prompt. - promptToken = new Semaphore(1); - // Responses will release this semaphore. - promptResponse = new Semaphore(0); - } - - - /** - * Register a user interface handler, if available. - */ - public void setHandler(Handler handler) { - this.handler = handler; - } - - /** - * Set an incoming value from an above user interface. Will automatically - * notify any waiting requests. - */ - public void setResponse(Object value) { - response = value; - promptRequested = null; - promptInstructions = null; - promptHint = null; - promptResponse.release(); - } - - /** - * Return the internal response value just before erasing and returning it. - */ - protected Object popResponse() { - Object value = response; - response = null; - return value; - } - - - /** - * Request a prompt response from parent. This is a blocking call until user - * interface returns a value. - * Only one thread can call this at a time. cancelPrompt() will force this to - * immediately return. - */ - private Object requestPrompt(String instructions, String hint, Object type) throws InterruptedException { - Object response = null; - promptToken.acquire(); - - try { - promptInstructions = instructions; - promptHint = hint; - promptRequested = type; - - // notify any parent watching for live events - if (handler != null) - Message.obtain(handler, -1, tag).sendToTarget(); - - // acquire lock until user passes back value - promptResponse.acquire(); - response = popResponse(); - } - finally { - promptToken.release(); - } - - return response; - } - - /** - * Request a string response from parent. This is a blocking call until user - * interface returns a value. - * @param hint prompt hint for user to answer - * @return string user has entered - */ - public String requestStringPrompt(String instructions, String hint) { - String value = null; - passwordRequested = false; - - try { - value = (String)this.requestPrompt(instructions, hint, String.class); - } - catch (Exception e) { - } - - return value; - } - - /** - * Request a password response from parent. This is a blocking call until user - * interface returns a value. - * @param hint prompt hint for user to answer - * @return string user has entered - */ - public String requestPasswordPrompt(String instructions, String hint) { - String value = null; - passwordRequested = true; - - try { - value = (String)this.requestPrompt(instructions, hint, String.class); - } - catch (Exception e) { - } - - return value; - } - - /** - * Request a boolean response from parent. This is a blocking call until user - * interface returns a value. - * @param hint prompt hint for user to answer - * @return choice user has made (yes/no) - */ - public Boolean requestBooleanPrompt(String instructions, String hint) { - Boolean value = null; - - try { - value = (Boolean)this.requestPrompt(instructions, hint, Boolean.class); - } - catch (Exception e) { - } - - return value; - } - - /** - * Cancel an in-progress prompt. - */ - public void cancelPrompt() { - if (!promptToken.tryAcquire()) { - // A thread has the token, so try to interrupt it - response = null; - promptResponse.release(); - } - else { - // No threads have acquired the token - promptToken.release(); - } - } -}
--- a/src/com/five_ten_sg/connectbot/service/Relay.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.service; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CodingErrorAction; -import java.util.Timer; -import java.util.TimerTask; - -import org.apache.harmony.niochar.charset.additional.IBM437; - -import com.five_ten_sg.connectbot.transport.AbsTransport; -import android.graphics.Paint; -import android.text.AndroidCharacter; -import android.util.Log; -import de.mud.terminal.vt320; - -/** - * @author Kenny Root - */ -public class Relay implements Runnable { - private static final String TAG = "ConnectBot.Relay"; - - private static final int BUFFER_SIZE = 4096; - - private TerminalBridge bridge; - - private Charset currentCharset; - private CharsetDecoder decoder; - - private AbsTransport transport; - - private vt320 buffer; - - private ByteBuffer byteBuffer; - private CharBuffer charBuffer; - - private byte[] byteArray; - private char[] charArray; - - private void eastAsianWidthMeasure(char[] charArray, int start, int end, - byte[] wideAttribute, Paint paint, int charWidth) { - AndroidCharacter.getEastAsianWidths(charArray, start, end - start, wideAttribute); - } - - public Relay(TerminalBridge bridge, AbsTransport transport, vt320 buffer, String encoding) { - setCharset(encoding); - this.bridge = bridge; - this.transport = transport; - this.buffer = buffer; - } - - public void setCharset(String encoding) { - Log.d("ConnectBot.Relay", "changing charset to " + encoding); - Charset charset; - - if (encoding.equals("CP437")) - charset = new IBM437("IBM437", - new String[] { "IBM437", "CP437" }); - else - charset = Charset.forName(encoding); - - if (charset == currentCharset || charset == null) - return; - - CharsetDecoder newCd = charset.newDecoder(); - newCd.onUnmappableCharacter(CodingErrorAction.REPLACE); - newCd.onMalformedInput(CodingErrorAction.REPLACE); - currentCharset = charset; - - synchronized (this) { - decoder = newCd; - } - } - - public Charset getCharset() { - return currentCharset; - } - - public void run() { - byteBuffer = ByteBuffer.allocate(BUFFER_SIZE); - charBuffer = CharBuffer.allocate(BUFFER_SIZE); - /* for East Asian character widths */ - byte[] wideAttribute = new byte[BUFFER_SIZE]; - byteArray = byteBuffer.array(); - charArray = charBuffer.array(); - CoderResult result; - int bytesRead = 0; - byteBuffer.limit(0); - int bytesToRead; - int offset; - int charWidth; - Timer timer = new Timer("relay.blocker", true); - TimerTask task = null; - - try { - while (true) { - charWidth = bridge.charWidth; - bytesToRead = byteBuffer.capacity() - byteBuffer.limit(); - offset = byteBuffer.arrayOffset() + byteBuffer.limit(); - - if (transport.willBlock()) { - task = new TimerTask() { - public void run() { - buffer.testChanged(); - } - }; - timer.schedule(task, 10); // 10 ms delay - } - - bytesRead = transport.read(byteArray, offset, bytesToRead); - - if (task != null) { - task.cancel(); - task = null; - } - - if (bytesRead > 0) { - byteBuffer.limit(byteBuffer.limit() + bytesRead); - - synchronized (this) { - result = decoder.decode(byteBuffer, charBuffer, false); - } - - if (result.isUnderflow() && - byteBuffer.limit() == byteBuffer.capacity()) { - byteBuffer.compact(); - byteBuffer.limit(byteBuffer.position()); - byteBuffer.position(0); - } - - offset = charBuffer.position(); - eastAsianWidthMeasure(charArray, 0, offset, wideAttribute, bridge.defaultPaint, charWidth); - buffer.putString(charArray, wideAttribute, 0, charBuffer.position()); - bridge.propagateConsoleText(charArray, charBuffer.position()); - charBuffer.clear(); - bridge.redraw(); - } - } - } - catch (IOException e) { - Log.e(TAG, "Problem while handling incoming data in relay thread", e); - } - - timer.cancel(); - } -}
--- a/src/com/five_ten_sg/connectbot/service/TerminalBridge.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1412 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.service; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.Charset; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.TerminalView; -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.bean.PortForwardBean; -import com.five_ten_sg.connectbot.bean.SelectionArea; -import com.five_ten_sg.connectbot.transport.AbsTransport; -import com.five_ten_sg.connectbot.transport.TransportFactory; -import com.five_ten_sg.connectbot.util.HostDatabase; -import com.five_ten_sg.connectbot.util.PreferenceConstants; -import com.five_ten_sg.connectbot.util.StringPickerDialog; -import android.app.AlertDialog; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.FontMetrics; -import android.graphics.Typeface; -import android.os.Binder; -import android.os.Environment; -import android.text.ClipboardManager; -import android.text.Editable; -import android.text.method.CharacterPickerDialog; -import android.util.FloatMath; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.widget.AdapterView; -import android.widget.Button; -import de.mud.terminal.VDUBuffer; -import de.mud.terminal.VDUDisplay; -import de.mud.terminal.vt320; - - -/** - * Provides a bridge between a MUD terminal buffer and a possible TerminalView. - * This separation allows us to keep the TerminalBridge running in a background - * service. A TerminalView shares down a bitmap that we can use for rendering - * when available. - * - * This class also provides SSH hostkey verification prompting, and password - * prompting. - */ -@SuppressWarnings("deprecation") // for ClipboardManager -public class TerminalBridge implements VDUDisplay { - public final static String TAG = "ConnectBot.TerminalBridge"; - - private final static float FONT_SIZE_FACTOR = 1.1f; - - public Integer[] color; - - public int defaultFg = HostDatabase.DEFAULT_FG_COLOR; - public int defaultBg = HostDatabase.DEFAULT_BG_COLOR; - - protected final TerminalManager manager; - public final HostBean host; - public final String homeDirectory; - - AbsTransport transport; - - final Paint defaultPaint; - - private Relay relay; - - private String emulation; // aka answerback string, aka terminal type - - public Bitmap bitmap = null; - public vt320 buffer = null; - - public TerminalView parent = null; - private final Canvas canvas = new Canvas(); - - private boolean disconnected = false; - private boolean awaitingClose = false; - - private boolean forcedSize = false; - private int columns; - private int rows; - - public TerminalMonitor monitor = null; - private TerminalKeyListener keyListener = null; - - private boolean selectingForCopy = false; - private final SelectionArea selectionArea; - - // TODO add support for the new clipboard API - private ClipboardManager clipboard; - - public int charWidth = -1; - public int charHeight = -1; - private int charTop = -1; - private float fontSize = -1; - - private final List<FontSizeChangedListener> fontSizeChangedListeners; - - private final List<String> localOutput; - - /** - * Flag indicating if we should perform a full-screen redraw during our next - * rendering pass. - */ - private boolean fullRedraw = false; - - public PromptHelper promptHelper; - - protected BridgeDisconnectedListener disconnectListener = null; - - /** - * Create a new terminal bridge suitable for unit testing. - */ - public TerminalBridge() { - buffer = new vt320() { - @Override - public void write(byte[] b) {} - @Override - public void write(int b) {} - @Override - public void sendTelnetCommand(byte cmd) {} - @Override - public void setWindowSize(int c, int r) {} - @Override - public void debug(String s) {} - }; - emulation = null; - manager = null; - host = null; - homeDirectory = null; - defaultPaint = new Paint(); - selectionArea = new SelectionArea(); - localOutput = new LinkedList<String>(); - fontSizeChangedListeners = new LinkedList<FontSizeChangedListener>(); - transport = null; - keyListener = new TerminalKeyListener(manager, this, buffer, null); - monitor = null; - } - - /** - * Create new terminal bridge with following parameters. - */ - public TerminalBridge(final TerminalManager manager, final HostBean host, final String homeDirectory) throws IOException { - this.manager = manager; - this.host = host; - this.homeDirectory = homeDirectory; - emulation = host.getHostEmulation(); - - if ((emulation == null) || (emulation.length() == 0)) emulation = manager.getEmulation(); - - // create prompt helper to relay password and hostkey requests up to gui - promptHelper = new PromptHelper(this); - // create our default paint - defaultPaint = new Paint(); - defaultPaint.setAntiAlias(true); - defaultPaint.setTypeface(Typeface.MONOSPACE); - defaultPaint.setFakeBoldText(true); // more readable? - localOutput = new LinkedList<String>(); - fontSizeChangedListeners = new LinkedList<FontSizeChangedListener>(); - setMyFontSize(); - resetColors(); - selectionArea = new SelectionArea(); - } - - public PromptHelper getPromptHelper() { - return promptHelper; - } - - /** - * Spawn thread to open connection and start login process. - */ - protected void startConnection() { - transport = TransportFactory.getTransport(host.getProtocol()); - transport.setLinks(manager, this, homeDirectory, host, emulation); - buffer = transport.getTransportBuffer(); - keyListener = transport.getTerminalKeyListener(); - String monitor_init = host.getMonitor(); - - if ((monitor_init != null) && (monitor_init.length() > 0)) { - monitor = new TerminalMonitor(manager, buffer, parent, host, monitor_init); - } - - transport.setCompression(host.getCompression()); - transport.setHttpproxy(host.getHttpproxy()); - transport.setUseAuthAgent(host.getUseAuthAgent()); - - if (transport.canForwardPorts()) { - for (PortForwardBean portForward : manager.hostdb.getPortForwardsForHost(host)) - transport.addPortForward(portForward); - } - - outputLine(manager.res.getString(R.string.terminal_connecting, host.getHostname(), host.getPort(), host.getProtocol())); - Thread connectionThread = new Thread(new Runnable() { - public void run() { - transport.connect(); - } - }); - connectionThread.setName("Connection"); - connectionThread.setDaemon(true); - connectionThread.start(); - } - - /** - * Handle challenges from keyboard-interactive authentication mode. - */ - public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) { - String[] responses = new String[numPrompts]; - - for (int i = 0; i < numPrompts; i++) { - // request response from user for each prompt - responses[i] = promptHelper.requestPasswordPrompt(instruction, prompt[i]); - } - - return responses; - } - - /** - * @return charset in use by bridge - */ - public Charset getCharset() { - if (relay != null) return relay.getCharset(); - - return keyListener.getCharset(); - } - - /** - * Sets the encoding used by the terminal. If the connection is live, - * then the character set is changed for the next read. - * @param encoding the canonical name of the character encoding - */ - public void setCharset(String encoding) { - if (relay != null) relay.setCharset(encoding); - - keyListener.setCharset(encoding); - } - - /** - * Convenience method for writing a line into the underlying MUD buffer. - * Should never be called once the session is established. - */ - public final void outputLine(String line) { - if (transport != null && transport.isSessionOpen()) - Log.e(TAG, "Session established, cannot use outputLine!", new IOException("outputLine call traceback")); - - synchronized (localOutput) { - final String s = line + "\r\n"; - localOutput.add(s); - buffer.putString(s); - // For accessibility - final char[] charArray = s.toCharArray(); - propagateConsoleText(charArray, charArray.length); - } - } - - /** - * Inject a specific string into this terminal. Used for post-login strings - * and pasting clipboard. - */ - public void injectString(final String string) { - if (string == null || string.length() == 0) - return; - - Thread injectStringThread = new Thread(new Runnable() { - public void run() { - try { - transport.write(string.getBytes(host.getEncoding())); - } - catch (Exception e) { - Log.e(TAG, "Couldn't inject string to remote host: ", e); - } - } - }); - injectStringThread.setName("InjectString"); - injectStringThread.start(); - } - - /** - * Internal method to request actual PTY terminal once we've finished - * authentication. If called before authenticated, it will just fail. - */ - public void onConnected() { - disconnected = false; - buffer.reset(); - buffer.setAnswerBack(emulation); - localOutput.clear(); // We no longer need our local output. - - if (HostDatabase.DELKEY_BACKSPACE.equals(host.getDelKey())) - buffer.setBackspace(vt320.DELETE_IS_BACKSPACE); - else - buffer.setBackspace(vt320.DELETE_IS_DEL); - - // create thread to relay incoming connection data to buffer - // only if needed by the transport - if (transport.needsRelay()) { - relay = new Relay(this, transport, buffer, host.getEncoding()); - Thread relayThread = new Thread(relay); - relayThread.setDaemon(true); - relayThread.setName("Relay"); - relayThread.start(); - } - - // get proper font size - setMyFontSize(); - // finally send any post-login string, if requested - injectString(host.getPostLogin()); - } - - private void setMyFontSize() { - if ((parent != null) && (host.getFixedSize())) { - resizeComputed(host.getFixedWidth(), host.getFixedHeight(), parent.getWidth(), parent.getHeight()); - } - else { - setFontSize(host.getFontSize()); - } - } - - /** - * @return whether a session is open or not - */ - public boolean isSessionOpen() { - if (transport != null) return transport.isSessionOpen(); - - return false; - } - - public void setOnDisconnectedListener(BridgeDisconnectedListener disconnectListener) { - this.disconnectListener = disconnectListener; - } - - /** - * Force disconnection of this terminal bridge. - */ - public void dispatchDisconnect(boolean immediate) { - // We don't need to do this multiple times. - synchronized (this) { - if (disconnected && !immediate) return; - - disconnected = true; - } - - // Cancel any pending prompts. - promptHelper.cancelPrompt(); - // disconnection request hangs if we havent really connected to a host yet - // temporary fix is to just spawn disconnection into a thread - Thread disconnectThread = new Thread(new Runnable() { - public void run() { - if (transport != null && transport.isConnected()) - transport.close(); - } - }); - disconnectThread.setName("Disconnect"); - disconnectThread.start(); - - if (immediate) { - awaitingClose = true; - - if (disconnectListener != null) - disconnectListener.onDisconnected(TerminalBridge.this); - } - else { - final String line = manager.res.getString(R.string.alert_disconnect_msg); - buffer.putString("\r\n" + line + "\r\n"); - - if (host.getStayConnected()) { - manager.requestReconnect(this); - return; - } - - Thread disconnectPromptThread = new Thread(new Runnable() { - public void run() { - Boolean result = promptHelper.requestBooleanPrompt(null, - manager.res.getString(R.string.prompt_host_disconnected)); - - if (result == null || result.booleanValue()) { - awaitingClose = true; - - // Tell the TerminalManager that we can be destroyed now. - if (disconnectListener != null) - disconnectListener.onDisconnected(TerminalBridge.this); - } - } - }); - disconnectPromptThread.setName("DisconnectPrompt"); - disconnectPromptThread.setDaemon(true); - disconnectPromptThread.start(); - } - - // close the monitor - if (monitor != null) monitor.Disconnect(); - - monitor = null; - } - - public void setSelectingForCopy(boolean selectingForCopy) { - this.selectingForCopy = selectingForCopy; - } - - public boolean isSelectingForCopy() { - return selectingForCopy; - } - - public SelectionArea getSelectionArea() { - return selectionArea; - } - - public synchronized void tryKeyVibrate() { - manager.tryKeyVibrate(); - } - - /** - * Request a different font size. Will make call to parentChanged() to make - * sure we resize PTY if needed. - */ - final void setFontSize(float size) { - if (size <= 0.0) size = 12.0f; - - size = (float)(int)((size * 10.0f) + 0.5f) / 10.0f; - defaultPaint.setTextSize(size); - fontSize = size; - // read new metrics to get exact pixel dimensions - FontMetrics fm = defaultPaint.getFontMetrics(); - charTop = (int)FloatMath.ceil(fm.top); - float[] widths = new float[1]; - defaultPaint.getTextWidths("X", widths); - charWidth = (int)FloatMath.ceil(widths[0]); - charHeight = (int)FloatMath.ceil(fm.descent - fm.top); - - // refresh any bitmap with new font size - if (parent != null) parentChanged(parent); - - synchronized(fontSizeChangedListeners) { - for (FontSizeChangedListener ofscl : fontSizeChangedListeners) - ofscl.onFontSizeChanged(size); - } - - host.setFontSize(size); - manager.hostdb.updateFontSize(host); - } - - /** - * Add an {@link FontSizeChangedListener} to the list of listeners for this - * bridge. - * - * @param listener - * listener to add - */ - public void addFontSizeChangedListener(FontSizeChangedListener listener) { - synchronized(fontSizeChangedListeners) { - fontSizeChangedListeners.add(listener); - } - } - - /** - * Remove an {@link FontSizeChangedListener} from the list of listeners for - * this bridge. - * - * @param listener - */ - public void removeFontSizeChangedListener(FontSizeChangedListener listener) { - synchronized(fontSizeChangedListeners) { - fontSizeChangedListeners.remove(listener); - } - } - - /** - * Something changed in our parent {@link TerminalView}, maybe it's a new - * parent, or maybe it's an updated font size. We should recalculate - * terminal size information and request a PTY resize. - */ - - public final synchronized void parentChanged(TerminalView parent) { - if (manager != null && !manager.isResizeAllowed()) { - Log.d(TAG, "Resize is not allowed now"); - return; - } - - this.parent = parent; - final int width = parent.getWidth(); - final int height = parent.getHeight(); - - // Something has gone wrong with our layout; we're 0 width or height! - if (width <= 0 || height <= 0) - return; - - clipboard = (ClipboardManager) parent.getContext().getSystemService(Context.CLIPBOARD_SERVICE); - keyListener.setClipboardManager(clipboard); - - if (!forcedSize) { - // recalculate buffer size - int newColumns, newRows; - newColumns = width / charWidth; - newRows = height / charHeight; - - // If nothing has changed in the terminal dimensions and not an intial - // draw then don't blow away scroll regions and such. - if (newColumns == columns && newRows == rows) - return; - - columns = newColumns; - rows = newRows; - } - - // reallocate new bitmap if needed - boolean newBitmap = (bitmap == null); - - if (bitmap != null) - newBitmap = (bitmap.getWidth() != width || bitmap.getHeight() != height); - - if (newBitmap) { - discardBitmap(); - bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); - canvas.setBitmap(bitmap); - } - - // clear out any old buffer information - defaultPaint.setColor(Color.BLACK); - canvas.drawPaint(defaultPaint); - - // Stroke the border of the terminal if the size is being forced; - if (forcedSize) { - int borderX = (columns * charWidth) + 1; - int borderY = (rows * charHeight) + 1; - defaultPaint.setColor(Color.GRAY); - defaultPaint.setStrokeWidth(0.0f); - - if (width >= borderX) - canvas.drawLine(borderX, 0, borderX, borderY + 1, defaultPaint); - - if (height >= borderY) - canvas.drawLine(0, borderY, borderX + 1, borderY, defaultPaint); - } - - try { - // request a terminal pty resize - if (buffer != null) { - synchronized (buffer) { - buffer.setScreenSize(columns, rows, true); - } - } - - if (transport != null) - transport.setDimensions(columns, rows, width, height); - } - catch (Exception e) { - Log.e(TAG, "Problem while trying to resize screen or PTY", e); - } - - // redraw local output if we don't have a session to receive our resize request - if (transport == null) { - synchronized (localOutput) { - buffer.reset(); - - for (String line : localOutput) - buffer.putString(line); - } - } - - // force full redraw with new buffer size - fullRedraw = true; - redraw(); - - // initial sequence from - // transport.connect() - // bridge.onConnected() - // bridge.setMyFontSize() - // bridge.resizeComputed() - // bridge.setFontSize() - // bridge.parentChanged() here is on the wrong thread - try { - parent.notifyUser(String.format("%d x %d", columns, rows)); - } - catch (Exception e) { - Log.e(TAG, "Problem while trying to notify user", e); - } - - Log.i(TAG, String.format("parentChanged() now width=%d, height=%d", columns, rows)); - } - - /** - * Somehow our parent {@link TerminalView} was destroyed. Now we don't need - * to redraw anywhere, and we can recycle our internal bitmap. - */ - - public synchronized void parentDestroyed() { - parent = null; - discardBitmap(); - } - - private void discardBitmap() { - if (bitmap != null) - bitmap.recycle(); - - bitmap = null; - } - - public void propagateConsoleText(char[] rawText, int length) { - if (parent != null) { - parent.propagateConsoleText(rawText, length); - } - } - - public void onDraw() { - int fg, bg; - - synchronized (buffer) { - boolean entireDirty = buffer.update[0] || fullRedraw; - boolean isWideCharacter = false; - - // walk through all lines in the buffer - for (int l = 0; l < buffer.height; l++) { - // check if this line is dirty and needs to be repainted - // also check for entire-buffer dirty flags - if (!entireDirty && !buffer.update[l + 1]) continue; - - // reset dirty flag for this line - buffer.update[l + 1] = false; - - // walk through all characters in this line - for (int c = 0; c < buffer.width; c++) { - int addr = 0; - int currAttr = buffer.charAttributes[buffer.windowBase + l][c]; - { - int fgcolor = defaultFg; - - // check if foreground color attribute is set - if ((currAttr & VDUBuffer.COLOR_FG) != 0) - fgcolor = ((currAttr & VDUBuffer.COLOR_FG) >> VDUBuffer.COLOR_FG_SHIFT) - 1; - - if (fgcolor < 8 && (currAttr & VDUBuffer.BOLD) != 0) - fg = color[fgcolor + 8]; - else - fg = color[fgcolor]; - } - - // check if background color attribute is set - if ((currAttr & VDUBuffer.COLOR_BG) != 0) - bg = color[((currAttr & VDUBuffer.COLOR_BG) >> VDUBuffer.COLOR_BG_SHIFT) - 1]; - else - bg = color[defaultBg]; - - // support character inversion by swapping background and foreground color - if ((currAttr & VDUBuffer.INVERT) != 0) { - int swapc = bg; - bg = fg; - fg = swapc; - } - - // set underlined attributes if requested - defaultPaint.setUnderlineText((currAttr & VDUBuffer.UNDERLINE) != 0); - isWideCharacter = (currAttr & VDUBuffer.FULLWIDTH) != 0; - - if (isWideCharacter) - addr++; - else { - // determine the amount of continuous characters with the same settings and print them all at once - while (c + addr < buffer.width - && buffer.charAttributes[buffer.windowBase + l][c + addr] == currAttr) { - addr++; - } - } - - // Save the current clip region - canvas.save(Canvas.CLIP_SAVE_FLAG); - // clear this dirty area with background color - defaultPaint.setColor(bg); - - if (isWideCharacter) { - canvas.clipRect(c * charWidth, - l * charHeight, - (c + 2) * charWidth, - (l + 1) * charHeight); - } - else { - canvas.clipRect(c * charWidth, - l * charHeight, - (c + addr) * charWidth, - (l + 1) * charHeight); - } - - canvas.drawPaint(defaultPaint); - // write the text string starting at 'c' for 'addr' number of characters - defaultPaint.setColor(fg); - - if ((currAttr & VDUBuffer.INVISIBLE) == 0) - canvas.drawText(buffer.charArray[buffer.windowBase + l], c, - addr, c * charWidth, (l * charHeight) - charTop, - defaultPaint); - - // Restore the previous clip region - canvas.restore(); - // advance to the next text block with different characteristics - c += addr - 1; - - if (isWideCharacter) - c++; - } - } - - // reset entire-buffer flags - buffer.update[0] = false; - } - - fullRedraw = false; - } - - public void redraw() { - if (parent != null) - parent.postInvalidate(); - } - - // We don't have a scroll bar. - public void updateScrollBar() { - } - - /** - * Resize terminal to fit [rows]x[cols] in screen of size [width]x[height] - * @param rows - * @param cols - * @param width - * @param height - */ - - public synchronized void resizeComputed(int cols, int rows, int width, int height) { - float size = 8.0f; - float step = 8.0f; - float limit = 0.125f; - int direction; - boolean fixed = true; - - if (!fixed) { - while ((direction = fontSizeCompare(size, cols, rows, width, height)) < 0) - size += step; - - if (direction == 0) { - Log.d("fontsize", String.format("Found match at %f", size)); - return; - } - - step /= 2.0f; - size -= step; - - while ((direction = fontSizeCompare(size, cols, rows, width, height)) != 0 - && step >= limit) { - step /= 2.0f; - - if (direction > 0) { - size -= step; - } - else { - size += step; - } - } - - if (direction > 0) size -= step; - } - - this.columns = cols; - this.rows = rows; - forcedSize = true; - - if (fixed) setFontSize(host.getFontSize()); - else setFontSize(size); - } - - private int fontSizeCompare(float size, int cols, int rows, int width, int height) { - // read new metrics to get exact pixel dimensions - defaultPaint.setTextSize(size); - FontMetrics fm = defaultPaint.getFontMetrics(); - float[] widths = new float[1]; - defaultPaint.getTextWidths("X", widths); - int termWidth = (int)widths[0] * cols; - int termHeight = (int)FloatMath.ceil(fm.descent - fm.top) * rows; - Log.d("fontsize", String.format("font size %f resulted in %d x %d", size, termWidth, termHeight)); - - // Check to see if it fits in resolution specified. - if (termWidth > width || termHeight > height) - return 1; - - if (termWidth == width || termHeight == height) - return 0; - - return -1; - } - - /** - * @return whether underlying transport can forward ports - */ - public boolean canFowardPorts() { - return transport.canForwardPorts(); - } - - /** - * Adds the {@link PortForwardBean} to the list. - * @param portForward the port forward bean to add - * @return true on successful addition - */ - public boolean addPortForward(PortForwardBean portForward) { - return transport.addPortForward(portForward); - } - - /** - * Removes the {@link PortForwardBean} from the list. - * @param portForward the port forward bean to remove - * @return true on successful removal - */ - public boolean removePortForward(PortForwardBean portForward) { - return transport.removePortForward(portForward); - } - - /** - * @return the list of port forwards - */ - public List<PortForwardBean> getPortForwards() { - return transport.getPortForwards(); - } - - /** - * Enables a port forward member. After calling this method, the port forward should - * be operational. - * @param portForward member of our current port forwards list to enable - * @return true on successful port forward setup - */ - public boolean enablePortForward(PortForwardBean portForward) { - if (!transport.isConnected()) { - Log.i(TAG, "Attempt to enable port forward while not connected"); - return false; - } - - return transport.enablePortForward(portForward); - } - - /** - * Disables a port forward member. After calling this method, the port forward should - * be non-functioning. - * @param portForward member of our current port forwards list to enable - * @return true on successful port forward tear-down - */ - public boolean disablePortForward(PortForwardBean portForward) { - if (!transport.isConnected()) { - Log.i(TAG, "Attempt to disable port forward while not connected"); - return false; - } - - return transport.disablePortForward(portForward); - } - - /** - * @return whether underlying transport can transfer files - */ - public boolean canTransferFiles() { - return transport.canTransferFiles(); - } - - /** - * Downloads the specified remote file to the local connectbot folder. - * @return true on success, false on failure - */ - public boolean downloadFile(String remoteFile, String localFolder) { - return transport.downloadFile(remoteFile, localFolder); - } - - /** - * Uploads the specified local file to the remote host's default directory. - * @return true on success, false on failure - */ - public boolean uploadFile(String localFile, String remoteFolder, String remoteFile, String mode) { - if (mode == null) - mode = "0600"; - - return transport.uploadFile(localFile, remoteFolder, remoteFile, mode); - } - - /** - * @return whether the TerminalBridge should close - */ - public boolean isAwaitingClose() { - return awaitingClose; - } - - /** - * @return whether this connection had started and subsequently disconnected - */ - public boolean isDisconnected() { - return disconnected; - } - - /* (non-Javadoc) - * @see de.mud.terminal.VDUDisplay#setColor(byte, byte, byte, byte) - */ - public void setColor(int index, int red, int green, int blue) { - // Don't allow the system colors to be overwritten for now. May violate specs. - if (index < color.length && index >= 16) - color[index] = 0xff000000 | red << 16 | green << 8 | blue; - } - - public final void resetColors() { - int[] defaults = manager.hostdb.getDefaultColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME); - defaultFg = defaults[0]; - defaultBg = defaults[1]; - color = manager.hostdb.getColorsForScheme(HostDatabase.DEFAULT_COLOR_SCHEME); - } - - private static Pattern urlPattern = null; - - /** - * @return - */ - public List<String> scanForURLs() { - Set<String> urls = new LinkedHashSet<String>(); - - if (urlPattern == null) { - // based on http://www.ietf.org/rfc/rfc2396.txt - String scheme = "[A-Za-z][-+.0-9A-Za-z]*"; - String unreserved = "[-._~0-9A-Za-z]"; - String pctEncoded = "%[0-9A-Fa-f]{2}"; - String subDelims = "[!$&'()*+,;:=]"; - String userinfo = "(?:" + unreserved + "|" + pctEncoded + "|" + subDelims + "|:)*"; - String h16 = "[0-9A-Fa-f]{1,4}"; - String decOctet = "(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; - String ipv4address = decOctet + "\\." + decOctet + "\\." + decOctet + "\\." + decOctet; - String ls32 = "(?:" + h16 + ":" + h16 + "|" + ipv4address + ")"; - String ipv6address = "(?:(?:" + h16 + "){6}" + ls32 + ")"; - String ipvfuture = "v[0-9A-Fa-f]+.(?:" + unreserved + "|" + subDelims + "|:)+"; - String ipLiteral = "\\[(?:" + ipv6address + "|" + ipvfuture + ")\\]"; - String regName = "(?:" + unreserved + "|" + pctEncoded + "|" + subDelims + ")*"; - String host = "(?:" + ipLiteral + "|" + ipv4address + "|" + regName + ")"; - String port = "[0-9]*"; - String authority = "(?:" + userinfo + "@)?" + host + "(?::" + port + ")?"; - String pchar = "(?:" + unreserved + "|" + pctEncoded + "|" + subDelims + "|@)"; - String segment = pchar + "*"; - String pathAbempty = "(?:/" + segment + ")*"; - String segmentNz = pchar + "+"; - String pathAbsolute = "/(?:" + segmentNz + "(?:/" + segment + ")*)?"; - String pathRootless = segmentNz + "(?:/" + segment + ")*"; - String hierPart = "(?://" + authority + pathAbempty + "|" + pathAbsolute + "|" + pathRootless + ")"; - String query = "(?:" + pchar + "|/|\\?)*"; - String fragment = "(?:" + pchar + "|/|\\?)*"; - String uriRegex = scheme + ":" + hierPart + "(?:" + query + ")?(?:#" + fragment + ")?"; - urlPattern = Pattern.compile(uriRegex); - } - - char[] visibleBuffer = new char[buffer.height * buffer.width]; - - for (int l = 0; l < buffer.height; l++) - System.arraycopy(buffer.charArray[buffer.windowBase + l], 0, - visibleBuffer, l * buffer.width, buffer.width); - - Matcher urlMatcher = urlPattern.matcher(new String(visibleBuffer)); - - while (urlMatcher.find()) - urls.add(urlMatcher.group()); - - return (new LinkedList<String> (urls)); - } - - /** - * @return - */ - public boolean isUsingNetwork() { - return transport.usesNetwork(); - } - - /** - * @return - */ - public TerminalKeyListener getKeyHandler() { - return keyListener; - } - - /** - * - */ - public void resetScrollPosition() { - // if we're in scrollback, scroll to bottom of window on input - if (buffer.windowBase != buffer.screenBase) - buffer.setWindowBase(buffer.screenBase); - } - - /** - * - */ - public void increaseFontSize() { - setFontSize(fontSize * FONT_SIZE_FACTOR); - } - - /** - * - */ - public void decreaseFontSize() { - setFontSize(fontSize / FONT_SIZE_FACTOR); - } - - /** - * Auto-size window back to default - */ - public void resetSize(TerminalView parent) { - this.forcedSize = false; - setMyFontSize(); - } - - /** - * Create a screenshot of the current view - */ - public void captureScreen() { - String msg; - File dir, path; - boolean success = true; - Bitmap screenshot = this.bitmap; - - if (manager == null || parent == null || screenshot == null) - return; - - SimpleDateFormat s = new SimpleDateFormat("yyyyMMdd_HHmmss"); - String date = s.format(new Date()); - String pref_path = manager.prefs.getString(PreferenceConstants.SCREEN_CAPTURE_FOLDER, ""); - File default_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); - - if (pref_path.equals("")) - dir = default_path; - else - dir = new File(pref_path); - - path = new File(dir, "vx-" + date + ".png"); - - try { - dir.mkdirs(); - FileOutputStream out = new FileOutputStream(path); - screenshot.compress(Bitmap.CompressFormat.PNG, 90, out); - out.close(); - } - catch (Exception e) { - e.printStackTrace(); - success = false; - } - - if (success) { - msg = manager.getResources().getString(R.string.screenshot_saved_as) + " " + path; - - if (manager.prefs.getBoolean(PreferenceConstants.SCREEN_CAPTURE_POPUP, true)) { - new AlertDialog.Builder(parent.getContext()) - .setTitle(R.string.screenshot_success_title) - .setMessage(msg) - .setPositiveButton(R.string.button_close, null) - .show(); - } - } - else { - msg = manager.getResources().getString(R.string.screenshot_not_saved_as) + " " + path; - new AlertDialog.Builder(parent.getContext()) - .setTitle(R.string.screenshot_error_title) - .setMessage(msg) - .setNegativeButton(R.string.button_close, null) - .show(); - } - - return; - } - - /** - * Show change font size dialog - */ - public boolean showFontSizeDialog() { - final String pickerString = "+-"; - CharSequence str = ""; - Editable content = Editable.Factory.getInstance().newEditable(str); - - if (parent == null) - return false; - - CharacterPickerDialog cpd = new CharacterPickerDialog(parent.getContext(), - parent, content, pickerString, true) { - private void changeFontSize(CharSequence result) { - if (result.equals("+")) - increaseFontSize(); - else if (result.equals("-")) - decreaseFontSize(); - } - @Override - public void onItemClick(AdapterView p, View v, int pos, long id) { - final String result = String.valueOf(pickerString.charAt(pos)); - changeFontSize(result); - } - @Override - public void onClick(View v) { - if (v instanceof Button) { - final CharSequence result = ((Button) v).getText(); - - if (result.equals("")) - dismiss(); - else - changeFontSize(result); - } - } - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_DOWN) { - if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) - dismiss(); - - return keyListener.onKey(parent, event.getKeyCode(), event); - } - - return true; - } - }; - cpd.show(); - return true; - } - - /** - * Show arrows dialog - */ - public boolean showArrowsDialog() { - final String []pickerStrings = {"←", "→", "↑", "↓", "tab", "ins", "del", "ret"}; - final HashMap<String, Integer> keymap = new HashMap<String, Integer>(); - keymap.put("←", vt320.KEY_LEFT); - keymap.put("→", vt320.KEY_RIGHT); - keymap.put("↑", vt320.KEY_UP); - keymap.put("↓", vt320.KEY_DOWN); - keymap.put("tab", vt320.KEY_TAB); - keymap.put("ins", vt320.KEY_INSERT); - keymap.put("del", vt320.KEY_DELETE); - keymap.put("ret", vt320.KEY_ENTER); - CharSequence str = ""; - Editable content = Editable.Factory.getInstance().newEditable(str); - - if (parent == null) return false; - - StringPickerDialog cpd = new StringPickerDialog(parent.getContext(), - parent, content, - pickerStrings, true) { - private void buttonPressed(String s) { - if (keymap.containsKey(s)) buffer.keyPressed(keymap.get(s), ' ', 0); - } - @Override - public void onItemClick(AdapterView p, View v, int pos, long id) { - buttonPressed(pickerStrings[pos]); - } - @Override - public void onClick(View v) { - if (v instanceof Button) { - final String s = ((Button) v).getText().toString(); - - if (s.equals("")) dismiss(); - else buttonPressed(s); - } - } - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_DOWN) { - if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) - dismiss(); - - return keyListener.onKey(parent, event.getKeyCode(), event); - } - - return true; - } - }; - cpd.show(); - return true; - } - - - /** - * CTRL dialog - */ - private String getCtrlString() { - final String defaultSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - String set = manager.prefs.getString(PreferenceConstants.CTRL_STRING, defaultSet); - - if (set == null || set.equals("")) { - set = defaultSet; - } - - return set; - } - - public boolean showCtrlDialog() { - CharSequence str = ""; - Editable content = Editable.Factory.getInstance().newEditable(str); - - if (parent == null) - return false; - - CharacterPickerDialog cpd = new CharacterPickerDialog(parent.getContext(), - parent, content, getCtrlString(), true) { - private void buttonPressed(CharSequence result) { - int code = result.toString().toUpperCase().charAt(0) - 64; - - if (code > 0 && code < 80) { - try { - transport.write(code); - } - catch (IOException e) { - Log.d(TAG, "Error writing CTRL+" + result.toString().toUpperCase().charAt(0)); - } - } - - dismiss(); - } - @Override - public void onItemClick(AdapterView p, View v, int pos, long id) { - final String result = String.valueOf(getCtrlString().charAt(pos)); - buttonPressed(result); - } - @Override - public void onClick(View v) { - if (v instanceof Button) { - final CharSequence result = ((Button) v).getText(); - - if (result.equals("")) - dismiss(); - else - buttonPressed(result); - } - } - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_DOWN) { - if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) - dismiss(); - - return keyListener.onKey(parent, event.getKeyCode(), event); - } - - return true; - } - }; - cpd.show(); - return true; - } - - /** - * Function keys dialog - */ - public boolean showFKeysDialog() { - final String []pickerStrings = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", "←", "→", "↑", "↓", "tab", "ins", "del", "ret"}; - final HashMap<String, Integer> keymap = new HashMap<String, Integer>(); - keymap.put("F1", vt320.KEY_F1); - keymap.put("F2", vt320.KEY_F2); - keymap.put("F3", vt320.KEY_F3); - keymap.put("F4", vt320.KEY_F4); - keymap.put("F5", vt320.KEY_F5); - keymap.put("F6", vt320.KEY_F6); - keymap.put("F7", vt320.KEY_F7); - keymap.put("F8", vt320.KEY_F8); - keymap.put("F9", vt320.KEY_F9); - keymap.put("F10", vt320.KEY_F10); - keymap.put("F11", vt320.KEY_F11); - keymap.put("F12", vt320.KEY_F12); - keymap.put("F13", vt320.KEY_F13); - keymap.put("F14", vt320.KEY_F14); - keymap.put("F15", vt320.KEY_F15); - keymap.put("F16", vt320.KEY_F16); - keymap.put("F17", vt320.KEY_F17); - keymap.put("F18", vt320.KEY_F18); - keymap.put("F19", vt320.KEY_F19); - keymap.put("F20", vt320.KEY_F20); - keymap.put("F21", vt320.KEY_F21); - keymap.put("F22", vt320.KEY_F22); - keymap.put("F23", vt320.KEY_F23); - keymap.put("F24", vt320.KEY_F24); - keymap.put("←", vt320.KEY_LEFT); - keymap.put("→", vt320.KEY_RIGHT); - keymap.put("↑", vt320.KEY_UP); - keymap.put("↓", vt320.KEY_DOWN); - keymap.put("tab", vt320.KEY_TAB); - keymap.put("ins", vt320.KEY_INSERT); - keymap.put("del", vt320.KEY_DELETE); - keymap.put("ret", vt320.KEY_ENTER); - CharSequence str = ""; - Editable content = Editable.Factory.getInstance().newEditable(str); - - if (parent == null) return false; - - StringPickerDialog cpd = new StringPickerDialog(parent.getContext(), - parent, content, - pickerStrings, true) { - private void buttonPressed(String s) { - if (keymap.containsKey(s)) buffer.keyPressed(keymap.get(s), ' ', 0); - - dismiss(); - } - @Override - public void onItemClick(AdapterView p, View v, int pos, long id) { - buttonPressed(pickerStrings[pos]); - } - @Override - public void onClick(View v) { - if (v instanceof Button) { - final String s = ((Button) v).getText().toString(); - - if (s.equals("")) dismiss(); - else buttonPressed(s); - } - } - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_DOWN) { - if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) - dismiss(); - - return keyListener.onKey(parent, event.getKeyCode(), event); - } - - return true; - } - }; - cpd.show(); - return true; - } - - private String getPickerString() { - final String defaultSet = "~\\^()[]{}<>|/:_;,.!@#$%&*?\"'-+="; - String set = manager.prefs.getString(PreferenceConstants.PICKER_STRING, defaultSet); - - if (set == null || set.equals("")) { - set = defaultSet; - } - - return set; - } - - public boolean showCharPickerDialog() { - CharSequence str = ""; - Editable content = Editable.Factory.getInstance().newEditable(str); - - if (parent == null || !transport.isAuthenticated()) - return false; - - CharacterPickerDialog cpd = new CharacterPickerDialog(parent.getContext(), - parent, content, getPickerString(), true) { - private void writeChar(CharSequence result) { - try { - if (transport.isAuthenticated()) - transport.write(result.toString().getBytes(getCharset().name())); - } - catch (IOException e) { - Log.e(TAG, "Problem with the CharacterPickerDialog", e); - } - - if (!manager.prefs.getBoolean(PreferenceConstants.PICKER_KEEP_OPEN, false)) - dismiss(); - } - @Override - public void onItemClick(AdapterView p, View v, int pos, long id) { - String result = String.valueOf(getPickerString().charAt(pos)); - writeChar(result); - } - @Override - public void onClick(View v) { - if (v instanceof Button) { - CharSequence result = ((Button) v).getText(); - - if (result.equals("")) - dismiss(); - else - writeChar(result); - } - } - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - int keyCode = event.getKeyCode(); - - if (event.getAction() == KeyEvent.ACTION_DOWN) { - // close window if SYM or BACK keys are pressed - if (keyListener.isSymKey(keyCode) || - keyCode == KeyEvent.KEYCODE_BACK) { - dismiss(); - return true; - } - } - - return super.dispatchKeyEvent(event); - } - }; - cpd.show(); - return true; - } -}
--- a/src/com/five_ten_sg/connectbot/service/TerminalKeyListener.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1217 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2010 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.five_ten_sg.connectbot.service; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.lang.ref.WeakReference; -import java.util.List; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.TerminalView; -import com.five_ten_sg.connectbot.bean.SelectionArea; -import com.five_ten_sg.connectbot.util.PreferenceConstants; -import android.app.Dialog; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.content.res.Configuration; -import android.net.Uri; -import android.preference.PreferenceManager; -import android.text.ClipboardManager; -import android.util.Log; -import android.view.Gravity; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnKeyListener; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.ListView; -import android.widget.TextView; -import de.mud.terminal.VDUBuffer; -import de.mud.terminal.vt320; - -/** - * @author kenny - * - */ -@SuppressWarnings("deprecation") // for ClipboardManager -public class TerminalKeyListener implements OnKeyListener, OnSharedPreferenceChangeListener { - private static final String TAG = "ConnectBot.OnKeyListener"; - - public final static int META_CTRL_ON = 0x01; - public final static int META_CTRL_LOCK = 0x02; - public final static int META_ALT_ON = 0x04; - public final static int META_ALT_LOCK = 0x08; - public final static int META_SHIFT_ON = 0x10; - public final static int META_SHIFT_LOCK = 0x20; - public final static int META_SLASH = 0x40; - public final static int META_TAB = 0x80; - - // The bit mask of momentary and lock states for each - public final static int META_CTRL_MASK = META_CTRL_ON | META_CTRL_LOCK; - public final static int META_ALT_MASK = META_ALT_ON | META_ALT_LOCK; - public final static int META_SHIFT_MASK = META_SHIFT_ON | META_SHIFT_LOCK; - - // backport constants from api level 11 - public final static int KEYCODE_ESCAPE = 111; - public final static int HC_META_CTRL_ON = 4096; - public final static int KEYCODE_PAGE_UP = 92; - public final static int KEYCODE_PAGE_DOWN = 93; - - // All the transient key codes - public final static int META_TRANSIENT = META_CTRL_ON | META_ALT_ON - | META_SHIFT_ON; - - protected final TerminalManager manager; - protected final TerminalBridge bridge; - protected final vt320 buffer; - protected String encoding; - - protected String keymode = null; - protected boolean hardKeyboard = false; - protected boolean hardKeyboardHidden; - protected String customKeyboard = null; - - protected int metaState = 0; - protected int mDeadKey = 0; - - // TODO add support for the new API. - private ClipboardManager clipboard = null; - private boolean selectingForCopy = false; - private final SelectionArea selectionArea; - protected final SharedPreferences prefs; - - - public TerminalKeyListener(TerminalManager manager, - TerminalBridge bridge, - vt320 buffer, - String encoding) { - this.manager = manager; - this.bridge = bridge; - this.buffer = buffer; - this.encoding = encoding; - selectionArea = new SelectionArea(); - prefs = PreferenceManager.getDefaultSharedPreferences(manager); - prefs.registerOnSharedPreferenceChangeListener(this); - hardKeyboard = (manager.res.getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY); - hardKeyboardHidden = manager.hardKeyboardHidden; - updateKeymode(); - updateCustomKeymap(); - } - - public void sendEscape() { - buffer.keyPressed(vt320.KEY_ESCAPE, ' ', getStateForBuffer()); - } - - protected void sendEncoded(String s) { - byte [] b = null; - - try { - b = s.getBytes(encoding); - } - catch (UnsupportedEncodingException e) { - } - - if (b != null) buffer.write(b); - } - - /** - * Handle onKey() events coming down from a {@link com.five_ten_sg.connectbot.TerminalView} above us. - * Modify the keys to make more sense to a host then pass it to the vt320. - */ - public boolean onKey(View v, int keyCode, KeyEvent event) { - try { - int repeat = event.getRepeatCount(); - - // skip keys if we aren't connected yet or have been disconnected - if (bridge.isDisconnected()) return false; - - // short cuts can see repeat counts and key up/down - if (handleShortcuts(v, keyCode, event, repeat, (event.getAction() == KeyEvent.ACTION_DOWN))) return true; - - // Ignore all key-up events except for the special keys - if (event.getAction() == KeyEvent.ACTION_UP) { - // There's nothing else here for virtual keyboard users. - if (!hardKeyboard || hardKeyboardHidden) return false; - - // if keycode debugging enabled, log and print the pressed key - if (prefs.getBoolean(PreferenceConstants.DEBUG_KEYCODES, false)) { - String keyCodeString = String.format(": %d", keyCode); - String toastText = v.getContext().getString(R.string.keycode_pressed) + keyCodeString; - Log.d(TAG, toastText); - } - - if (fullKeyboard()) { - switch (keyCode) { - case KeyEvent.KEYCODE_CTRL_LEFT: - case KeyEvent.KEYCODE_CTRL_RIGHT: - metaKeyUp(META_CTRL_ON); - return true; - - case KeyEvent.KEYCODE_ALT_LEFT: - case KeyEvent.KEYCODE_ALT_RIGHT: - metaKeyUp(META_ALT_ON); - return true; - - case KeyEvent.KEYCODE_SHIFT_LEFT: - case KeyEvent.KEYCODE_SHIFT_RIGHT: - metaKeyUp(META_SHIFT_ON); - return true; - - default: - } - } - else if (PreferenceConstants.KEYMODE_RIGHT.equals(keymode)) { - if (keyCode == KeyEvent.KEYCODE_ALT_RIGHT - && (metaState & META_SLASH) != 0) { - metaState &= ~(META_SLASH | META_TRANSIENT); - buffer.write('/'); - return true; - } - else if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT - && (metaState & META_TAB) != 0) { - metaState &= ~(META_TAB | META_TRANSIENT); - buffer.keyPressed(vt320.KEY_TAB, ' ', getStateForBuffer()); - return true; - } - } - else if (PreferenceConstants.KEYMODE_LEFT.equals(keymode)) { - if (keyCode == KeyEvent.KEYCODE_ALT_LEFT - && (metaState & META_SLASH) != 0) { - metaState &= ~(META_SLASH | META_TRANSIENT); - buffer.write('/'); - return true; - } - else if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT - && (metaState & META_TAB) != 0) { - metaState &= ~(META_TAB | META_TRANSIENT); - buffer.keyPressed(vt320.KEY_TAB, ' ', getStateForBuffer()); - return true; - } - } - - return false; - } - - bridge.resetScrollPosition(); - - if (keyCode == KeyEvent.KEYCODE_UNKNOWN && - event.getAction() == KeyEvent.ACTION_MULTIPLE) { - sendEncoded(event.getCharacters()); - return true; - } - - int curMetaState = event.getMetaState(); - final int orgMetaState = curMetaState; - - if ((metaState & META_SHIFT_MASK) != 0) { - curMetaState |= KeyEvent.META_SHIFT_ON; - } - - if ((metaState & META_ALT_MASK) != 0) { - curMetaState |= KeyEvent.META_ALT_ON; - } - - int uchar = event.getUnicodeChar(curMetaState); - - // no hard keyboard? ALT-k should pass through to below - if ((orgMetaState & KeyEvent.META_ALT_ON) != 0 && - (!hardKeyboard || hardKeyboardHidden)) { - uchar = 0; - } - - if ((uchar & KeyCharacterMap.COMBINING_ACCENT) != 0) { - mDeadKey = uchar & KeyCharacterMap.COMBINING_ACCENT_MASK; - return true; - } - - if (mDeadKey != 0 && uchar != 0) { - uchar = KeyCharacterMap.getDeadChar(mDeadKey, uchar); - mDeadKey = 0; - } - - // handle customized keymaps - if (customKeymapAction(v, keyCode, event)) - return true; - - if (v != null) { - //Show up the CharacterPickerDialog when the SYM key is pressed - if ((isSymKey(keyCode) || uchar == KeyCharacterMap.PICKER_DIALOG_INPUT)) { - bridge.showCharPickerDialog(); - - if (metaState == 4) { // reset fn-key state - metaState = 0; - bridge.redraw(); - } - - return true; - } - else if (keyCode == KeyEvent.KEYCODE_SEARCH) { - //Show up the URL scan dialog when the search key is pressed - urlScan(v); - return true; - } - } - - // otherwise pass through to existing session - // print normal keys - if (uchar > 0x00 && keyCode != KeyEvent.KEYCODE_ENTER) { - metaState &= ~(META_SLASH | META_TAB); - // Remove shift and alt modifiers - final int lastMetaState = metaState; - metaState &= ~(META_SHIFT_ON | META_ALT_ON); - - if (metaState != lastMetaState) { - bridge.redraw(); - } - - if ((metaState & META_CTRL_MASK) != 0) { - metaState &= ~META_CTRL_ON; - bridge.redraw(); - - // If there is no hard keyboard or there is a hard keyboard currently hidden, - // CTRL-1 through CTRL-9 will send F1 through F9 - if ((!hardKeyboard || hardKeyboardHidden) && sendFunctionKey(keyCode)) - return true; - - uchar = keyAsControl(uchar); - } - - // handle pressing f-keys - if ((hardKeyboard && !hardKeyboardHidden) - && (curMetaState & KeyEvent.META_ALT_ON) != 0 - && (curMetaState & KeyEvent.META_SHIFT_ON) != 0 - && sendFunctionKey(keyCode)) - return true; - - if (uchar < 0x80) - buffer.write(uchar); - else - sendEncoded(new String(Character.toChars(uchar))); - - return true; - } - - // send ctrl and meta-keys as appropriate - if (!hardKeyboard || hardKeyboardHidden) { - int k = event.getUnicodeChar(0); - int k0 = k; - boolean sendCtrl = false; - boolean sendMeta = false; - - if (k != 0) { - if ((orgMetaState & HC_META_CTRL_ON) != 0) { - k = keyAsControl(k); - if (k != k0) sendCtrl = true; - // send F1-F10 via CTRL-1 through CTRL-0 - if (!sendCtrl && sendFunctionKey(keyCode)) - return true; - } - else if ((orgMetaState & KeyEvent.META_ALT_ON) != 0) { - sendMeta = true; - sendEscape(); - } - - if (sendMeta || sendCtrl) { - buffer.write(k); - return true; - } - } - } - - // handle meta and f-keys for full hardware keyboard - if (hardKeyboard && !hardKeyboardHidden && fullKeyboard()) { - int k = event.getUnicodeChar(orgMetaState & KeyEvent.META_SHIFT_ON); - int k0 = k; - - if (k != 0) { - if ((orgMetaState & HC_META_CTRL_ON) != 0) { - k = keyAsControl(k); - if (k != k0) buffer.write(k); - return true; - } - else if ((orgMetaState & KeyEvent.META_ALT_ON) != 0) { - sendEscape(); - buffer.write(k); - return true; - } - } - - if (sendFullSpecialKey(keyCode)) - return true; - } - - // try handling keymode shortcuts - if (hardKeyboard && !hardKeyboardHidden && (repeat == 0)) { - if (PreferenceConstants.KEYMODE_RIGHT.equals(keymode)) { - switch (keyCode) { - case KeyEvent.KEYCODE_ALT_RIGHT: - metaState |= META_SLASH; - return true; - - case KeyEvent.KEYCODE_SHIFT_RIGHT: - metaState |= META_TAB; - return true; - - case KeyEvent.KEYCODE_SHIFT_LEFT: - metaPress(META_SHIFT_ON); - return true; - - case KeyEvent.KEYCODE_ALT_LEFT: - metaPress(META_ALT_ON); - return true; - } - } - else if (PreferenceConstants.KEYMODE_LEFT.equals(keymode)) { - switch (keyCode) { - case KeyEvent.KEYCODE_ALT_LEFT: - metaState |= META_SLASH; - return true; - - case KeyEvent.KEYCODE_SHIFT_LEFT: - metaState |= META_TAB; - return true; - - case KeyEvent.KEYCODE_SHIFT_RIGHT: - metaPress(META_SHIFT_ON); - return true; - - case KeyEvent.KEYCODE_ALT_RIGHT: - metaPress(META_ALT_ON); - return true; - } - } - else { - switch (keyCode) { - case KeyEvent.KEYCODE_ALT_RIGHT: - case KeyEvent.KEYCODE_ALT_LEFT: - metaPress(META_ALT_ON); - return true; - - case KeyEvent.KEYCODE_SHIFT_LEFT: - case KeyEvent.KEYCODE_SHIFT_RIGHT: - metaPress(META_SHIFT_ON); - return true; - } - } - - // Handle hardware CTRL keys - if (keyCode == KeyEvent.KEYCODE_CTRL_LEFT || - keyCode == KeyEvent.KEYCODE_CTRL_RIGHT) { - ctrlKeySpecial(); - return true; - } - } - - // look for special chars - switch (keyCode) { - case KeyEvent.KEYCODE_ESCAPE: - sendEscape(); - return true; - - case KeyEvent.KEYCODE_TAB: - buffer.keyPressed(vt320.KEY_TAB, ' ', getStateForBuffer()); - return true; - - case KeyEvent.KEYCODE_PAGE_DOWN: - buffer.keyPressed(vt320.KEY_PAGE_DOWN, ' ', getStateForBuffer()); - metaState &= ~META_TRANSIENT; - bridge.tryKeyVibrate(); - return true; - - case KeyEvent.KEYCODE_PAGE_UP: - buffer.keyPressed(vt320.KEY_PAGE_UP, ' ', getStateForBuffer()); - metaState &= ~META_TRANSIENT; - bridge.tryKeyVibrate(); - return true; - - case KeyEvent.KEYCODE_MOVE_HOME: - buffer.keyPressed(vt320.KEY_HOME, ' ', getStateForBuffer()); - metaState &= ~META_TRANSIENT; - bridge.tryKeyVibrate(); - return true; - - case KeyEvent.KEYCODE_MOVE_END: - buffer.keyPressed(vt320.KEY_END, ' ', getStateForBuffer()); - metaState &= ~META_TRANSIENT; - bridge.tryKeyVibrate(); - return true; - - case KeyEvent.KEYCODE_DEL: - if ((metaState & META_ALT_MASK) != 0) { - buffer.keyPressed(vt320.KEY_INSERT, ' ', getStateForBuffer()); - } - else { - buffer.keyPressed(vt320.KEY_BACK_SPACE, ' ', getStateForBuffer()); - } - - metaState &= ~META_TRANSIENT; - return true; - - case KeyEvent.KEYCODE_ENTER: - buffer.keyPressed(vt320.KEY_ENTER, ' ', getStateForBuffer()); - metaState &= ~META_TRANSIENT; - return true; - - case KeyEvent.KEYCODE_DPAD_LEFT: - if (selectingForCopy) { - selectionArea.decrementColumn(); - bridge.redraw(); - } - else { - if ((metaState & META_ALT_MASK) != 0) { - buffer.keyPressed(vt320.KEY_HOME, ' ', getStateForBuffer()); - } - else { - buffer.keyPressed(vt320.KEY_LEFT, ' ', getStateForBuffer()); - } - - metaState &= ~META_TRANSIENT; - bridge.tryKeyVibrate(); - } - - return true; - - case KeyEvent.KEYCODE_DPAD_UP: - if (selectingForCopy) { - selectionArea.decrementRow(); - bridge.redraw(); - } - else { - if ((metaState & META_ALT_MASK) != 0) { - buffer.keyPressed(vt320.KEY_PAGE_UP, ' ', getStateForBuffer()); - } - else { - buffer.keyPressed(vt320.KEY_UP, ' ', getStateForBuffer()); - } - - metaState &= ~META_TRANSIENT; - bridge.tryKeyVibrate(); - } - - return true; - - case KeyEvent.KEYCODE_DPAD_DOWN: - if (selectingForCopy) { - selectionArea.incrementRow(); - bridge.redraw(); - } - else { - if ((metaState & META_ALT_MASK) != 0) { - buffer.keyPressed(vt320.KEY_PAGE_DOWN, ' ', getStateForBuffer()); - } - else { - buffer.keyPressed(vt320.KEY_DOWN, ' ', getStateForBuffer()); - } - - metaState &= ~META_TRANSIENT; - bridge.tryKeyVibrate(); - } - - return true; - - case KeyEvent.KEYCODE_DPAD_RIGHT: - if (selectingForCopy) { - selectionArea.incrementColumn(); - bridge.redraw(); - } - else { - if ((metaState & META_ALT_MASK) != 0) { - buffer.keyPressed(vt320.KEY_END, ' ', getStateForBuffer()); - } - else { - buffer.keyPressed(vt320.KEY_RIGHT, ' ', getStateForBuffer()); - } - - metaState &= ~META_TRANSIENT; - bridge.tryKeyVibrate(); - } - - return true; - - case KeyEvent.KEYCODE_DPAD_CENTER: - ctrlKeySpecial(); - return true; - } - } - catch (NullPointerException npe) { - Log.d(TAG, "Input before connection established ignored."); - return true; - } - - return false; - } - - private boolean handleShortcuts(View v, int keyCode, KeyEvent event, int repeat, boolean down) { - String hwbuttonShortcut; - - switch (keyCode) { - case KeyEvent.KEYCODE_CAMERA: - // check to see which shortcut the camera button triggers - hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.CAMERA, - PreferenceConstants.HWBUTTON_SCREEN_CAPTURE); - return (handleShortcut(v, hwbuttonShortcut, repeat, down)); - - case KeyEvent.KEYCODE_VOLUME_UP: - // check to see which shortcut the volume button triggers - hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.VOLUP, - PreferenceConstants.HWBUTTON_FUNCTION_KEYS); - return (handleShortcut(v, hwbuttonShortcut, repeat, down)); - - case KeyEvent.KEYCODE_VOLUME_DOWN: - // check to see which shortcut the camera button triggers - hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.VOLDN, - PreferenceConstants.HWBUTTON_TAB); - return (handleShortcut(v, hwbuttonShortcut, repeat, down)); - - case KeyEvent.KEYCODE_SEARCH: - // check to see which shortcut the search button triggers - hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.SEARCH, - PreferenceConstants.HWBUTTON_ESC); - return (handleShortcut(v, hwbuttonShortcut, repeat, down)); - - case KeyEvent.KEYCODE_BUTTON_L2: - // check to see which shortcut the ptt button triggers - hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.PTT, - PreferenceConstants.HWBUTTON_MONITOR); - return (handleShortcut(v, hwbuttonShortcut, repeat, down)); - - default: return false; - } - } - - private boolean handleShortcut(View v, String shortcut, int repeat, boolean down) { - if (PreferenceConstants.HWBUTTON_DECREASE_FONTSIZE.equals(shortcut)) { - if (!down) return false; - - bridge.decreaseFontSize(); - } - else if (PreferenceConstants.HWBUTTON_INCREASE_FONTSIZE.equals(shortcut)) { - if (!down) return false; - - bridge.increaseFontSize(); - } - else if (PreferenceConstants.HWBUTTON_FUNCTION_KEYS.equals(shortcut)) { - if (repeat > 0) return false; - - if (!down) return false; - - bridge.showFKeysDialog(); - } - else if (PreferenceConstants.HWBUTTON_MONITOR.equals(shortcut)) { - if (repeat > 0) return false; - - buffer.monitorKey(down); - } - else if (PreferenceConstants.HWBUTTON_SCREEN_CAPTURE.equals(shortcut)) { - if (repeat > 0) return false; - - if (!down) return false; - - bridge.captureScreen(); - } - else if (PreferenceConstants.HWBUTTON_CTRL.equals(shortcut)) { - if (!down) return false; - - showMetakeyToast(v, PreferenceConstants.HWBUTTON_CTRL); - metaPress(META_CTRL_ON); - } - else if (PreferenceConstants.HWBUTTON_TAB.equals(shortcut)) { - if (!down) return false; - - buffer.keyPressed(vt320.KEY_TAB, ' ', getStateForBuffer()); - } - else if (PreferenceConstants.HWBUTTON_CTRLA_SPACE.equals(shortcut)) { - if (!down) return false; - - buffer.write(0x01); - buffer.write(' '); - } - else if (PreferenceConstants.HWBUTTON_CTRLA.equals(shortcut)) { - if (!down) return false; - - buffer.write(0x01); - } - else if (PreferenceConstants.HWBUTTON_ESC.equals(shortcut)) { - if (!down) return false; - - showMetakeyToast(v, PreferenceConstants.HWBUTTON_ESC); - sendEscape(); - } - else if (PreferenceConstants.HWBUTTON_ESC_A.equals(shortcut)) { - if (!down) return false; - - sendEscape(); - buffer.write('a'); - } - else { - return (false); - } - - return (true); - } - - private void showMetakeyToast(View v, String keyname) { - Log.d(TAG, keyname); - } - - public int keyAsControl(int key) { - // Support CTRL-a through CTRL-z - if (key >= 0x60 && key <= 0x7A) - key -= 0x60; - // Support CTRL-A through CTRL-_ - else if (key >= 0x40 && key <= 0x5F) - key -= 0x40; - // CTRL-space sends NULL - else if (key == 0x20) - key = 0x00; - // CTRL-? sends DEL - else if (key == 0x3F) - key = 0x7F; - - return key; - } - - /** - * @param key - * @return successful - */ - private boolean sendFunctionKey(int keyCode) { - switch (keyCode) { - case KeyEvent.KEYCODE_1: - buffer.keyPressed(vt320.KEY_F1, ' ', 0); - return true; - - case KeyEvent.KEYCODE_2: - buffer.keyPressed(vt320.KEY_F2, ' ', 0); - return true; - - case KeyEvent.KEYCODE_3: - buffer.keyPressed(vt320.KEY_F3, ' ', 0); - return true; - - case KeyEvent.KEYCODE_4: - buffer.keyPressed(vt320.KEY_F4, ' ', 0); - return true; - - case KeyEvent.KEYCODE_5: - buffer.keyPressed(vt320.KEY_F5, ' ', 0); - return true; - - case KeyEvent.KEYCODE_6: - buffer.keyPressed(vt320.KEY_F6, ' ', 0); - return true; - - case KeyEvent.KEYCODE_7: - buffer.keyPressed(vt320.KEY_F7, ' ', 0); - return true; - - case KeyEvent.KEYCODE_8: - buffer.keyPressed(vt320.KEY_F8, ' ', 0); - return true; - - case KeyEvent.KEYCODE_9: - buffer.keyPressed(vt320.KEY_F9, ' ', 0); - return true; - - case KeyEvent.KEYCODE_0: - buffer.keyPressed(vt320.KEY_F10, ' ', 0); - return true; - - default: - return false; - } - } - - private boolean sendFullSpecialKey(int keyCode) { - switch (keyCode) { - case KeyEvent.KEYCODE_F1: - buffer.keyPressed(vt320.KEY_F1, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F2: - buffer.keyPressed(vt320.KEY_F2, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F3: - buffer.keyPressed(vt320.KEY_F3, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F4: - buffer.keyPressed(vt320.KEY_F4, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F5: - buffer.keyPressed(vt320.KEY_F5, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F6: - buffer.keyPressed(vt320.KEY_F6, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F7: - buffer.keyPressed(vt320.KEY_F7, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F8: - buffer.keyPressed(vt320.KEY_F8, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F9: - buffer.keyPressed(vt320.KEY_F9, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F10: - buffer.keyPressed(vt320.KEY_F10, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F11: - buffer.keyPressed(vt320.KEY_F11, ' ', 0); - return true; - - case KeyEvent.KEYCODE_F12: - buffer.keyPressed(vt320.KEY_F12, ' ', 0); - return true; - - case KeyEvent.KEYCODE_INSERT: - buffer.keyPressed(vt320.KEY_INSERT, ' ', 0); - return true; - - case KeyEvent.KEYCODE_FORWARD_DEL: - buffer.keyPressed(vt320.KEY_DELETE, ' ', 0); - return true; - - /* - case KeyEvent.KEYCODE_PAGE_UP: - buffer.keyPressed(vt320.KEY_PAGE_UP, ' ', 0); - return true; - case KeyEvent.KEYCODE_PAGE_DOWN: - buffer.keyPressed(vt320.KEY_PAGE_DOWN, ' ', 0); - return true; - case KeyEvent.KEYCODE_MOVE_HOME: - buffer.keyPressed(vt320.KEY_HOME, ' ', getStateForBuffer()); - return true; - case KeyEvent.KEYCODE_MOVE_END: - buffer.keyPressed(vt320.KEY_END, ' ', getStateForBuffer()); - return true; - */ - default: - return false; - } - } - - /** - * Handle meta key presses for full hardware keyboard - */ - private void metaKeyDown(int code) { - if ((metaState & code) == 0) { - metaState |= code; - bridge.redraw(); - } - } - - protected void metaKeyUp(int code) { - if ((metaState & code) != 0) { - metaState &= ~code; - bridge.redraw(); - } - } - - /** - * Handle meta key presses where the key can be locked on. - * <p> - * 1st press: next key to have meta state<br /> - * 2nd press: meta state is locked on<br /> - * 3rd press: disable meta state - * - * @param code - */ - public void metaPress(int code) { - if ((metaState & (code << 1)) != 0) { - metaState &= ~(code << 1); - } - else if ((metaState & code) != 0) { - metaState &= ~code; - - if (!fullKeyboard()) - metaState |= code << 1; - } - else - metaState |= code; - - bridge.redraw(); - } - - public void setTerminalKeyMode(String keymode) { - this.keymode = keymode; - } - - private int getStateForBuffer() { - int bufferState = 0; - - if ((metaState & META_CTRL_MASK) != 0) - bufferState |= vt320.KEY_CONTROL; - - if ((metaState & META_SHIFT_MASK) != 0) - bufferState |= vt320.KEY_SHIFT; - - if ((metaState & META_ALT_MASK) != 0) - bufferState |= vt320.KEY_ALT; - - return bufferState; - } - - public int getMetaState() { - return metaState; - } - - public int getDeadKey() { - return mDeadKey; - } - - public void setClipboardManager(ClipboardManager clipboard) { - this.clipboard = clipboard; - } - - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { - if (PreferenceConstants.KEYMODE.equals(key)) { - updateKeymode(); - } - else if (PreferenceConstants.CUSTOM_KEYMAP.equals(key)) { - updateCustomKeymap(); - } - } - - private void updateKeymode() { - keymode = prefs.getString(PreferenceConstants.KEYMODE, PreferenceConstants.KEYMODE_RIGHT); - } - - private void updateCustomKeymap() { - customKeyboard = prefs.getString(PreferenceConstants.CUSTOM_KEYMAP, - PreferenceConstants.CUSTOM_KEYMAP_DISABLED); - } - - public void setCharset(String encoding) { - this.encoding = encoding; - } - - public Charset getCharset() { - return Charset.forName(encoding); - } - - protected void ctrlKeySpecial() { - if (selectingForCopy) { - if (selectionArea.isSelectingOrigin()) - selectionArea.finishSelectingOrigin(); - else { - if (clipboard != null) { - // copy selected area to clipboard - String copiedText = selectionArea.copyFrom(buffer); - clipboard.setText(copiedText); - selectingForCopy = false; - selectionArea.reset(); - } - } - } - else { - if ((metaState & META_CTRL_ON) != 0) { - sendEscape(); - metaState &= ~META_CTRL_ON; - } - else - metaPress(META_CTRL_ON); - } - - bridge.redraw(); - } - - protected boolean customKeymapAction(View v, int keyCode, KeyEvent event) { - if (bridge == null || customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_DISABLED)) - return false; - - byte c = 0x00; - int termKey = 0; - - if (fullKeyboard()) { - switch (keyCode) { - case KeyEvent.KEYCODE_CTRL_LEFT: - case KeyEvent.KEYCODE_CTRL_RIGHT: - metaKeyDown(META_CTRL_ON); - return true; - - case KeyEvent.KEYCODE_ALT_LEFT: - case KeyEvent.KEYCODE_ALT_RIGHT: - metaKeyDown(META_ALT_ON); - return true; - - case KeyEvent.KEYCODE_SHIFT_LEFT: - case KeyEvent.KEYCODE_SHIFT_RIGHT: - metaKeyDown(META_SHIFT_ON); - return true; - - case KeyEvent.KEYCODE_BACK: - if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_ASUS_TF)) { - // Check to see whether this is the back button on the - // screen (-1) or the Asus Transformer Keyboard Dock. - // Treat the HW button as ESC. - if (event.getDeviceId() > 0) { - sendEscape(); - return true; - } - } - - default: - } - } - - if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_ASUS_TF)) { - if ((metaState & META_ALT_MASK) != 0 - && (metaState & META_SHIFT_MASK) != 0 - && sendFunctionKey(keyCode)) - return true; - } - else if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_SE_XPPRO)) { - // Sony Ericsson Xperia pro (MK16i) and Xperia mini Pro (SK17i) - // Language key acts as CTRL - if (keyCode == KeyEvent.KEYCODE_SWITCH_CHARSET) { - ctrlKeySpecial(); - return true; - } - - if ((metaState & META_ALT_MASK) != 0) { - if ((metaState & META_SHIFT_MASK) != 0) { - // ALT + shift + key - switch (keyCode) { - case KeyEvent.KEYCODE_U: - c = 0x5B; - break; - - case KeyEvent.KEYCODE_I: - c = 0x5D; - break; - - case KeyEvent.KEYCODE_O: - c = 0x7B; - break; - - case KeyEvent.KEYCODE_P: - c = 0x7D; - break; - } - } - else { - // ALT + key - switch (keyCode) { - case KeyEvent.KEYCODE_S: - c = 0x7c; - break; - - case KeyEvent.KEYCODE_Z: - c = 0x5c; - break; - - case KeyEvent.KEYCODE_DEL: - termKey = vt320.KEY_DELETE; - break; - } - } - } - else if ((metaState & META_SHIFT_MASK) != 0) { - // shift + key - switch (keyCode) { - case KeyEvent.KEYCODE_AT: - c = 0x3c; - break; - - case KeyEvent.KEYCODE_COMMA: - c = 0x3e; - break; - - case KeyEvent.KEYCODE_PERIOD: - c = 0x5e; - break; - - case KeyEvent.KEYCODE_GRAVE: - c = 0x60; - break; - - case KeyEvent.KEYCODE_APOSTROPHE: - c = 0x7e; - break; - - case KeyEvent.KEYCODE_DEL: - termKey = vt320.KEY_BACK_SPACE; - break; - } - } - } - else if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_SGH_I927)) { - // Samsung Captivate Glide (SGH-i927) - if (keyCode == 115) { - // .com key = ESC - c = 0x00; - termKey = vt320.KEY_ESCAPE; - return true; - } - else if (keyCode == 116) { - // Microphone key = TAB - c = 0x00; - termKey = vt320.KEY_TAB; - } - else if ((metaState & META_ALT_MASK) != 0 && (metaState & META_SHIFT_MASK) != 0) { - switch (keyCode) { - case KeyEvent.KEYCODE_O: - c = 0x5B; - break; - - case KeyEvent.KEYCODE_P: - c = 0x5D; - break; - - case KeyEvent.KEYCODE_A: - c = 0x3C; - break; - - case KeyEvent.KEYCODE_D: - c = 0x3E; - break; - } - } - } - else if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_SGH_I927_ICS)) { - // Samsung Captivate Glide (SGH-i927) Ice Cream Sandwich (4.0.x) - if (keyCode == 226) { - // .com key = ESC - c = 0x00; - termKey = vt320.KEY_ESCAPE; - } - else if (keyCode == 220) { - // Microphone key = TAB - c = 0x00; - termKey = vt320.KEY_TAB; - } - else if ((metaState & META_ALT_MASK) != 0 && (metaState & META_SHIFT_MASK) != 0) { - switch (keyCode) { - case KeyEvent.KEYCODE_O: - c = 0x5B; - break; - - case KeyEvent.KEYCODE_P: - c = 0x5D; - break; - - case KeyEvent.KEYCODE_A: - c = 0x3C; - break; - - case KeyEvent.KEYCODE_D: - c = 0x3E; - break; - } - } - } - - if ((c != 0x00) || termKey != 0) { - if (c != 0x00) - buffer.write(c); - else - buffer.keyPressed(termKey, ' ', 0); - - metaState &= ~(META_SHIFT_ON | META_ALT_ON); - bridge.redraw(); - return true; - } - - return false; - } - - public void urlScan(View v) { - //final TerminalView terminalView = (TerminalView) findCurrentView(R.id.console_flip); - List<String> urls = bridge.scanForURLs(); - Dialog urlDialog = new Dialog(v.getContext()); - urlDialog.setTitle(R.string.console_menu_urlscan); - ListView urlListView = new ListView(v.getContext()); - URLItemListener urlListener = new URLItemListener(v.getContext()); - urlListView.setOnItemClickListener(urlListener); - urlListView.setAdapter(new ArrayAdapter<String> (v.getContext(), android.R.layout.simple_list_item_1, urls)); - urlDialog.setContentView(urlListView); - urlDialog.show(); - } - - public boolean isSymKey(int keyCode) { - if (keyCode == KeyEvent.KEYCODE_SYM || - keyCode == KeyEvent.KEYCODE_PICTSYMBOLS) - return true; - - if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_SGH_I927_ICS) && - keyCode == 227) - return true; - - return false; - } - - protected boolean fullKeyboard() { - if (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_FULL) || - (customKeyboard.equals(PreferenceConstants.CUSTOM_KEYMAP_ASUS_TF))) - return true; - - return false; - } - - private class URLItemListener implements OnItemClickListener { - private WeakReference<Context> contextRef; - - URLItemListener(Context context) { - this.contextRef = new WeakReference<Context> (context); - } - - public void onItemClick(AdapterView<?> arg0, View view, int position, - long id) { - Context context = contextRef.get(); - - if (context == null) - return; - - try { - TextView urlView = (TextView) view; - String url = urlView.getText().toString(); - - if (url.indexOf("://") < 0) - url = "http://" + url; - - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - context.startActivity(intent); - } - catch (Exception e) { - Log.e(TAG, "couldn't open URL", e); - // We should probably tell the user that we couldn't find a - // handler... - } - } - } -}
--- a/src/com/five_ten_sg/connectbot/service/TerminalManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,730 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.service; - -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Timer; -import java.util.TimerTask; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.bean.PubkeyBean; -import com.five_ten_sg.connectbot.transport.TransportFactory; -import com.five_ten_sg.connectbot.util.HostDatabase; -import com.five_ten_sg.connectbot.util.PreferenceConstants; -import com.five_ten_sg.connectbot.util.PubkeyDatabase; -import com.five_ten_sg.connectbot.util.PubkeyUtils; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.content.res.AssetFileDescriptor; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.media.AudioManager; -import android.media.MediaPlayer; -import android.media.MediaPlayer.OnCompletionListener; -import android.net.Uri; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Vibrator; -import android.preference.PreferenceManager; -import android.util.Log; - -/** - * Manager for SSH connections that runs as a service. This service holds a list - * of currently connected SSH bridges that are ready for connection up to a GUI - * if needed. - * - * @author jsharkey - */ -public class TerminalManager extends Service implements BridgeDisconnectedListener, OnSharedPreferenceChangeListener { - public final static String TAG = "ConnectBot.TerminalManager"; - - public List<TerminalBridge> bridges = new LinkedList<TerminalBridge>(); - public Map<HostBean, WeakReference<TerminalBridge>> mHostBridgeMap = - new HashMap<HostBean, WeakReference<TerminalBridge>>(); - public Map<String, WeakReference<TerminalBridge>> mNicknameBridgeMap = - new HashMap<String, WeakReference<TerminalBridge>>(); - - public TerminalBridge defaultBridge = null; - - public List<HostBean> disconnected = new LinkedList<HostBean>(); - - public Handler disconnectHandler = null; - - public Map<String, KeyHolder> loadedKeypairs = new HashMap<String, KeyHolder>(); - - public Resources res; - - public HostDatabase hostdb; - public PubkeyDatabase pubkeydb; - - protected SharedPreferences prefs; - - final private IBinder binder = new TerminalBinder(); - - private ConnectivityReceiver connectivityManager; - private ConnectionNotifier connectionNotifier = new ConnectionNotifier(); - - private MediaPlayer mediaPlayer; - - private Timer pubkeyTimer; - - private Timer idleTimer; - private final long IDLE_TIMEOUT = 300000; // 5 minutes - - private Vibrator vibrator; - private volatile boolean wantKeyVibration; - public static final long VIBRATE_DURATION = 30; - - private boolean wantBellVibration; - - private boolean resizeAllowed = true; - - private int fullScreen = 0; - - private boolean savingKeys; - - protected List<WeakReference<TerminalBridge>> mPendingReconnect - = new LinkedList<WeakReference<TerminalBridge>>(); - - public boolean hardKeyboardHidden; - - @Override - public void onCreate() { - Log.i(TAG, "Starting service"); - prefs = PreferenceManager.getDefaultSharedPreferences(this); - prefs.registerOnSharedPreferenceChangeListener(this); - res = getResources(); - pubkeyTimer = new Timer("pubkeyTimer", true); - hostdb = new HostDatabase(this); - pubkeydb = new PubkeyDatabase(this); - // load all marked pubkeys into memory - updateSavingKeys(); - List<PubkeyBean> pubkeys = pubkeydb.getAllStartPubkeys(); - - for (PubkeyBean pubkey : pubkeys) { - try { - PrivateKey privKey = PubkeyUtils.decodePrivate(pubkey.getPrivateKey(), pubkey.getType()); - PublicKey pubKey = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); - KeyPair pair = new KeyPair(pubKey, privKey); - addKey(pubkey, pair); - } - catch (Exception e) { - Log.d(TAG, String.format("Problem adding key '%s' to in-memory cache", pubkey.getNickname()), e); - } - } - - vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); - wantKeyVibration = prefs.getBoolean(PreferenceConstants.BUMPY_ARROWS, true); - wantBellVibration = prefs.getBoolean(PreferenceConstants.BELL_VIBRATE, true); - enableMediaPlayer(); - hardKeyboardHidden = (res.getConfiguration().hardKeyboardHidden == - Configuration.HARDKEYBOARDHIDDEN_YES); - final boolean lockingWifi = prefs.getBoolean(PreferenceConstants.WIFI_LOCK, true); - connectivityManager = new ConnectivityReceiver(this, lockingWifi); - } - - private void updateSavingKeys() { - savingKeys = prefs.getBoolean(PreferenceConstants.MEMKEYS, true); - } - - @Override - public void onDestroy() { - Log.i(TAG, "Destroying service"); - disconnectAll(true); - - if (hostdb != null) { - hostdb.close(); - hostdb = null; - } - - if (pubkeydb != null) { - pubkeydb.close(); - pubkeydb = null; - } - - synchronized (this) { - if (idleTimer != null) - idleTimer.cancel(); - - if (pubkeyTimer != null) - pubkeyTimer.cancel(); - } - - connectivityManager.cleanup(); - connectionNotifier.hideRunningNotification(this); - disableMediaPlayer(); - } - - /** - * Disconnect all currently connected bridges. - */ - private void disconnectAll(final boolean immediate) { - disconnectAll(immediate, false); - } - - /** - * Disconnect all currently connected bridges. - */ - private void disconnectAll(final boolean immediate, boolean onlyRemote) { - TerminalBridge[] tmpBridges = null; - - synchronized (bridges) { - if (bridges.size() > 0) { - tmpBridges = bridges.toArray(new TerminalBridge[bridges.size()]); - } - } - - if (tmpBridges != null) { - // disconnect and dispose of any existing bridges - for (int i = 0; i < tmpBridges.length; i++) { - if (!onlyRemote || !(tmpBridges[i].transport instanceof com.five_ten_sg.connectbot.transport.Local)) - tmpBridges[i].dispatchDisconnect(immediate); - } - } - } - - /** - * Open a new SSH session using the given parameters. - */ - private TerminalBridge openConnection(HostBean host) throws IllegalArgumentException, IOException { - // throw exception if terminal already open - if (getConnectedBridge(host) != null) { - throw new IllegalArgumentException("Connection already open for that nickname"); - } - - TerminalBridge bridge = new TerminalBridge(this, host, getApplicationInfo().dataDir); - bridge.setOnDisconnectedListener(this); - bridge.startConnection(); - - synchronized (bridges) { - bridges.add(bridge); - WeakReference<TerminalBridge> wr = new WeakReference<TerminalBridge> (bridge); - mHostBridgeMap.put(bridge.host, wr); - mNicknameBridgeMap.put(bridge.host.getNickname(), wr); - } - - synchronized (disconnected) { - disconnected.remove(bridge.host); - } - - if (bridge.isUsingNetwork()) { - connectivityManager.incRef(); - } - - if (prefs.getBoolean(PreferenceConstants.CONNECTION_PERSIST, true)) { - connectionNotifier.showRunningNotification(this); - } - - // also update database with new connected time - touchHost(host); - return bridge; - } - - public String getEmulation() { - return prefs.getString(PreferenceConstants.EMULATION, "xterm-256color"); - } - - public int getScrollback() { - int scrollback = 140; - - try { - scrollback = Integer.parseInt(prefs.getString(PreferenceConstants.SCROLLBACK, "140")); - } - catch (Exception e) { - } - - return scrollback; - } - - /** - * Open a new connection by reading parameters from the given URI. Follows - * format specified by an individual transport. - */ - public TerminalBridge openConnection(Uri uri) throws Exception { - HostBean host = TransportFactory.findHost(hostdb, uri); - - if (host == null) - host = TransportFactory.getTransport(uri.getScheme()).createHost(uri); - - return openConnection(host); - } - - /** - * Update the last-connected value for the given nickname by passing through - * to {@link HostDatabase}. - */ - private void touchHost(HostBean host) { - hostdb.touchHost(host); - } - - /** - * Find a connected {@link TerminalBridge} with the given HostBean. - * - * @param host the HostBean to search for - * @return TerminalBridge that uses the HostBean - */ - public TerminalBridge getConnectedBridge(HostBean host) { - WeakReference<TerminalBridge> wr = mHostBridgeMap.get(host); - - if (wr != null) { - return wr.get(); - } - else { - return null; - } - } - - /** - * Find a connected {@link TerminalBridge} using its nickname. - * - * @param nickname - * @return TerminalBridge that matches nickname - */ - public TerminalBridge getConnectedBridge(final String nickname) { - if (nickname == null) { - return null; - } - - WeakReference<TerminalBridge> wr = mNicknameBridgeMap.get(nickname); - - if (wr != null) { - return wr.get(); - } - else { - return null; - } - } - - /** - * Called by child bridge when somehow it's been disconnected. - */ - public void onDisconnected(TerminalBridge bridge) { - boolean shouldHideRunningNotification = false; - - synchronized (bridges) { - // remove this bridge from our list - bridges.remove(bridge); - mHostBridgeMap.remove(bridge.host); - mNicknameBridgeMap.remove(bridge.host.getNickname()); - - if (bridge.isUsingNetwork()) { - connectivityManager.decRef(); - } - - if (bridges.size() == 0 && - mPendingReconnect.size() == 0) { - shouldHideRunningNotification = true; - } - } - - synchronized (disconnected) { - disconnected.add(bridge.host); - } - - if (shouldHideRunningNotification) { - connectionNotifier.hideRunningNotification(this); - } - - // pass notification back up to gui - if (disconnectHandler != null) - Message.obtain(disconnectHandler, -1, bridge).sendToTarget(); - } - - public boolean isKeyLoaded(String nickname) { - return loadedKeypairs.containsKey(nickname); - } - - public void addKey(PubkeyBean pubkey, KeyPair pair) { - addKey(pubkey, pair, false); - } - - public void addKey(PubkeyBean pubkey, KeyPair pair, boolean force) { - if (!savingKeys && !force) - return; - - removeKey(pubkey.getNickname()); - byte[] sshPubKey = PubkeyUtils.extractOpenSSHPublic(pair); - KeyHolder keyHolder = new KeyHolder(); - keyHolder.bean = pubkey; - keyHolder.pair = pair; - keyHolder.openSSHPubkey = sshPubKey; - loadedKeypairs.put(pubkey.getNickname(), keyHolder); - - if (pubkey.getLifetime() > 0) { - final String nickname = pubkey.getNickname(); - pubkeyTimer.schedule(new TimerTask() { - @Override - public void run() { - Log.d(TAG, "Unloading from memory key: " + nickname); - removeKey(nickname); - } - }, pubkey.getLifetime() * 1000); - } - - Log.d(TAG, String.format("Added key '%s' to in-memory cache", pubkey.getNickname())); - } - - public boolean removeKey(String nickname) { - Log.d(TAG, String.format("Removed key '%s' from in-memory cache", nickname)); - return loadedKeypairs.remove(nickname) != null; - } - - public boolean removeKey(byte[] publicKey) { - String nickname = null; - - for (Entry<String, KeyHolder> entry : loadedKeypairs.entrySet()) { - if (Arrays.equals(entry.getValue().openSSHPubkey, publicKey)) { - nickname = entry.getKey(); - break; - } - } - - if (nickname != null) { - Log.d(TAG, String.format("Removed key '%s' to in-memory cache", nickname)); - return removeKey(nickname); - } - else - return false; - } - - public KeyPair getKey(String nickname) { - if (loadedKeypairs.containsKey(nickname)) { - KeyHolder keyHolder = loadedKeypairs.get(nickname); - return keyHolder.pair; - } - else - return null; - } - - public KeyPair getKey(byte[] publicKey) { - for (KeyHolder keyHolder : loadedKeypairs.values()) { - if (Arrays.equals(keyHolder.openSSHPubkey, publicKey)) - return keyHolder.pair; - } - - return null; - } - - public String getKeyNickname(byte[] publicKey) { - for (Entry<String, KeyHolder> entry : loadedKeypairs.entrySet()) { - if (Arrays.equals(entry.getValue().openSSHPubkey, publicKey)) - return entry.getKey(); - } - - return null; - } - - private void stopWithDelay() { - // TODO add in a way to check whether keys loaded are encrypted and only - // set timer when we have an encrypted key loaded - if (loadedKeypairs.size() > 0) { - synchronized (this) { - if (idleTimer == null) - idleTimer = new Timer("idleTimer", true); - - idleTimer.schedule(new IdleTask(), IDLE_TIMEOUT); - } - } - else { - Log.d(TAG, "Stopping service immediately"); - stopSelf(); - } - } - - protected void stopNow() { - if (bridges.size() == 0) { - stopSelf(); - } - } - - private synchronized void stopIdleTimer() { - if (idleTimer != null) { - idleTimer.cancel(); - idleTimer = null; - } - } - - public class TerminalBinder extends Binder { - public TerminalManager getService() { - return TerminalManager.this; - } - } - - @Override - public IBinder onBind(Intent intent) { - Log.i(TAG, "Someone bound to TerminalManager"); - setResizeAllowed(true); - stopIdleTimer(); - // Make sure we stay running to maintain the bridges - startService(new Intent(this, TerminalManager.class)); - return binder; - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - /* - * We want this service to continue running until it is explicitly - * stopped, so return sticky. - */ - return START_STICKY; - } - - @Override - public void onRebind(Intent intent) { - super.onRebind(intent); - setResizeAllowed(true); - Log.i(TAG, "Someone rebound to TerminalManager"); - stopIdleTimer(); - } - - @Override - public boolean onUnbind(Intent intent) { - Log.i(TAG, "Someone unbound from TerminalManager"); - setResizeAllowed(true); - - if (bridges.size() == 0) { - stopWithDelay(); - } - - return true; - } - - private class IdleTask extends TimerTask { - /* (non-Javadoc) - * @see java.util.TimerTask#run() - */ - @Override - public void run() { - Log.d(TAG, String.format("Stopping service after timeout of ~%d seconds", IDLE_TIMEOUT / 1000)); - TerminalManager.this.stopNow(); - } - } - - public void tryKeyVibrate() { - if (wantKeyVibration) - vibrate(); - } - - private void vibrate() { - if (vibrator != null) - vibrator.vibrate(VIBRATE_DURATION); - } - - private void enableMediaPlayer() { - mediaPlayer = new MediaPlayer(); - float volume = prefs.getFloat(PreferenceConstants.BELL_VOLUME, - PreferenceConstants.DEFAULT_BELL_VOLUME); - mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION); - mediaPlayer.setOnCompletionListener(new BeepListener()); - AssetFileDescriptor file = res.openRawResourceFd(R.raw.bell); - - try { - mediaPlayer.setDataSource(file.getFileDescriptor(), file - .getStartOffset(), file.getLength()); - file.close(); - mediaPlayer.setVolume(volume, volume); - mediaPlayer.prepare(); - } - catch (IOException e) { - Log.e(TAG, "Error setting up bell media player", e); - } - } - - private void disableMediaPlayer() { - if (mediaPlayer != null) { - mediaPlayer.release(); - mediaPlayer = null; - } - } - - public void playBeep() { - if (mediaPlayer != null) - mediaPlayer.start(); - - if (wantBellVibration) - vibrate(); - } - - private static class BeepListener implements OnCompletionListener { - public void onCompletion(MediaPlayer mp) { - mp.seekTo(0); - } - } - - /** - * Send system notification to user for a certain host. When user selects - * the notification, it will bring them directly to the ConsoleActivity - * displaying the host. - * - * @param host - */ - public void sendActivityNotification(HostBean host) { - if (!prefs.getBoolean(PreferenceConstants.BELL_NOTIFICATION, false)) - return; - - connectionNotifier.showActivityNotification(this, host); - } - - /* (non-Javadoc) - * @see android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged(android.content.SharedPreferences, java.lang.String) - */ - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { - if (PreferenceConstants.BELL.equals(key)) { - boolean wantAudible = sharedPreferences.getBoolean( - PreferenceConstants.BELL, true); - - if (wantAudible && mediaPlayer == null) - enableMediaPlayer(); - else if (!wantAudible && mediaPlayer != null) - disableMediaPlayer(); - } - else if (PreferenceConstants.BELL_VOLUME.equals(key)) { - if (mediaPlayer != null) { - float volume = sharedPreferences.getFloat( - PreferenceConstants.BELL_VOLUME, - PreferenceConstants.DEFAULT_BELL_VOLUME); - mediaPlayer.setVolume(volume, volume); - } - } - else if (PreferenceConstants.BELL_VIBRATE.equals(key)) { - wantBellVibration = sharedPreferences.getBoolean( - PreferenceConstants.BELL_VIBRATE, true); - } - else if (PreferenceConstants.BUMPY_ARROWS.equals(key)) { - wantKeyVibration = sharedPreferences.getBoolean( - PreferenceConstants.BUMPY_ARROWS, true); - } - else if (PreferenceConstants.WIFI_LOCK.equals(key)) { - final boolean lockingWifi = prefs.getBoolean(PreferenceConstants.WIFI_LOCK, true); - connectivityManager.setWantWifiLock(lockingWifi); - } - else if (PreferenceConstants.MEMKEYS.equals(key)) { - updateSavingKeys(); - } - } - - /** - * Allow {@link TerminalBridge} to resize when the parent has changed. - * @param resizeAllowed - */ - public void setResizeAllowed(boolean resizeAllowed) { - this.resizeAllowed = resizeAllowed; - } - - public boolean isResizeAllowed() { - return resizeAllowed; - } - - public void setFullScreen(int fullScreen) { - this.fullScreen = fullScreen; - } - - public int getFullScreen() { - return this.fullScreen; - } - - public static class KeyHolder { - public PubkeyBean bean; - public KeyPair pair; - public byte[] openSSHPubkey; - } - - /** - * Called when connectivity to the network is lost and it doesn't appear - * we'll be getting a different connection any time soon. - */ - public void onConnectivityLost() { - final Thread t = new Thread() { - @Override - public void run() { - disconnectAll(false, true); - } - }; - t.setName("Disconnector"); - t.start(); - } - - /** - * Called when connectivity to the network is restored. - */ - public void onConnectivityRestored() { - final Thread t = new Thread() { - @Override - public void run() { - reconnectPending(); - } - }; - t.setName("Reconnector"); - t.start(); - } - - /** - * Insert request into reconnect queue to be executed either immediately - * or later when connectivity is restored depending on whether we're - * currently connected. - * - * @param bridge the TerminalBridge to reconnect when possible - */ - public void requestReconnect(TerminalBridge bridge) { - synchronized (mPendingReconnect) { - mPendingReconnect.add(new WeakReference<TerminalBridge> (bridge)); - - if (!bridge.isUsingNetwork() || - connectivityManager.isConnected()) { - reconnectPending(); - } - } - } - - /** - * Reconnect all bridges that were pending a reconnect when connectivity - * was lost. - */ - private void reconnectPending() { - synchronized (mPendingReconnect) { - for (WeakReference<TerminalBridge> ref : mPendingReconnect) { - TerminalBridge bridge = ref.get(); - - if (bridge == null) { - continue; - } - - bridge.startConnection(); - } - - mPendingReconnect.clear(); - } - } -}
--- a/src/com/five_ten_sg/connectbot/service/TerminalMonitor.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,522 +0,0 @@ -package com.five_ten_sg.connectbot.service; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.net.Uri; -import android.os.IBinder; -import android.util.Log; -import android.view.View; -import de.mud.terminal.vt320; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.Socket; -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.HashMap; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; - -import com.five_ten_sg.connectbot.ConsoleActivity; -import com.five_ten_sg.connectbot.bean.HostBean; - - -public class TerminalMonitor { - public final static String TAG = "ConnectBot.TerminalMonitor"; - - public static final char MONITOR_CMD_INIT = 0; - public static final char MONITOR_CMD_ACTIVATE = 1; - public static final char MONITOR_CMD_KEYSTATE = 2; - public static final char MONITOR_CMD_CURSORMOVE = 3; - public static final char MONITOR_CMD_SCREENCHANGE = 4; - public static final char MONITOR_CMD_FIELDVALUE = 5; - public static final char MONITOR_CMD_SETFIELD = 5; - public static final char MONITOR_CMD_GETFIELD = 6; - public static final char MONITOR_CMD_SCREENWATCH = 7; - public static final char MONITOR_CMD_DEPRESS = 8; - public static final char MONITOR_CMD_SHOWURL = 9; - public static final char MONITOR_CMD_SWITCHSESSION = 10; - public static final char MONITOR_CMD_CURSORREQUEST = 11; - - public static final String[] commands = { - "cmd_init", - "cmd_activate", - "cmd_keystate", - "cmd_cursormove", - "cmd_screenchange", - "cmd_fieldvalue/setfield", - "cmd_getfield", - "cmd_screenwatch", - "cmd_depress", - "cmd_showurl", - "cmd_switchsession", - "cmd_cursorrequest" - }; - - public static final char CURSOR_REQUESTED = 0; - public static final char CURSOR_SCREEN_CHANGE = 1; - public static final char CURSOR_USER_KEY = 2; - - private static final int MONITORPORT = 6000; - private static final String LOCALHOST = "127.0.0.1"; - - private Context parent = null; - private vt320 buffer = null; - private View view = null; - private HostBean host = null; - private String init = null; - private int start_line = 0; // monitor part of the screen for changes - private int end_line = 500; // "" - private int start_column = 0; // "" - private int end_column = 500; // "" - private boolean modified = false; // used to delay screen change notifications - private boolean moved = false; // used to delay cursor moved notifications - private int to_line = 0; // "" - private int to_column = 0; // "" - private HashMap<Integer, Integer> keymap = null; // map MS VK_ keys to vt320 virtual keys - private IBinder bound = null; - private Socket monitor_socket = null; - private InputStream monitor_in = null; - private OutputStream monitor_out = null; - private MyReader monitor_reader = null; - private BlockingQueue<char[]> pending_commands = new ArrayBlockingQueue<char[]>(100); - private MyServiceConnection monitor_connection = new MyServiceConnection(); - - class MyReader extends Thread { - private InputStream monitor_in; - private byte[] b; - private boolean is_closing = false; - - public MyReader(InputStream monitor_in) { - this.monitor_in = monitor_in; - b = new byte[100]; - Log.i(TAG, "MyReader constructor"); - } - - public void closing() { - is_closing = true; - } - - private char[] forceRead(int len) throws IOException { - int len2 = len * 2; - int off = 0; - - if (b.length < len2) b = new byte[len2]; - - while (off < len2) { - int l = monitor_in.read(b, off, len2 - off); - - if (l < 0) throw new IOException("eof"); - - off += l; - } - - return bytesToChars(b, len2); - } - - public void run() { - while (true) { - try { - char[] len = forceRead(1); - char[] packet = forceRead(len[0]); - char cmd = packet[0]; - Log.i(TAG, String.format("received %s", commands[cmd])); - - switch (cmd) { - case MONITOR_CMD_SETFIELD: - if (packet.length >= 3) - setField(packet[1], packet[2], packet, 3); - - break; - - case MONITOR_CMD_GETFIELD: - if (packet.length == 4) - getField(packet[1], packet[2], packet[3]); - - break; - - case MONITOR_CMD_SCREENWATCH: - if (packet.length == 4) - screenWatch(packet[1], packet[2], packet[3]); - - break; - - case MONITOR_CMD_DEPRESS: - if (packet.length == 2) - depress(packet[1]); - - break; - - case MONITOR_CMD_SHOWURL: - if (packet.length > 1) - showUrl(packet, 1); - - break; - - case MONITOR_CMD_SWITCHSESSION: - if (packet.length == 1) - switchSession(); - - break; - - case MONITOR_CMD_CURSORREQUEST: - if (packet.length == 1) - cursorRequest(); - - break; - - default: - break; - } - } - catch (IOException e) { - if (!is_closing) Log.e(TAG, "exception in MyReader.run()", e); - - break; - } - } - } - } - - class MyServiceConnection implements ServiceConnection { - public void onServiceConnected(ComponentName className, IBinder service) { - bound = service; - Log.i(TAG, "bound to service"); - - try { - InetAddress serverAddr = InetAddress.getByName(LOCALHOST); - int tries = 0; - while (tries < 10) { - try { - Thread.sleep(100); - monitor_socket = new Socket(serverAddr, MONITORPORT); - break; - } - catch (Exception e) { - monitor_socket = null; - Log.e(TAG, "exception connecting to monitor socket", e); - tries = tries + 1; - } - } - if (monitor_socket != null) { - Log.i(TAG, "connected to monitor socket, send init " + init); - monitor_in = monitor_socket.getInputStream(); - monitor_out = monitor_socket.getOutputStream(); - monitor_reader = new MyReader(monitor_in); - monitor_reader.start(); - String x = " " + init; - monitorWrite(MONITOR_CMD_INIT, x.toCharArray()); - char [] c; - - while (true) { - c = pending_commands.poll(); - - if (c == null) break; - - monitorWrite(c[1], c); - } - } - } - catch (IOException e) { - Log.e(TAG, "exception in onServiceConnected()", e); - } - } - public void onServiceDisconnected(ComponentName classNam) { - bound = null; - Log.i(TAG, "unbound from service"); - } - }; - - - public TerminalMonitor(Context parent, vt320 buffer, View view, HostBean host, String init) { - this.parent = parent; - this.buffer = buffer; - this.view = view; - this.host = host; - this.init = init; - // setup the windows->android keymapping - // http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731 - keymap = new HashMap<Integer, Integer>(); - keymap.put(0x08, vt320.KEY_BACK_SPACE); // vk_back - keymap.put(0x09, vt320.KEY_TAB); // vk_tab - keymap.put(0x0d, vt320.KEY_ENTER); // vk_return - keymap.put(0x1b, vt320.KEY_ESCAPE); // vk_escape - keymap.put(0x21, vt320.KEY_PAGE_UP); // vk_prior - keymap.put(0x22, vt320.KEY_PAGE_DOWN); // vk_next - keymap.put(0x23, vt320.KEY_END); // vk_end - keymap.put(0x24, vt320.KEY_HOME); // vk_home - keymap.put(0x25, vt320.KEY_LEFT); // vk_left - keymap.put(0x26, vt320.KEY_UP); // vk_up - keymap.put(0x27, vt320.KEY_RIGHT); // vk_right - keymap.put(0x28, vt320.KEY_DOWN); // vk_down - keymap.put(0x2d, vt320.KEY_INSERT); // vk_insert - keymap.put(0x2e, vt320.KEY_DELETE); // vk_delete - keymap.put(0x70, vt320.KEY_F1); // vk_f1 - keymap.put(0x71, vt320.KEY_F2); // vk_f2 - keymap.put(0x72, vt320.KEY_F3); // vk_f3 - keymap.put(0x73, vt320.KEY_F4); // vk_f4 - keymap.put(0x74, vt320.KEY_F5); // vk_f5 - keymap.put(0x75, vt320.KEY_F6); // vk_f6 - keymap.put(0x76, vt320.KEY_F7); // vk_f7 - keymap.put(0x77, vt320.KEY_F8); // vk_f8 - keymap.put(0x78, vt320.KEY_F9); // vk_f9 - keymap.put(0x79, vt320.KEY_F10); // vk_f10 - keymap.put(0x7a, vt320.KEY_F11); // vk_f11 - keymap.put(0x7b, vt320.KEY_F12); // vk_f12 - keymap.put(0x7c, vt320.KEY_F13); // vk_f13 - keymap.put(0x7d, vt320.KEY_F14); // vk_f14 - keymap.put(0x7e, vt320.KEY_F15); // vk_f15 - keymap.put(0x7f, vt320.KEY_F16); // vk_f16 - keymap.put(0x80, vt320.KEY_F17); // vk_f17 - keymap.put(0x81, vt320.KEY_F18); // vk_f18 - keymap.put(0x82, vt320.KEY_F19); // vk_f19 - keymap.put(0x83, vt320.KEY_F20); // vk_f20 - keymap.put(0x84, vt320.KEY_F21); // vk_f21 - keymap.put(0x85, vt320.KEY_F22); // vk_f22 - keymap.put(0x86, vt320.KEY_F23); // vk_f23 - keymap.put(0x87, vt320.KEY_F24); // vk_f24 - // bind to the monitor service - Intent intent = new Intent("com.five_ten_sg.connectbot.monitor.MonitorService"); - parent.bindService(intent, monitor_connection, Context.BIND_AUTO_CREATE); - Log.i(TAG, "constructor"); - } - - - public void Disconnect() { - if (monitor_reader != null) monitor_reader.closing(); - - try { - if (monitor_out != null) monitor_out.close(); - - if (monitor_in != null) monitor_in.close(); - - if (monitor_socket != null) monitor_socket.close(); - - Log.i(TAG, "disconnected from monitor socket"); - } - catch (IOException e) { - Log.e(TAG, "exception in Disconnect() closing sockets", e); - } - - monitor_reader = null; - monitor_out = null; - monitor_in = null; - monitor_socket = null; - - if (bound != null) parent.unbindService(monitor_connection); - - monitor_connection = null; - } - - - public char[] bytesToChars(byte[] b, int len) { - char[] c = new char[len >> 1]; - int bp = 0; - - for (int i = 0; i < c.length; i++) { - byte b1 = b[bp++]; - byte b2 = b[bp++]; - c[i] = (char)(((b1 & 0x00FF) << 8) + (b2 & 0x00FF)); - } - - return c; - } - - - public byte[] charsToBytes(char[] c) { - byte[] b = new byte[c.length << 1]; - int bp = 0; - - for (int i = 0; i < c.length; i++) { - b[bp++] = (byte)((c[i] & 0xff00) >> 8); - b[bp++] = (byte)(c[i] & 0x00ff); - } - - return b; - } - - - public synchronized void monitorWrite(char cmd, char[] c) { - try { - if (monitor_out != null) { - c[0] = (char)(c.length - 1); // number of chars following - c[1] = cmd; - Log.i(TAG, String.format("sending %s", commands[cmd])); - monitor_out.write(charsToBytes(c)); - monitor_out.flush(); - } - else { - c[1] = cmd; - pending_commands.offer(c); - } - } - catch (IOException e) { - Log.i(TAG, "exception in monitorWrite(), monitor died or closed the socket", e); - - try { - monitor_out.close(); - } - catch (IOException ee) { - Log.e(TAG, "exception in monitorWrite() closing output stream", ee); - } - - monitor_out = null; - } - }; - - public void resetWatch() { - start_line = 0; - end_line = 500; - start_column = 0; - end_column = 500; - }; - - public void sendScreen(char cmd) { - char lines = (char)(buffer.height & 0x0000ffff); - char columns = (char)(buffer.width & 0x0000ffff); - char[] arg = new char[4 + lines * columns]; - arg[2] = lines; - arg[3] = columns; - int base = 4; - - for (int i = 0; i < lines; i++) { - System.arraycopy(buffer.charArray[buffer.screenBase + i], 0, arg, base, columns); - base += columns; - } - - monitorWrite(cmd, arg); - resetWatch(); - } - - public synchronized void activate() { - sendScreen(MONITOR_CMD_ACTIVATE); - cursorMoved(CURSOR_SCREEN_CHANGE); - } - - public synchronized void keyState(boolean down) { - char[] arg = new char[3]; - arg[2] = (char)((down) ? 1 : 0); - monitorWrite(MONITOR_CMD_KEYSTATE, arg); - } - - public synchronized void cursorMove(int l, int c) { - if ((to_line != l) || (to_column != c)) moved = true; - - to_line = l; - to_column = c; - } - - public void cursorMoved(char why) { - char[] arg = new char[5]; - arg[2] = (char)(to_line & 0x0000ffff); - arg[3] = (char)(to_column & 0x0000ffff); - arg[4] = why; - monitorWrite(MONITOR_CMD_CURSORMOVE, arg); - moved = false; - } - - public void testMoved() { - if (moved) cursorMoved(CURSOR_USER_KEY); - } - - public synchronized void testChanged() { - if (modified) { - modified = false; - sendScreen(MONITOR_CMD_SCREENCHANGE); - cursorMoved(CURSOR_SCREEN_CHANGE); - } - else { - if (moved) cursorMoved(CURSOR_SCREEN_CHANGE); - } - } - - public synchronized void screenChanged(int llow, int lhigh, int clow, int chigh) { - if ((start_line <= lhigh) && (llow <= end_line) && (start_column <= chigh) && (clow <= end_column)) { - modified = true; - } - } - - public synchronized void screenChanged(int l, int c) { - screenChanged(l, l, c, c); - } - - public synchronized void setField(int l, int c, char[] data, int offset) { - int len = data.length - offset; - char[] da = new char[len]; - System.arraycopy(data, offset, da, 0, len); - Log.i(TAG, String.format("setField(line %d, col %d, value %s)", l, c, new String(da))); - - if ((l > 60000) || (c > 60000)) { - l = -1; - c = -1; - } - else { - // ignore setfield outside screen boundaries - if ((l >= buffer.height) || (c + len > buffer.width)) return; - } - - buffer.setField(l, c, da); - } - - public synchronized void showUrl(char [] data, int offset) { - char[] da = new char[data.length - offset]; - System.arraycopy(data, offset, da, 0, data.length - offset); - String url = new String(da); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - parent.startActivity(intent); - } - - public synchronized void getField(int l, int c, int len) { - Log.i(TAG, String.format("getField(line %d, col %d, len %d)", l, c, len)); - char[] arg2 = new char[4 + len]; - arg2[2] = (char)(l & 0x0000ffff); - arg2[3] = (char)(c & 0x0000ffff); - int base = 4; - - if ((l >= buffer.height) || (c + len > buffer.width)) { - Arrays.fill(arg2, base, base + len, ' '); - } - else { - System.arraycopy(buffer.charArray[buffer.screenBase + l], c, arg2, base, len); - } - - char[] da = new char[len]; - System.arraycopy(arg2, base, da, 0, len); - Log.i(TAG, String.format("getField value %s", new String(da))); - - monitorWrite(MONITOR_CMD_FIELDVALUE, arg2); - } - - public synchronized void screenWatch(int l, int c, int len) { - Log.i(TAG, String.format("screenWatch(line %d, col %d, len %d)", l, c, len)); - start_line = l; - end_line = l; - start_column = c; - end_column = c + len - 1; - } - - public synchronized void depress(int vk_key) { - Log.i(TAG, String.format("depress(%d)", vk_key)); - Integer x = keymap.get(new Integer(vk_key)); - - if (x != null) buffer.keyDepressed(x, ' ', 0); - } - - public synchronized void switchSession() { - Log.i(TAG, "switchSession()"); - Intent intent = new Intent(parent, ConsoleActivity.class); - intent.setAction(Intent.ACTION_VIEW); - intent.setData(host.getUri()); - parent.startActivity(intent); - } - - - public synchronized void cursorRequest() { - cursorMoved(CURSOR_REQUESTED); - } - -}
--- a/src/com/five_ten_sg/connectbot/transport/AbsTransport.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,413 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.transport; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.bean.PortForwardBean; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalKeyListener; -import com.five_ten_sg.connectbot.service.TerminalManager; -import android.content.Context; -import android.net.Uri; -import android.util.Log; -import de.mud.terminal.vt320; - -/** - * @author Kenny Root - * - */ -public abstract class AbsTransport { - protected String TAG; - protected TerminalManager manager; - protected TerminalBridge bridge; - protected String homeDirectory; - protected HostBean host; - protected vt320 buffer = null; - protected String emulation; - - class vt320Default extends vt320 { - @Override - public void debug(String s) { - Log.d(TAG, s); - } - - // monitor injecting a field - //@Override - //public void setField(int l, int c, char [] data) - // implementation in the base vt320 - - // terminal key listener found special key, send notification to monitor - @Override - public void monitorKey(boolean down) { - if (bridge.monitor != null) bridge.monitor.keyState(down); - } - - // terminal key listener sending to the host - @Override - public void write(byte[] b) { - try { - AbsTransport.this.write(b); - } - catch (IOException e) { - Log.e(TAG, "Problem writing outgoing data in vt320() thread", e); - } - } - @Override - public void write(int b) { - try { - AbsTransport.this.write(b); - } - catch (IOException e) { - Log.e(TAG, "Problem writing outgoing data in vt320() thread", e); - } - } - - // We don't use telnet sequences. - @Override - public void sendTelnetCommand(byte cmd) { - } - // We don't want remote to resize our window. - @Override - public void setWindowSize(int c, int r) { - } - // play beep noise - @Override - public void beep() { - if ((bridge.parent != null) && (bridge.parent.isShown())) - manager.playBeep(); - else - manager.sendActivityNotification(host); - } - - // test for changed screen contents - @Override - public void testChanged() { - if (bridge.monitor != null) bridge.monitor.testChanged(); - } - // relay socket writing to the screen - // bridge.monitor placement of new characters - @Override - public void putChar(int c, int l, char ch, int attributes) { - if (bridge.monitor != null) bridge.monitor.screenChanged(l, c); - - super.putChar(c, l, ch, attributes); - } - @Override - public void insertChar(int c, int l, char ch, int attributes) { - if (bridge.monitor != null) bridge.monitor.screenChanged(l, l, c, width - 1); - - super.insertChar(c, l, ch, attributes); - } - @Override - public void insertLine(int l, int n, boolean scrollDown) { - if (bridge.monitor != null) { - if (scrollDown) bridge.monitor.screenChanged(l, height - 1, 0, width - 1); - else bridge.monitor.screenChanged(0, l, 0, width - 1); - } - - super.insertLine(l, n, scrollDown); - } - @Override - public void deleteLine(int l) { - if (bridge.monitor != null) bridge.monitor.screenChanged(l, height - 1, 0, width - 1); - - super.deleteLine(l); - } - @Override - public void deleteChar(int c, int l) { - if (bridge.monitor != null) bridge.monitor.screenChanged(l, l, c, width - 1); - - super.deleteChar(c, l); - } - @Override - public void setCursorPosition(int c, int l) { - if (bridge.monitor != null) bridge.monitor.cursorMove(l, c); - - super.setCursorPosition(c, l); - } - - }; - - - public AbsTransport() {} - - /** - * @return protocol part of the URI - */ - public static String getProtocolName() { - return "unknown"; - } - - /** - * Encode the current transport into a URI that can be passed via intent calls. - * @return URI to host - */ - public abstract Uri getUri(String input); - - - /** - * Causes transport to connect to the target host. After connecting but before a - * session is started, must call back to {@link TerminalBridge#onConnected()}. - * After that call a session may be opened. - */ - public abstract void connect(); - - /** - * Checks if read() will block. If there are no bytes remaining in - * the underlying transport, return true. - */ - public abstract boolean willBlock(); - - /** - * Reads from the transport. Transport must support reading into a byte array - * <code>buffer</code> at the start of <code>offset</code> and a maximum of - * <code>length</code> bytes. If the remote host disconnects, throw an - * {@link IOException}. - * @param buffer byte buffer to store read bytes into - * @param offset where to start writing in the buffer - * @param length maximum number of bytes to read - * @return number of bytes read - * @throws IOException when remote host disconnects - */ - public abstract int read(byte[] buffer, int offset, int length) throws IOException; - - /** - * Writes to the transport. If the host is not yet connected, simply return without - * doing anything. An {@link IOException} should be thrown if there is an error after - * connection. - * @param buffer bytes to write to transport - * @throws IOException when there is a problem writing after connection - */ - public abstract void write(byte[] buffer) throws IOException; - - /** - * Writes to the transport. See {@link #write(byte[])} for behavior details. - * @param c character to write to the transport - * @throws IOException when there is a problem writing after connection - */ - public abstract void write(int c) throws IOException; - - /** - * Flushes the write commands to the transport. - * @throws IOException when there is a problem writing after connection - */ - public abstract void flush() throws IOException; - - /** - * Closes the connection to the terminal. Note that the resulting failure to read - * should call {@link TerminalBridge#dispatchDisconnect(boolean)}. - */ - public abstract void close(); - - /** - * Tells the transport what dimensions the display is currently - * @param columns columns of text - * @param rows rows of text - * @param width width in pixels - * @param height height in pixels - */ - public abstract void setDimensions(int columns, int rows, int width, int height); - - public void setOptions(Map<String, String> options) { - // do nothing - } - - public Map<String, String> getOptions() { - return null; - } - - public void setCompression(boolean compression) { - // do nothing - } - - public void setHttpproxy(String httpproxy) { - // do nothing - } - - public void setUseAuthAgent(String useAuthAgent) { - // do nothing - } - - public String getEmulation() { - return emulation; - } - - protected vt320 setupTransportBuffer() { - int scrollback = (host.getWantSession()) ? manager.getScrollback() : 0; - buffer.setBufferSize(scrollback); - buffer.setDisplay(bridge); - return buffer; - } - - public vt320 getTransportBuffer() { - buffer = new vt320Default(); - return setupTransportBuffer(); - } - - public void setLinks(TerminalManager manager, TerminalBridge bridge, String homeDirectory, HostBean host, String emulation) { - this.manager = manager; - this.bridge = bridge; - this.homeDirectory = homeDirectory; - this.host = host; - this.emulation = emulation; - } - - /** - * Whether or not this transport type can forward ports. - * @return true on ability to forward ports - */ - public boolean canForwardPorts() { - return false; - } - - /** - * Adds the {@link PortForwardBean} to the list. - * @param portForward the port forward bean to add - * @return true on successful addition - */ - public boolean addPortForward(PortForwardBean portForward) { - return false; - } - - /** - * Enables a port forward member. After calling this method, the port forward should - * be operational iff it could be enabled by the transport. - * @param portForward member of our current port forwards list to enable - * @return true on successful port forward setup - */ - public boolean enablePortForward(PortForwardBean portForward) { - return false; - } - - /** - * Disables a port forward member. After calling this method, the port forward should - * be non-functioning iff it could be disabled by the transport. - * @param portForward member of our current port forwards list to enable - * @return true on successful port forward tear-down - */ - public boolean disablePortForward(PortForwardBean portForward) { - return false; - } - - /** - * Removes the {@link PortForwardBean} from the available port forwards. - * @param portForward the port forward bean to remove - * @return true on successful removal - */ - public boolean removePortForward(PortForwardBean portForward) { - return false; - } - - /** - * Gets a list of the {@link PortForwardBean} currently used by this transport. - * @return the list of port forwards - */ - public List<PortForwardBean> getPortForwards() { - return null; - } - - /** - * Whether or not this transport type can transfer files. - * @return true on ability to transfer files - */ - public boolean canTransferFiles() { - return false; - } - - /** - * Downloads the specified remote file to a local folder. - * @param remoteFile The path to the remote file to be downloaded. Must be non-null. - * @param localFolder The path to local folder. Null = default external storage folder. - * @return true on success, false on failure - */ - public boolean downloadFile(String remoteFile, String localFolder) { - return false; - } - - /** - * Uploads the specified local file to the remote host. - * @param localFile The path to the local file to be uploaded. Must be non-null. - * @param remoteFolder The path to the remote directory. Null == default remote directory. - * @return true on success, false on failure - */ - public boolean uploadFile(String localFile, String remoteFile, - String remoteFolder, String mode) { - return false; - } - - - /** - * @return int default port for protocol - */ - public abstract int getDefaultPort(); - public abstract boolean isConnected(); - public abstract boolean isSessionOpen(); - public abstract boolean isAuthenticated(); - - /** - * @param username - * @param hostname - * @param port - * @return - */ - public abstract String getDefaultNickname(String username, String hostname, int port); - - /** - * @param uri - * @param selectionKeys - * @param selectionValues - */ - public abstract void getSelectionArgs(Uri uri, Map<String, String> selection); - - /** - * @param uri - * @return - */ - public abstract HostBean createHost(Uri uri); - - /** - * @param context context containing the correct resources - * @return string that hints at the format for connection - */ - public abstract String getFormatHint(Context context); - - /** - * @return do we use the network - */ - public abstract boolean usesNetwork(); - - /** - * @return do we need a relay object to read from the transport - * and send the data into the vt320 buffer - */ - public boolean needsRelay() { - return true; - } - - /** - * @return a key listener - */ - public TerminalKeyListener getTerminalKeyListener() { - return new TerminalKeyListener(manager, bridge, buffer, host.getEncoding()); - } - -}
--- a/src/com/five_ten_sg/connectbot/transport/Local.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,226 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.transport; - -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Map; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.util.HostDatabase; -import android.content.Context; -import android.net.Uri; -import android.util.Log; - -import com.google.ase.Exec; - -/** - * @author Kenny Root - * - */ -public class Local extends AbsTransport { - private static final String TAG = "ConnectBot.Local"; - private static final String PROTOCOL = "local"; - private static final String DEFAULT_URI = "local:#Local"; - - private FileDescriptor shellFd; - private FileInputStream is; - private FileOutputStream os; - - /** - * - */ - public Local() { - } - - - public static String getProtocolName() { - return PROTOCOL; - } - - - public Uri getUri(String input) { - Uri uri = Uri.parse(DEFAULT_URI); - - if (input != null && input.length() > 0) { - uri = uri.buildUpon().fragment(input).build(); - } - - return uri; - } - - - @Override - public void connect() { - int[] pids = new int[1]; - - try { - shellFd = Exec.createSubprocess("/system/bin/sh", "-", null, pids); - } - catch (Exception e) { - bridge.outputLine(manager.res.getString(R.string.local_shell_unavailable)); - Log.e(TAG, "Cannot start local shell", e); - return; - } - - final int shellPid = pids[0]; - Runnable exitWatcher = new Runnable() { - public void run() { - Exec.waitFor(shellPid); - bridge.dispatchDisconnect(false); - } - }; - Thread exitWatcherThread = new Thread(exitWatcher); - exitWatcherThread.setName("LocalExitWatcher"); - exitWatcherThread.setDaemon(true); - exitWatcherThread.start(); - is = new FileInputStream(shellFd); - os = new FileOutputStream(shellFd); - bridge.onConnected(); - } - - - @Override - public boolean willBlock() { - if (is == null) return true; - - try { - return is.available() == 0; - } - catch (Exception e) { - return true; - } - } - - @Override - public int read(byte[] buffer, int start, int len) throws IOException { - if (is == null) { - bridge.dispatchDisconnect(false); - throw new IOException("session closed"); - } - - return is.read(buffer, start, len); - } - - @Override - public void write(byte[] buffer) throws IOException { - if (os != null) - os.write(buffer); - } - - @Override - public void write(int c) throws IOException { - if (os != null) - os.write(c); - } - - @Override - public void flush() throws IOException { - os.flush(); - } - - @Override - public void close() { - try { - if (os != null) { - os.close(); - os = null; - } - - if (is != null) { - is.close(); - is = null; - } - } - catch (IOException e) { - Log.e(TAG, "Couldn't close shell", e); - } - } - - @Override - public void setDimensions(int columns, int rows, int width, int height) { - try { - Exec.setPtyWindowSize(shellFd, rows, columns, width, height); - } - catch (Exception e) { - Log.e(TAG, "Couldn't resize pty", e); - } - } - - @Override - public int getDefaultPort() { - return 0; - } - - @Override - public boolean isConnected() { - return is != null && os != null; - } - - @Override - public boolean isSessionOpen() { - return isConnected(); - } - - @Override - public boolean isAuthenticated() { - return isConnected(); - } - - @Override - public String getDefaultNickname(String username, String hostname, int port) { - return DEFAULT_URI; - } - - @Override - public void getSelectionArgs(Uri uri, Map<String, String> selection) { - selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL); - selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment()); - } - - @Override - public HostBean createHost(Uri uri) { - HostBean host = new HostBean(); - host.setProtocol(PROTOCOL); - String nickname = uri.getFragment(); - - if (nickname == null || nickname.length() == 0) { - host.setNickname(getDefaultNickname(host.getUsername(), - host.getHostname(), host.getPort())); - } - else { - host.setNickname(uri.getFragment()); - } - - return host; - } - - public String getFormatHint(Context context) { - return context.getString(R.string.hostpref_nickname_title); - } - - @Override - public boolean usesNetwork() { - return false; - } -}
--- a/src/com/five_ten_sg/connectbot/transport/SSH.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1152 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.transport; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.URL; -import java.net.MalformedURLException; -import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.DSAPublicKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.bean.PortForwardBean; -import com.five_ten_sg.connectbot.bean.PubkeyBean; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.service.TerminalManager.KeyHolder; -import com.five_ten_sg.connectbot.util.HostDatabase; -import com.five_ten_sg.connectbot.util.PubkeyDatabase; -import com.five_ten_sg.connectbot.util.PubkeyUtils; -import android.content.Context; -import android.net.Uri; -import android.os.Environment; -import android.util.Log; - -import ch.ethz.ssh2.AuthAgentCallback; -import ch.ethz.ssh2.ChannelCondition; -import ch.ethz.ssh2.Connection; -import ch.ethz.ssh2.ConnectionInfo; -import ch.ethz.ssh2.ConnectionMonitor; -import ch.ethz.ssh2.DynamicPortForwarder; -import ch.ethz.ssh2.InteractiveCallback; -import ch.ethz.ssh2.KnownHosts; -import ch.ethz.ssh2.LocalPortForwarder; -import ch.ethz.ssh2.SCPClient; -import ch.ethz.ssh2.ServerHostKeyVerifier; -import ch.ethz.ssh2.Session; -import ch.ethz.ssh2.HTTPProxyData; -import ch.ethz.ssh2.HTTPProxyException; -import ch.ethz.ssh2.crypto.PEMDecoder; -import ch.ethz.ssh2.signature.DSASHA1Verify; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; -import ch.ethz.ssh2.signature.RSASHA1Verify; - -/** - * @author Kenny Root - * - */ -public class SSH extends AbsTransport implements ConnectionMonitor, InteractiveCallback, AuthAgentCallback { - private static final String PROTOCOL = "ssh"; - private static final String TAG = "ConnectBot.SSH"; - private static final int DEFAULT_PORT = 22; - - private static final String AUTH_PUBLICKEY = "publickey", - AUTH_PASSWORD = "password", - AUTH_KEYBOARDINTERACTIVE = "keyboard-interactive"; - - private final static int AUTH_TRIES = 20; - - static final Pattern hostmask; - static { - hostmask = Pattern.compile("^(.+)@([0-9a-z.-]+)(:(\\d+))?$", Pattern.CASE_INSENSITIVE); - } - - private boolean compression = false; - private String httpproxy = null; - private volatile boolean authenticated = false; - private volatile boolean connected = false; - private volatile boolean sessionOpen = false; - - private boolean pubkeysExhausted = false; - private boolean interactiveCanContinue = true; - - private Connection connection; - private Session session; - private ConnectionInfo connectionInfo; - - private OutputStream stdin; - private InputStream stdout; - private InputStream stderr; - - private static final int conditions = ChannelCondition.STDOUT_DATA - | ChannelCondition.STDERR_DATA - | ChannelCondition.CLOSED - | ChannelCondition.EOF; - - private List<PortForwardBean> portForwards = new LinkedList<PortForwardBean>(); - - private int columns; - private int rows; - - private int width; - private int height; - - private String useAuthAgent = HostDatabase.AUTHAGENT_NO; - private String agentLockPassphrase; - - public class HostKeyVerifier implements ServerHostKeyVerifier { - public boolean verifyServerHostKey(String hostname, int port, - String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { - // read in all known hosts from hostdb - KnownHosts hosts = manager.hostdb.getKnownHosts(); - Boolean result; - String matchName = String.format(Locale.US, "%s:%d", hostname, port); - String fingerprint = KnownHosts.createHexFingerprint(serverHostKeyAlgorithm, serverHostKey); - String algorithmName; - - if ("ssh-rsa".equals(serverHostKeyAlgorithm)) - algorithmName = "RSA"; - else if ("ssh-dss".equals(serverHostKeyAlgorithm)) - algorithmName = "DSA"; - else if (serverHostKeyAlgorithm.startsWith("ecdsa-sha2-")) - algorithmName = "EC"; - else - algorithmName = serverHostKeyAlgorithm; - - switch (hosts.verifyHostkey(matchName, serverHostKeyAlgorithm, serverHostKey)) { - case KnownHosts.HOSTKEY_IS_OK: - bridge.outputLine(manager.res.getString(R.string.terminal_sucess, algorithmName, fingerprint)); - return true; - - case KnownHosts.HOSTKEY_IS_NEW: - // prompt user - bridge.outputLine(manager.res.getString(R.string.host_authenticity_warning, hostname)); - bridge.outputLine(manager.res.getString(R.string.host_fingerprint, algorithmName, fingerprint)); - result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_continue_connecting)); - - if (result == null) return false; - - if (result.booleanValue()) { - // save this key in known database - manager.hostdb.saveKnownHost(hostname, port, serverHostKeyAlgorithm, serverHostKey); - } - - return result.booleanValue(); - - case KnownHosts.HOSTKEY_HAS_CHANGED: - String header = String.format("@ %s @", - manager.res.getString(R.string.host_verification_failure_warning_header)); - char[] atsigns = new char[header.length()]; - Arrays.fill(atsigns, '@'); - String border = new String(atsigns); - bridge.outputLine(border); - bridge.outputLine(manager.res.getString(R.string.host_verification_failure_warning)); - bridge.outputLine(border); - bridge.outputLine(String.format(manager.res.getString(R.string.host_fingerprint), - algorithmName, fingerprint)); - // Users have no way to delete keys, so we'll prompt them for now. - result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_continue_connecting)); - - if (result == null) return false; - - if (result.booleanValue()) { - // save this key in known database - manager.hostdb.saveKnownHost(hostname, port, serverHostKeyAlgorithm, serverHostKey); - } - - return result.booleanValue(); - - default: - return false; - } - } - - } - - - public SSH() { - super(); - } - - - /** - * @return protocol part of the URI - */ - public static String getProtocolName() { - return PROTOCOL; - } - - - public Uri getUri(String input) { - Matcher matcher = hostmask.matcher(input); - - if (!matcher.matches()) - return null; - - StringBuilder sb = new StringBuilder(); - sb.append(PROTOCOL) - .append("://") - .append(Uri.encode(matcher.group(1))) - .append('@') - .append(matcher.group(2)); - String portString = matcher.group(4); - int port = DEFAULT_PORT; - - if (portString != null) { - try { - port = Integer.parseInt(portString); - - if (port < 1 || port > 65535) { - port = DEFAULT_PORT; - } - } - catch (NumberFormatException nfe) { - // Keep the default port - } - } - - if (port != DEFAULT_PORT) { - sb.append(':') - .append(port); - } - - sb.append("/#") - .append(Uri.encode(input)); - Uri uri = Uri.parse(sb.toString()); - return uri; - } - - - private void authenticate() { - try { - if (connection.authenticateWithNone(host.getUsername())) { - finishConnection(); - return; - } - } - catch (Exception e) { - Log.d(TAG, "Host does not support 'none' authentication."); - } - - bridge.outputLine(manager.res.getString(R.string.terminal_auth)); - - try { - long pubkeyId = host.getPubkeyId(); - - if (!pubkeysExhausted && - pubkeyId != HostDatabase.PUBKEYID_NEVER && - connection.isAuthMethodAvailable(host.getUsername(), AUTH_PUBLICKEY)) { - // if explicit pubkey defined for this host, then prompt for password as needed - // otherwise just try all in-memory keys held in terminalmanager - if (pubkeyId == HostDatabase.PUBKEYID_ANY) { - // try each of the in-memory keys - bridge.outputLine(manager.res - .getString(R.string.terminal_auth_pubkey_any)); - - for (Entry<String, KeyHolder> entry : manager.loadedKeypairs.entrySet()) { - if (entry.getValue().bean.isConfirmUse() - && !promptForPubkeyUse(entry.getKey())) - continue; - - if (this.tryPublicKey(host.getUsername(), entry.getKey(), - entry.getValue().pair)) { - finishConnection(); - break; - } - } - } - else { - bridge.outputLine(manager.res.getString(R.string.terminal_auth_pubkey_specific)); - // use a specific key for this host, as requested - PubkeyBean pubkey = manager.pubkeydb.findPubkeyById(pubkeyId); - - if (pubkey == null) - bridge.outputLine(manager.res.getString(R.string.terminal_auth_pubkey_invalid)); - else if (tryPublicKey(pubkey)) - finishConnection(); - } - - pubkeysExhausted = true; - } - else if (interactiveCanContinue && - connection.isAuthMethodAvailable(host.getUsername(), AUTH_KEYBOARDINTERACTIVE)) { - // this auth method will talk with us using InteractiveCallback interface - // it blocks until authentication finishes - bridge.outputLine(manager.res.getString(R.string.terminal_auth_ki)); - interactiveCanContinue = false; - - if (connection.authenticateWithKeyboardInteractive(host.getUsername(), this)) { - finishConnection(); - } - else { - bridge.outputLine(manager.res.getString(R.string.terminal_auth_ki_fail)); - } - } - else if (connection.isAuthMethodAvailable(host.getUsername(), AUTH_PASSWORD)) { - bridge.outputLine(manager.res.getString(R.string.terminal_auth_pass)); - String password = bridge.getPromptHelper().requestPasswordPrompt(null, - manager.res.getString(R.string.prompt_password)); - - if (password != null - && connection.authenticateWithPassword(host.getUsername(), password)) { - finishConnection(); - } - else { - bridge.outputLine(manager.res.getString(R.string.terminal_auth_pass_fail)); - } - } - else { - bridge.outputLine(manager.res.getString(R.string.terminal_auth_fail)); - } - } - catch (IllegalStateException e) { - Log.e(TAG, "Connection went away while we were trying to authenticate", e); - return; - } - catch (Exception e) { - Log.e(TAG, "Problem during handleAuthentication()", e); - } - } - - - /** - * Attempt connection with database row pointed to by cursor. - * @param cursor - * @return true for successful authentication - * @throws NoSuchAlgorithmException - * @throws InvalidKeySpecException - * @throws IOException - */ - private boolean tryPublicKey(PubkeyBean pubkey) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { - KeyPair pair = null; - - if (manager.isKeyLoaded(pubkey.getNickname())) { - // load this key from memory if its already there - Log.d(TAG, String.format("Found unlocked key '%s' already in-memory", pubkey.getNickname())); - - if (pubkey.isConfirmUse()) { - if (!promptForPubkeyUse(pubkey.getNickname())) - return false; - } - - pair = manager.getKey(pubkey.getNickname()); - } - else { - // otherwise load key from database and prompt for password as needed - String password = null; - - if (pubkey.isEncrypted()) { - password = bridge.getPromptHelper().requestPasswordPrompt(null, - manager.res.getString(R.string.prompt_pubkey_password, pubkey.getNickname())); - - // Something must have interrupted the prompt. - if (password == null) - return false; - } - - if (PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType())) { - // load specific key using pem format - pair = PEMDecoder.decode(new String(pubkey.getPrivateKey()).toCharArray(), password); - } - else { - // load using internal generated format - PrivateKey privKey; - - try { - privKey = PubkeyUtils.decodePrivate(pubkey.getPrivateKey(), - pubkey.getType(), password); - } - catch (Exception e) { - String message = String.format("Bad password for key '%s'. Authentication failed.", pubkey.getNickname()); - Log.e(TAG, message, e); - bridge.outputLine(message); - return false; - } - - PublicKey pubKey = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); - // convert key to trilead format - pair = new KeyPair(pubKey, privKey); - Log.d(TAG, "Unlocked key " + PubkeyUtils.formatKey(pubKey)); - } - - Log.d(TAG, String.format("Unlocked key '%s'", pubkey.getNickname())); - // save this key in memory - manager.addKey(pubkey, pair); - } - - return tryPublicKey(host.getUsername(), pubkey.getNickname(), pair); - } - - - private boolean tryPublicKey(String username, String keyNickname, KeyPair pair) throws IOException { - //bridge.outputLine(String.format("Attempting 'publickey' with key '%s' [%s]...", keyNickname, trileadKey.toString())); - boolean success = connection.authenticateWithPublicKey(username, pair); - - if (!success) - bridge.outputLine(manager.res.getString(R.string.terminal_auth_pubkey_fail, keyNickname)); - - return success; - } - - - /** - * Internal method to request actual PTY terminal once we've finished - * authentication. If called before authenticated, it will just fail. - */ - private void finishConnection() { - authenticated = true; - - for (PortForwardBean portForward : portForwards) { - try { - enablePortForward(portForward); - bridge.outputLine(manager.res.getString(R.string.terminal_enable_portfoward, portForward.getDescription())); - } - catch (Exception e) { - Log.e(TAG, "Error setting up port forward during connect", e); - } - } - - if (!host.getWantSession()) { - bridge.outputLine(manager.res.getString(R.string.terminal_no_session)); - bridge.onConnected(); - return; - } - - try { - session = connection.openSession(); - - if (!useAuthAgent.equals(HostDatabase.AUTHAGENT_NO)) - session.requestAuthAgentForwarding(this); - - if (host.getWantX11Forward()) { - try { - session.requestX11Forwarding(host.getX11Host(), host.getX11Port(), null, false); - } - catch (IOException e2) { - Log.e(TAG, "Problem while trying to setup X11 forwarding in finishConnection()", e2); - } - } - - session.requestPTY(getEmulation(), columns, rows, width, height, null); - session.startShell(); - stdin = session.getStdin(); - stdout = session.getStdout(); - stderr = session.getStderr(); - sessionOpen = true; - bridge.onConnected(); - } - catch (IOException e1) { - Log.e(TAG, "Problem while trying to create PTY in finishConnection()", e1); - } - } - - - @Override - public void connect() { - connection = new Connection(host.getHostname(), host.getPort()); - connection.addConnectionMonitor(this); - - try { - connection.setCompression(compression); - } - catch (IOException e) { - Log.e(TAG, "Could not enable compression!", e); - } - - if (httpproxy != null && httpproxy.length() > 0) { - Log.d(TAG, "Want HTTP Proxy: " + httpproxy, null); - - try { - URL u; - - if (httpproxy.startsWith("http://")) { - u = new URL(httpproxy); - } - else { - u = new URL("http://" + httpproxy); - } - - connection.setProxyData(new HTTPProxyData( - u.getHost(), - u.getPort(), - u.getUserInfo(), - u.getAuthority())); - bridge.outputLine("Connecting via proxy: " + httpproxy); - } - catch (MalformedURLException e) { - Log.e(TAG, "Could not parse proxy " + httpproxy, e); - // Display the reason in the text. - bridge.outputLine("Bad proxy URL: " + httpproxy); - onDisconnect(); - return; - } - } - - try { - /* Uncomment when debugging SSH protocol: - DebugLogger logger = new DebugLogger() { - - public void log(int level, String className, String message) { - Log.d("SSH", message); - } - - }; - Logger.enabled = true; - Logger.logger = logger; - */ - connectionInfo = connection.connect(new HostKeyVerifier()); - connected = true; - - if (connectionInfo.clientToServerCryptoAlgorithm - .equals(connectionInfo.serverToClientCryptoAlgorithm) - && connectionInfo.clientToServerMACAlgorithm - .equals(connectionInfo.serverToClientMACAlgorithm)) { - bridge.outputLine(manager.res.getString(R.string.terminal_using_algorithm, - connectionInfo.clientToServerCryptoAlgorithm, - connectionInfo.clientToServerMACAlgorithm)); - } - else { - bridge.outputLine(manager.res.getString( - R.string.terminal_using_c2s_algorithm, - connectionInfo.clientToServerCryptoAlgorithm, - connectionInfo.clientToServerMACAlgorithm)); - bridge.outputLine(manager.res.getString( - R.string.terminal_using_s2c_algorithm, - connectionInfo.serverToClientCryptoAlgorithm, - connectionInfo.serverToClientMACAlgorithm)); - } - } - catch (HTTPProxyException e) { - Log.e(TAG, "Failed to connect to HTTP Proxy", e); - // Display the reason in the text. - bridge.outputLine("Failed to connect to HTTP Proxy."); - onDisconnect(); - return; - } - catch (IOException e) { - Log.e(TAG, "Problem in SSH connection thread during authentication", e); - // Display the reason in the text. - Throwable t = e.getCause(); - String m = (t == null) ? e.getMessage() : t.getMessage(); - bridge.outputLine(m); - onDisconnect(); - return; - } - - try { - // enter a loop to keep trying until authentication - int tries = 0; - - while (connected && !connection.isAuthenticationComplete() && tries++ < AUTH_TRIES) { - authenticate(); - // sleep to make sure we dont kill system - Thread.sleep(1000); - } - } - catch (Exception e) { - Log.e(TAG, "Problem in SSH connection thread during authentication", e); - } - } - - - @Override - public boolean willBlock() { - if (stdout == null) return true; - - try { - return stdout.available() == 0; - } - catch (Exception e) { - return true; - } - } - - - @Override - public int read(byte[] buffer, int start, int len) throws IOException { - int bytesRead = 0; - - if (session == null) - return 0; - - int newConditions = session.waitForCondition(conditions, 0); - - if ((newConditions & ChannelCondition.STDOUT_DATA) != 0) { - bytesRead = stdout.read(buffer, start, len); - } - - if ((newConditions & ChannelCondition.STDERR_DATA) != 0) { - byte discard[] = new byte[256]; - - while (stderr.available() > 0) { - stderr.read(discard); - } - } - - if ((newConditions & ChannelCondition.EOF) != 0) { - onDisconnect(); - throw new IOException("Remote end closed connection"); - } - - return bytesRead; - } - - - @Override - public void write(byte[] buffer) throws IOException { - if (stdin != null) - stdin.write(buffer); - } - - - @Override - public void write(int c) throws IOException { - if (stdin != null) - stdin.write(c); - } - - - @Override - public void flush() throws IOException { - if (stdin != null) - stdin.flush(); - } - - - public void connectionLost(Throwable reason) { - onDisconnect(); - } - - - private void onDisconnect() { - close(); - bridge.dispatchDisconnect(false); - } - - - @Override - public void close() { - connected = false; - - if (session != null) { - session.close(); - session = null; - } - - if (connection != null) { - connection.close(); - connection = null; - } - } - - - @Override - public void setDimensions(int columns, int rows, int width, int height) { - this.columns = columns; - this.rows = rows; - - if (sessionOpen) { - try { - session.resizePTY(columns, rows, width, height); - } - catch (IOException e) { - Log.e(TAG, "Couldn't send resize PTY packet", e); - } - } - } - - - @Override - public void setOptions(Map<String, String> options) { - if (options.containsKey("compression")) - compression = Boolean.parseBoolean(options.get("compression")); - - if (options.containsKey("httpproxy")) - httpproxy = options.get("httpproxy"); - } - - - @Override - public Map<String, String> getOptions() { - Map<String, String> options = new HashMap<String, String>(); - options.put("compression", Boolean.toString(compression)); - - if (httpproxy != null) - options.put("httpproxy", httpproxy); - - return options; - } - - - @Override - public void setCompression(boolean compression) { - this.compression = compression; - } - - - @Override - public void setHttpproxy(String httpproxy) { - this.httpproxy = httpproxy; - } - - - @Override - public void setUseAuthAgent(String useAuthAgent) { - this.useAuthAgent = useAuthAgent; - } - - @Override - public boolean canForwardPorts() { - return true; - } - - @Override - public List<PortForwardBean> getPortForwards() { - return portForwards; - } - - @Override - public boolean addPortForward(PortForwardBean portForward) { - return portForwards.add(portForward); - } - - @Override - public boolean removePortForward(PortForwardBean portForward) { - // Make sure we don't have a phantom forwarder. - disablePortForward(portForward); - return portForwards.remove(portForward); - } - - @Override - public boolean enablePortForward(PortForwardBean portForward) { - if (!portForwards.contains(portForward)) { - Log.e(TAG, "Attempt to enable port forward not in list"); - return false; - } - - if (!authenticated) - return false; - - if (HostDatabase.PORTFORWARD_LOCAL.equals(portForward.getType())) { - LocalPortForwarder lpf = null; - - try { - lpf = connection.createLocalPortForwarder( - new InetSocketAddress(InetAddress.getLocalHost(), portForward.getSourcePort()), - portForward.getDestAddr(), portForward.getDestPort()); - } - catch (Exception e) { - Log.e(TAG, "Could not create local port forward", e); - return false; - } - - if (lpf == null) { - Log.e(TAG, "returned LocalPortForwarder object is null"); - return false; - } - - portForward.setIdentifier(lpf); - portForward.setEnabled(true); - return true; - } - else if (HostDatabase.PORTFORWARD_REMOTE.equals(portForward.getType())) { - try { - connection.requestRemotePortForwarding("", portForward.getSourcePort(), portForward.getDestAddr(), portForward.getDestPort()); - } - catch (Exception e) { - Log.e(TAG, "Could not create remote port forward", e); - return false; - } - - portForward.setEnabled(true); - return true; - } - else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(portForward.getType())) { - DynamicPortForwarder dpf = null; - - try { - dpf = connection.createDynamicPortForwarder( - new InetSocketAddress(InetAddress.getLocalHost(), portForward.getSourcePort())); - } - catch (Exception e) { - Log.e(TAG, "Could not create dynamic port forward", e); - return false; - } - - portForward.setIdentifier(dpf); - portForward.setEnabled(true); - return true; - } - else { - // Unsupported type - Log.e(TAG, String.format("attempt to forward unknown type %s", portForward.getType())); - return false; - } - } - - @Override - public boolean disablePortForward(PortForwardBean portForward) { - if (!portForwards.contains(portForward)) { - Log.e(TAG, "Attempt to disable port forward not in list"); - return false; - } - - if (!authenticated) - return false; - - if (HostDatabase.PORTFORWARD_LOCAL.equals(portForward.getType())) { - LocalPortForwarder lpf = null; - lpf = (LocalPortForwarder)portForward.getIdentifier(); - - if (!portForward.isEnabled() || lpf == null) { - Log.d(TAG, String.format("Could not disable %s; it appears to be not enabled or have no handler", portForward.getNickname())); - return false; - } - - portForward.setEnabled(false); - - try { - lpf.close(); - } - catch (IOException e) { - Log.e(TAG, "Could not stop local port forwarder, setting enabled to false", e); - return false; - } - - return true; - } - else if (HostDatabase.PORTFORWARD_REMOTE.equals(portForward.getType())) { - portForward.setEnabled(false); - - try { - connection.cancelRemotePortForwarding(portForward.getSourcePort()); - } - catch (IOException e) { - Log.e(TAG, "Could not stop remote port forwarding, setting enabled to false", e); - return false; - } - - return true; - } - else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(portForward.getType())) { - DynamicPortForwarder dpf = null; - dpf = (DynamicPortForwarder)portForward.getIdentifier(); - - if (!portForward.isEnabled() || dpf == null) { - Log.d(TAG, String.format("Could not disable %s; it appears to be not enabled or have no handler", portForward.getNickname())); - return false; - } - - portForward.setEnabled(false); - - try { - dpf.close(); - } - catch (IOException e) { - Log.e(TAG, "Could not stop dynamic port forwarder, setting enabled to false", e); - return false; - } - - return true; - } - else { - // Unsupported type - Log.e(TAG, String.format("attempt to forward unknown type %s", portForward.getType())); - return false; - } - } - - @Override - public boolean canTransferFiles() { - return true; - } - - @Override - public boolean downloadFile(String remoteFile, String localFolder) { - try { - SCPClient client = new SCPClient(connection); - - if (localFolder == null || localFolder == "") - localFolder = Environment.getExternalStorageDirectory().getAbsolutePath(); - - File dir = new File(localFolder); - dir.mkdirs(); - client.get(remoteFile, localFolder); - return true; - } - catch (IOException e) { - Log.e(TAG, "Could not download remote file", e); - return false; - } - } - - @Override - public boolean uploadFile(String localFile, String remoteFile, - String remoteFolder, String mode) { - try { - SCPClient client = new SCPClient(connection); - - if (remoteFolder == null) - remoteFolder = ""; - - if (remoteFile == null || remoteFile == "") - client.put(localFile, remoteFolder, mode); - else - client.put(localFile, remoteFile, remoteFolder, mode); - - return true; - } - catch (IOException e) { - Log.e(TAG, "Could not upload local file", e); - return false; - } - } - - - @Override - public int getDefaultPort() { - return DEFAULT_PORT; - } - - - @Override - public boolean isConnected() { - return connected; - } - - - @Override - public boolean isSessionOpen() { - return sessionOpen; - } - - - @Override - public boolean isAuthenticated() { - return authenticated; - } - - - @Override - public String getDefaultNickname(String username, String hostname, int port) { - if (port == DEFAULT_PORT) { - return String.format(Locale.US, "%s@%s", username, hostname); - } - else { - return String.format(Locale.US, "%s@%s:%d", username, hostname, port); - } - } - - - @Override - public void getSelectionArgs(Uri uri, Map<String, String> selection) { - selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL); - selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment()); - selection.put(HostDatabase.FIELD_HOST_HOSTNAME, uri.getHost()); - int port = uri.getPort(); - - if (port < 0) - port = DEFAULT_PORT; - - selection.put(HostDatabase.FIELD_HOST_PORT, Integer.toString(port)); - selection.put(HostDatabase.FIELD_HOST_USERNAME, uri.getUserInfo()); - } - - - @Override - public HostBean createHost(Uri uri) { - HostBean host = new HostBean(); - host.setProtocol(PROTOCOL); - host.setHostname(uri.getHost()); - int port = uri.getPort(); - - if (port < 0) - port = DEFAULT_PORT; - - host.setPort(port); - host.setUsername(uri.getUserInfo()); - String nickname = uri.getFragment(); - - if (nickname == null || nickname.length() == 0) { - host.setNickname(getDefaultNickname(host.getUsername(), - host.getHostname(), host.getPort())); - } - else { - host.setNickname(uri.getFragment()); - } - - return host; - } - - - public String getFormatHint(Context context) { - return String.format("%s@%s:%s", - context.getString(R.string.format_username), - context.getString(R.string.format_hostname), - context.getString(R.string.format_port)); - } - - - /** - * @return do we use the network - */ - @Override - public boolean usesNetwork() { - return true; - } - - - /** - * Handle challenges from keyboard-interactive authentication mode. - */ - public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) { - interactiveCanContinue = true; - String[] responses = new String[numPrompts]; - - for (int i = 0; i < numPrompts; i++) { - // request response from user for each prompt - responses[i] = bridge.promptHelper.requestPasswordPrompt(instruction, prompt[i]); - } - - return responses; - } - - public Map<String, byte[]> retrieveIdentities() { - Map<String, byte[]> pubKeys = new HashMap<String, byte[]> (manager.loadedKeypairs.size()); - - for (Entry<String, KeyHolder> entry : manager.loadedKeypairs.entrySet()) { - KeyPair pair = entry.getValue().pair; - - try { - PrivateKey privKey = pair.getPrivate(); - - if (privKey instanceof RSAPrivateKey) { - RSAPublicKey pubkey = (RSAPublicKey) pair.getPublic(); - pubKeys.put(entry.getKey(), RSASHA1Verify.encodeSSHRSAPublicKey(pubkey)); - } - else if (privKey instanceof DSAPrivateKey) { - DSAPublicKey pubkey = (DSAPublicKey) pair.getPublic(); - pubKeys.put(entry.getKey(), DSASHA1Verify.encodeSSHDSAPublicKey(pubkey)); - } - else if (privKey instanceof ECPrivateKey) { - ECPublicKey pubkey = (ECPublicKey) pair.getPublic(); - pubKeys.put(entry.getKey(), ECDSASHA2Verify.encodeSSHECDSAPublicKey(pubkey)); - } - else - continue; - } - catch (IOException e) { - continue; - } - } - - return pubKeys; - } - - public KeyPair getKeyPair(byte[] publicKey) { - String nickname = manager.getKeyNickname(publicKey); - - if (nickname == null) - return null; - - if (useAuthAgent.equals(HostDatabase.AUTHAGENT_NO)) { - Log.e(TAG, ""); - return null; - } - else if (useAuthAgent.equals(HostDatabase.AUTHAGENT_CONFIRM) || - manager.loadedKeypairs.get(nickname).bean.isConfirmUse()) { - if (!promptForPubkeyUse(nickname)) - return null; - } - - return manager.getKey(nickname); - } - - private boolean promptForPubkeyUse(String nickname) { - Boolean result = bridge.promptHelper.requestBooleanPrompt(null, - manager.res.getString(R.string.prompt_allow_agent_to_use_key, - nickname)); - return result; - } - - public boolean addIdentity(KeyPair pair, String comment, boolean confirmUse, int lifetime) { - PubkeyBean pubkey = new PubkeyBean(); -// pubkey.setType(PubkeyDatabase.KEY_TYPE_IMPORTED); - pubkey.setNickname(comment); - pubkey.setConfirmUse(confirmUse); - pubkey.setLifetime(lifetime); - manager.addKey(pubkey, pair); - return true; - } - - public boolean removeAllIdentities() { - manager.loadedKeypairs.clear(); - return true; - } - - public boolean removeIdentity(byte[] publicKey) { - return manager.removeKey(publicKey); - } - - public boolean isAgentLocked() { - return agentLockPassphrase != null; - } - - public boolean requestAgentUnlock(String unlockPassphrase) { - if (agentLockPassphrase == null) - return false; - - if (agentLockPassphrase.equals(unlockPassphrase)) - agentLockPassphrase = null; - - return agentLockPassphrase == null; - } - - public boolean setAgentLock(String lockPassphrase) { - if (agentLockPassphrase != null) - return false; - - agentLockPassphrase = lockPassphrase; - return true; - } - -}
--- a/src/com/five_ten_sg/connectbot/transport/TN5250.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,472 +0,0 @@ -/* - * 510ConnectBot - * Copyright 2014 Carl Byington - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.transport; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.tn5250j.framework.tn5250.Screen5250; -import org.tn5250j.framework.tn5250.tnvt; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.bean.PortForwardBean; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalKeyListener; -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.util.HostDatabase; -import com.five_ten_sg.connectbot.util.PreferenceConstants; -import android.content.Context; -import android.net.Uri; -import android.util.Log; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; -import android.view.View; -import de.mud.terminal.vt320; - - -/** - * @author Carl Byington - * - */ -public class TN5250 extends AbsTransport { - private static final String PROTOCOL = "tn5250"; - private static final String TAG = "ConnectBot.tn5250"; - private static final int DEFAULT_PORT = 23; - - private Screen5250 screen52; - private tnvt handler = null; - private Socket socket; - private boolean connected = false; - - static final Pattern hostmask; - static { - hostmask = Pattern.compile("^([0-9a-z.-]+)(:(\\d+))?$", Pattern.CASE_INSENSITIVE); - } - - - class vt320x5250 extends vt320 { - private HashMap<Integer, Integer> controls; - private HashMap<Integer, String> mnemonics; - - public vt320x5250() { - this(80, 24); - } - - public vt320x5250(int width, int height) { - super(width, height); - controls = new HashMap<Integer, Integer>(); - controls.put(0x01, KEY_PAUSE); // ctrl-a -> [attn] - controls.put(0x08, KEY_BACK_SPACE); - controls.put(0x09, KEY_TAB); - controls.put(0x0d, KEY_ENTER); - controls.put(0x12, KEY_ESCAPE); // ctrl-r -> [reset] - controls.put(0x13, KEY_SYSREQ); // ctrl-s -> [sysreq] - controls.put(0x1b, KEY_ESCAPE); // esc -> [reset] - mnemonics = new HashMap<Integer, String>(); - mnemonics.put(KEY_PAUSE , "[attn]"); - mnemonics.put(KEY_F1 , "[pf1]"); - mnemonics.put(KEY_F2 , "[pf2]"); - mnemonics.put(KEY_F3 , "[pf3]"); - mnemonics.put(KEY_F4 , "[pf4]"); - mnemonics.put(KEY_F5 , "[pf5]"); - mnemonics.put(KEY_F6 , "[pf6]"); - mnemonics.put(KEY_F7 , "[pf7]"); - mnemonics.put(KEY_F8 , "[pf8]"); - mnemonics.put(KEY_F9 , "[pf9]"); - mnemonics.put(KEY_F10 , "[pf10]"); - mnemonics.put(KEY_F11 , "[pf11]"); - mnemonics.put(KEY_F12 , "[pf12]"); - mnemonics.put(KEY_F13 , "[pf13]"); - mnemonics.put(KEY_F14 , "[pf14]"); - mnemonics.put(KEY_F15 , "[pf15]"); - mnemonics.put(KEY_F16 , "[pf16]"); - mnemonics.put(KEY_F17 , "[pf17]"); - mnemonics.put(KEY_F18 , "[pf18]"); - mnemonics.put(KEY_F19 , "[pf19]"); - mnemonics.put(KEY_F20 , "[pf20]"); - mnemonics.put(KEY_F21 , "[pf21]"); - mnemonics.put(KEY_F22 , "[pf22]"); - mnemonics.put(KEY_F23 , "[pf23]"); - mnemonics.put(KEY_F24 , "[pf24]"); - mnemonics.put(KEY_UP , "[up]"); - mnemonics.put(KEY_DOWN , "[down]"); - mnemonics.put(KEY_LEFT , "[left]"); - mnemonics.put(KEY_RIGHT , "[right]"); - mnemonics.put(KEY_PAGE_DOWN , "[pgdown]"); - mnemonics.put(KEY_PAGE_UP , "[pgup]"); - mnemonics.put(KEY_INSERT , "[insert]"); - mnemonics.put(KEY_DELETE , "[delete]"); - mnemonics.put(KEY_BACK_SPACE , "[backspace]"); - mnemonics.put(KEY_HOME , "[home]"); - mnemonics.put(KEY_END , "[end]"); - mnemonics.put(KEY_NUM_LOCK , ""); - mnemonics.put(KEY_CAPS_LOCK , ""); - mnemonics.put(KEY_SHIFT , ""); - mnemonics.put(KEY_CONTROL , ""); - mnemonics.put(KEY_ALT , ""); - mnemonics.put(KEY_ENTER , "[enter]"); - mnemonics.put(KEY_NUMPAD0 , "0"); - mnemonics.put(KEY_NUMPAD1 , "1"); - mnemonics.put(KEY_NUMPAD2 , "2"); - mnemonics.put(KEY_NUMPAD3 , "3"); - mnemonics.put(KEY_NUMPAD4 , "4"); - mnemonics.put(KEY_NUMPAD5 , "5"); - mnemonics.put(KEY_NUMPAD6 , "6"); - mnemonics.put(KEY_NUMPAD7 , "7"); - mnemonics.put(KEY_NUMPAD8 , "8"); - mnemonics.put(KEY_NUMPAD9 , "9"); - mnemonics.put(KEY_DECIMAL , "."); - mnemonics.put(KEY_ADD , "+"); - mnemonics.put(KEY_ESCAPE , "[reset]"); - mnemonics.put(KEY_TAB , "[tab]"); - mnemonics.put(KEY_SYSREQ , "[sysreq]"); - } - - @Override - public void debug(String s) { - Log.d(TAG, s); - } - - // monitor injecting a field - @Override - public void setField(int l, int c, char [] data) { - screen52.setField(l, c, data); - } - - // monitor simulating key depress - @Override - public void keyDepressed(int keyCode, char keyChar, int modifiers) { - if (mnemonics.containsKey(keyCode)) { - String s = mnemonics.get(keyCode); - - if (s != "") screen52.sendKeys(s); - } - } - - // terminal key listener found special key, send notification to monitor - @Override - public void monitorKey(boolean down) { - if (bridge.monitor != null) bridge.monitor.keyState(down); - } - - // terminal key listener sending to local screen - @Override - public void write(byte[] b) { - screen52.sendKeys(new String(b)); - - if (bridge.monitor != null) bridge.monitor.testMoved(); - } - @Override - public void write(int b) { - if (controls.containsKey(b)) keyPressed(controls.get(b), ' ', 0); - else screen52.sendKeys(new String(new byte[] {(byte)b})); - - if (bridge.monitor != null) bridge.monitor.testMoved(); - } - @Override - public void keyPressed(int keyCode, char keyChar, int modifiers) { - keyDepressed(keyCode, keyChar, modifiers); - - if (bridge.monitor != null) bridge.monitor.testMoved(); - } - - // 5250 writing to the screen - // test for changed screen contents - @Override - public void testChanged() { - if (bridge.monitor != null) bridge.monitor.testChanged(); - } - @Override - public void putChar(int c, int l, char ch, int attributes) { - if (bridge.monitor != null) bridge.monitor.screenChanged(l, c); - - super.putChar(c, l, ch, attributes); - } - @Override - public void setCursorPosition(int c, int l) { - if (bridge.monitor != null) bridge.monitor.cursorMove(l, c); - - super.setCursorPosition(c, l); - redraw(); - } - }; - - - public TN5250() { - super(); - } - - - /** - * @return protocol part of the URI - */ - public static String getProtocolName() { - return PROTOCOL; - } - - - /** - * Encode the current transport into a URI that can be passed via intent calls. - * @return URI to host - */ - public Uri getUri(String input) { - Matcher matcher = hostmask.matcher(input); - - if (!matcher.matches()) - return null; - - StringBuilder sb = new StringBuilder(); - sb.append(PROTOCOL) - .append("://") - .append(matcher.group(1)); - String portString = matcher.group(3); - int port = DEFAULT_PORT; - - if (portString != null) { - try { - port = Integer.parseInt(portString); - - if (port < 1 || port > 65535) { - port = DEFAULT_PORT; - } - } - catch (NumberFormatException nfe) { - // Keep the default port - } - } - - if (port != DEFAULT_PORT) { - sb.append(':'); - sb.append(port); - } - - sb.append("/#") - .append(Uri.encode(input)); - Uri uri = Uri.parse(sb.toString()); - return uri; - } - - - /** - * Causes transport to connect to the target host. After connecting but before a - * session is started, must call back to {@link TerminalBridge#onConnected()}. - * After that call a session may be opened. - */ - @Override - public void connect() { - screen52 = new Screen5250(); - handler = new tnvt(screen52, true, true, bridge, manager); - screen52.setVT(handler); - screen52.setBuffer(buffer); - bridge.addFontSizeChangedListener(screen52); - connected = handler.connect(host, homeDirectory, buffer); - - if (connected) bridge.onConnected(); - } - - - /** - * Checks if read() will block. If there are no bytes remaining in - * the underlying transport, return true. - */ - @Override - public boolean willBlock() { - // we don't use a relay thread between the transport and the vt320 buffer - return true; - } - - - /** - * Reads from the transport. Transport must support reading into a byte array - * <code>buffer</code> at the start of <code>offset</code> and a maximum of - * <code>length</code> bytes. If the remote host disconnects, throw an - * {@link IOException}. - * @param buffer byte buffer to store read bytes into - * @param offset where to start writing in the buffer - * @param length maximum number of bytes to read - * @return number of bytes read - * @throws IOException when remote host disconnects - */ - public int read(byte[] buffer, int offset, int length) throws IOException { - // we don't use a relay thread between the transport and the vt320 buffer - return 0; - } - - - /** - * Writes to the transport. If the host is not yet connected, simply return without - * doing anything. An {@link IOException} should be thrown if there is an error after - * connection. - * @param buffer bytes to write to transport - * @throws IOException when there is a problem writing after connection - */ - public void write(byte[] buffer) throws IOException { - } - - - /** - * Writes to the transport. See {@link #write(byte[])} for behavior details. - * @param c character to write to the transport - * @throws IOException when there is a problem writing after connection - */ - public void write(int c) throws IOException { - } - - - /** - * Flushes the write commands to the transport. - * @throws IOException when there is a problem writing after connection - */ - public void flush() throws IOException { - } - - - /** - * Closes the connection to the terminal. - */ - public void close() { - handler.disconnect(); - connected = false; - bridge.removeFontSizeChangedListener(screen52); - bridge.dispatchDisconnect(false); - } - - - /** - * Tells the transport what dimensions the display is currently - * @param columns columns of text - * @param rows rows of text - * @param width width in pixels - * @param height height in pixels - */ - @Override - public void setDimensions(int columns, int rows, int width, int height) { - // do nothing - } - - - @Override - public vt320 getTransportBuffer() { - buffer = new vt320x5250(); - return setupTransportBuffer(); - } - - - @Override - public int getDefaultPort() { - return DEFAULT_PORT; - } - - - @Override - public boolean isConnected() { - return connected; - } - - - @Override - public boolean isSessionOpen() { - return connected; - } - - - @Override - public boolean isAuthenticated() { - return connected; - } - - - @Override - public String getDefaultNickname(String username, String hostname, int port) { - if (port == DEFAULT_PORT) { - return String.format("%s", hostname); - } - else { - return String.format("%s:%d", hostname, port); - } - } - - - @Override - public void getSelectionArgs(Uri uri, Map<String, String> selection) { - selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL); - selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment()); - selection.put(HostDatabase.FIELD_HOST_HOSTNAME, uri.getHost()); - int port = uri.getPort(); - - if (port < 0) port = DEFAULT_PORT; - - selection.put(HostDatabase.FIELD_HOST_PORT, Integer.toString(port)); - } - - - @Override - public HostBean createHost(Uri uri) { - HostBean host = new HostBean(); - host.setProtocol(PROTOCOL); - host.setHostname(uri.getHost()); - int port = uri.getPort(); - - if (port < 0) port = DEFAULT_PORT; - - host.setPort(port); - String nickname = uri.getFragment(); - - if (nickname == null || nickname.length() == 0) { - nickname = getDefaultNickname(host.getUsername(), host.getHostname(), host.getPort()); - } - - host.setNickname(nickname); - return host; - } - - - public String getFormatHint(Context context) { - return String.format("%s:%s", - context.getString(R.string.format_hostname), - context.getString(R.string.format_port)); - } - - - @Override - public boolean usesNetwork() { - return true; - } - - - @Override - public boolean needsRelay() { - // we don't use a relay thread between the transport and the vt320 buffer - return false; - } - - public TerminalKeyListener getTerminalKeyListener() { - return new TerminalKeyListener(manager, bridge, buffer, host.getEncoding()); - } - -}
--- a/src/com/five_ten_sg/connectbot/transport/Telnet.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,357 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.transport; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.nio.charset.Charset; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; -import com.five_ten_sg.connectbot.util.HostDatabase; - -import android.content.Context; -import android.net.Uri; -import android.util.Log; - -import de.mud.telnet.TelnetProtocolHandler; - - -/** - * Telnet transport implementation.<br/> - * Original idea from the JTA telnet package (de.mud.telnet) - * - * @author Kenny Root - * - */ -public class Telnet extends AbsTransport { - private static final String TAG = "ConnectBot.Telnet"; - private static final String PROTOCOL = "telnet"; - private static final int DEFAULT_PORT = 23; - - private TelnetProtocolHandler handler; - private Socket socket; - private InputStream is; - private OutputStream os; - private int width; - private int height; - private boolean connected = false; - - static final Pattern hostmask; - static { - hostmask = Pattern.compile("^([0-9a-z.-]+)(:(\\d+))?$", Pattern.CASE_INSENSITIVE); - } - - public Telnet() { - handler = new TelnetProtocolHandler() { - /** get the current terminal type */ - @Override - public String getTerminalType() { - return getEmulation(); - } - /** get the current window size */ - @Override - public int[] getWindowSize() { - return new int[] { width, height }; - } - /** notify about local echo */ - @Override - public void setLocalEcho(boolean echo) { - /* EMPTY */ - } - /** write data to our back end */ - @Override - public void write(byte[] b) throws IOException { - if (os != null) - os.write(b); - } - /** sent on IAC EOR (prompt terminator for remote access systems). */ - @Override - public void notifyEndOfRecord() { - } - @Override - protected String getCharsetName() { - Charset charset = bridge.getCharset(); - - if (charset != null) - return charset.name(); - else - return ""; - } - }; - } - - - public static String getProtocolName() { - return PROTOCOL; - } - - - public Uri getUri(String input) { - Matcher matcher = hostmask.matcher(input); - - if (!matcher.matches()) - return null; - - StringBuilder sb = new StringBuilder(); - sb.append(PROTOCOL) - .append("://") - .append(matcher.group(1)); - String portString = matcher.group(3); - int port = DEFAULT_PORT; - - if (portString != null) { - try { - port = Integer.parseInt(portString); - - if (port < 1 || port > 65535) { - port = DEFAULT_PORT; - } - } - catch (NumberFormatException nfe) { - // Keep the default port - } - } - - if (port != DEFAULT_PORT) { - sb.append(':'); - sb.append(port); - } - - sb.append("/#") - .append(Uri.encode(input)); - Uri uri = Uri.parse(sb.toString()); - return uri; - } - - - @Override - public void connect() { - try { - socket = new Socket(host.getHostname(), host.getPort()); - connected = true; - is = socket.getInputStream(); - os = socket.getOutputStream(); - bridge.onConnected(); - } - catch (UnknownHostException e) { - Log.d(TAG, "IO Exception connecting to host", e); - } - catch (IOException e) { - Log.d(TAG, "IO Exception connecting to host", e); - } - } - - - @Override - public boolean willBlock() { - if (is == null) return true; - - try { - return is.available() == 0; - } - catch (Exception e) { - return true; - } - } - - - @Override - public int read(byte[] buffer, int start, int len) throws IOException { - /* process all already read bytes */ - int n = 0; - - do { - n = handler.negotiate(buffer, start); - - if (n > 0) - return n; - } - while (n == 0); - - while (n <= 0) { - do { - n = handler.negotiate(buffer, start); - - if (n > 0) - return n; - } - while (n == 0); - - n = is.read(buffer, start, len); - - if (n < 0) { - bridge.dispatchDisconnect(false); - throw new IOException("Remote end closed connection."); - } - - handler.inputfeed(buffer, start, n); - n = handler.negotiate(buffer, start); - } - - return n; - } - - - @Override - public void write(byte[] buffer) throws IOException { - try { - if (os != null) - os.write(buffer); - } - catch (SocketException e) { - bridge.dispatchDisconnect(false); - } - } - - - @Override - public void write(int c) throws IOException { - try { - if (os != null) - os.write(c); - } - catch (SocketException e) { - bridge.dispatchDisconnect(false); - } - } - - - @Override - public void flush() throws IOException { - os.flush(); - } - - - @Override - public void close() { - connected = false; - - if (socket != null) - try { - socket.close(); - socket = null; - } - catch (IOException e) { - Log.d(TAG, "Error closing telnet socket.", e); - } - } - - - @Override - public void setDimensions(int columns, int rows, int width, int height) { - try { - handler.setWindowSize(columns, rows); - } - catch (IOException e) { - Log.e(TAG, "Couldn't resize remote terminal", e); - } - } - - - @Override - public int getDefaultPort() { - return DEFAULT_PORT; - } - - @Override - public boolean isConnected() { - return connected; - } - - @Override - public boolean isSessionOpen() { - return isConnected(); - } - - @Override - public boolean isAuthenticated() { - return isConnected(); - } - - - @Override - public String getDefaultNickname(String username, String hostname, int port) { - if (port == DEFAULT_PORT) { - return String.format("%s", hostname); - } - else { - return String.format("%s:%d", hostname, port); - } - } - - - @Override - public void getSelectionArgs(Uri uri, Map<String, String> selection) { - selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL); - selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment()); - selection.put(HostDatabase.FIELD_HOST_HOSTNAME, uri.getHost()); - int port = uri.getPort(); - - if (port < 0) - port = DEFAULT_PORT; - - selection.put(HostDatabase.FIELD_HOST_PORT, Integer.toString(port)); - } - - - @Override - public HostBean createHost(Uri uri) { - HostBean host = new HostBean(); - host.setProtocol(PROTOCOL); - host.setHostname(uri.getHost()); - int port = uri.getPort(); - - if (port < 0) - port = DEFAULT_PORT; - - host.setPort(port); - String nickname = uri.getFragment(); - - if (nickname == null || nickname.length() == 0) { - host.setNickname(getDefaultNickname(host.getUsername(), - host.getHostname(), host.getPort())); - } - else { - host.setNickname(uri.getFragment()); - } - - return host; - } - - - public String getFormatHint(Context context) { - return String.format("%s:%s", - context.getString(R.string.format_hostname), - context.getString(R.string.format_port)); - } - - @Override - public boolean usesNetwork() { - return true; - } -}
--- a/src/com/five_ten_sg/connectbot/transport/TransportFactory.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.transport; - -import java.util.HashMap; -import java.util.Map; - -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.util.HostDatabase; -import android.content.Context; -import android.net.Uri; -import android.util.Log; - - -/** - * @author Kenny Root - * - */ -public class TransportFactory { - private static final String TAG = "ConnectBot.TransportFactory"; - - private static String[] transportNames = { - SSH.getProtocolName(), - TN5250.getProtocolName(), - Telnet.getProtocolName(), - Local.getProtocolName(), - }; - - /** - * @param protocol - * @return - */ - public static AbsTransport getTransport(String protocol) { - if (SSH.getProtocolName().equals(protocol)) { - return new SSH(); - } - else if (TN5250.getProtocolName().equals(protocol)) { - return new TN5250(); - } - else if (Telnet.getProtocolName().equals(protocol)) { - return new Telnet(); - } - else if (Local.getProtocolName().equals(protocol)) { - return new Local(); - } - else { - return null; - } - } - - public static Uri getUri(String protocol, String input) { - Log.d("TransportFactory", String.format( - "Attempting to discover URI for protocol=%s on input=%s", - protocol, input)); - AbsTransport t = getTransport(protocol); - - if (t == null) return null; - - return t.getUri(input); - } - - public static String[] getTransportNames() { - return transportNames; - } - - public static boolean isSameTransportType(AbsTransport a, AbsTransport b) { - if (a == null || b == null) - return false; - - return a.getClass().equals(b.getClass()); - } - - public static boolean canForwardPorts(String protocol) { - AbsTransport t = getTransport(protocol); - - if (t == null) return false; - - return t.canForwardPorts(); - } - - /** - * @param protocol text name of protocol - * @param context - * @return expanded format hint - */ - public static String getFormatHint(String protocol, Context context) { - AbsTransport t = getTransport(protocol); - - if (t == null) return "???"; - - return t.getFormatHint(context); - } - - /** - * @param hostdb Handle to HostDatabase - * @param uri URI to target server - * @return HostBean or null - */ - public static HostBean findHost(HostDatabase hostdb, Uri uri) { - AbsTransport transport = getTransport(uri.getScheme()); - Map<String, String> selection = new HashMap<String, String>(); - transport.getSelectionArgs(uri, selection); - - if (selection.size() == 0) { - Log.e(TAG, String.format("Transport %s failed to do something useful with URI=%s", - uri.getScheme(), uri.toString())); - throw new IllegalStateException("Failed to get needed selection arguments"); - } - - return hostdb.findHost(selection); - } -}
--- a/src/com/five_ten_sg/connectbot/util/Colors.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -/** - * @author Kenny Root - * - */ -public class Colors { - public final static Integer[] defaults = new Integer[] { - 0xff000000, // black // 0 - 0xffcc0000, // red // 1 - 0xff00cc00, // green // 2 - 0xffcccc00, // brown // 3 - 0xff0000cc, // blue // 4 - 0xffcc00cc, // purple // 5 - 0xff00cccc, // cyan // 6 - 0xffcccccc, // light grey // 7 - 0xff444444, // dark grey // 8 - 0xffff4444, // light red // 9 - 0xff44ff44, // light green // a - 0xffffff44, // yellow // b - 0xff4444ff, // light blue // c - 0xffff44ff, // light purple // d - 0xff44ffff, // light cyan // e - 0xffffffff, // white // f - 0xff000000, 0xff00005f, 0xff000087, 0xff0000af, 0xff0000d7, - 0xff0000ff, 0xff005f00, 0xff005f5f, 0xff005f87, 0xff005faf, - 0xff005fd7, 0xff005fff, 0xff008700, 0xff00875f, 0xff008787, - 0xff0087af, 0xff0087d7, 0xff0087ff, 0xff00af00, 0xff00af5f, - 0xff00af87, 0xff00afaf, 0xff00afd7, 0xff00afff, 0xff00d700, - 0xff00d75f, 0xff00d787, 0xff00d7af, 0xff00d7d7, 0xff00d7ff, - 0xff00ff00, 0xff00ff5f, 0xff00ff87, 0xff00ffaf, 0xff00ffd7, - 0xff00ffff, 0xff5f0000, 0xff5f005f, 0xff5f0087, 0xff5f00af, - 0xff5f00d7, 0xff5f00ff, 0xff5f5f00, 0xff5f5f5f, 0xff5f5f87, - 0xff5f5faf, 0xff5f5fd7, 0xff5f5fff, 0xff5f8700, 0xff5f875f, - 0xff5f8787, 0xff5f87af, 0xff5f87d7, 0xff5f87ff, 0xff5faf00, - 0xff5faf5f, 0xff5faf87, 0xff5fafaf, 0xff5fafd7, 0xff5fafff, - 0xff5fd700, 0xff5fd75f, 0xff5fd787, 0xff5fd7af, 0xff5fd7d7, - 0xff5fd7ff, 0xff5fff00, 0xff5fff5f, 0xff5fff87, 0xff5fffaf, - 0xff5fffd7, 0xff5fffff, 0xff870000, 0xff87005f, 0xff870087, - 0xff8700af, 0xff8700d7, 0xff8700ff, 0xff875f00, 0xff875f5f, - 0xff875f87, 0xff875faf, 0xff875fd7, 0xff875fff, 0xff878700, - 0xff87875f, 0xff878787, 0xff8787af, 0xff8787d7, 0xff8787ff, - 0xff87af00, 0xff87af5f, 0xff87af87, 0xff87afaf, 0xff87afd7, - 0xff87afff, 0xff87d700, 0xff87d75f, 0xff87d787, 0xff87d7af, - 0xff87d7d7, 0xff87d7ff, 0xff87ff00, 0xff87ff5f, 0xff87ff87, - 0xff87ffaf, 0xff87ffd7, 0xff87ffff, 0xffaf0000, 0xffaf005f, - 0xffaf0087, 0xffaf00af, 0xffaf00d7, 0xffaf00ff, 0xffaf5f00, - 0xffaf5f5f, 0xffaf5f87, 0xffaf5faf, 0xffaf5fd7, 0xffaf5fff, - 0xffaf8700, 0xffaf875f, 0xffaf8787, 0xffaf87af, 0xffaf87d7, - 0xffaf87ff, 0xffafaf00, 0xffafaf5f, 0xffafaf87, 0xffafafaf, - 0xffafafd7, 0xffafafff, 0xffafd700, 0xffafd75f, 0xffafd787, - 0xffafd7af, 0xffafd7d7, 0xffafd7ff, 0xffafff00, 0xffafff5f, - 0xffafff87, 0xffafffaf, 0xffafffd7, 0xffafffff, 0xffd70000, - 0xffd7005f, 0xffd70087, 0xffd700af, 0xffd700d7, 0xffd700ff, - 0xffd75f00, 0xffd75f5f, 0xffd75f87, 0xffd75faf, 0xffd75fd7, - 0xffd75fff, 0xffd78700, 0xffd7875f, 0xffd78787, 0xffd787af, - 0xffd787d7, 0xffd787ff, 0xffd7af00, 0xffd7af5f, 0xffd7af87, - 0xffd7afaf, 0xffd7afd7, 0xffd7afff, 0xffd7d700, 0xffd7d75f, - 0xffd7d787, 0xffd7d7af, 0xffd7d7d7, 0xffd7d7ff, 0xffd7ff00, - 0xffd7ff5f, 0xffd7ff87, 0xffd7ffaf, 0xffd7ffd7, 0xffd7ffff, - 0xffff0000, 0xffff005f, 0xffff0087, 0xffff00af, 0xffff00d7, - 0xffff00ff, 0xffff5f00, 0xffff5f5f, 0xffff5f87, 0xffff5faf, - 0xffff5fd7, 0xffff5fff, 0xffff8700, 0xffff875f, 0xffff8787, - 0xffff87af, 0xffff87d7, 0xffff87ff, 0xffffaf00, 0xffffaf5f, - 0xffffaf87, 0xffffafaf, 0xffffafd7, 0xffffafff, 0xffffd700, - 0xffffd75f, 0xffffd787, 0xffffd7af, 0xffffd7d7, 0xffffd7ff, - 0xffffff00, 0xffffff5f, 0xffffff87, 0xffffffaf, 0xffffffd7, - 0xffffffff, 0xff080808, 0xff121212, 0xff1c1c1c, 0xff262626, - 0xff303030, 0xff3a3a3a, 0xff444444, 0xff4e4e4e, 0xff585858, - 0xff626262, 0xff6c6c6c, 0xff767676, 0xff808080, 0xff8a8a8a, - 0xff949494, 0xff9e9e9e, 0xffa8a8a8, 0xffb2b2b2, 0xffbcbcbc, - 0xffc6c6c6, 0xffd0d0d0, 0xffdadada, 0xffe4e4e4, 0xffeeeeee, - }; -}
--- a/src/com/five_ten_sg/connectbot/util/Encryptor.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -/** - * This class is from: - * - * Encryptor.java - * Copyright 2008 Zach Scrivena - * zachscrivena@gmail.com - * http://zs.freeshell.org/ - */ - -import java.security.MessageDigest; -import java.security.SecureRandom; -import java.util.Arrays; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - - -/** - * Perform AES-128 encryption. - */ -public final class Encryptor { - /** name of the character set to use for converting between characters and bytes */ - private static final String CHARSET_NAME = "UTF-8"; - - /** random number generator algorithm */ - private static final String RNG_ALGORITHM = "SHA1PRNG"; - - /** message digest algorithm (must be sufficiently long to provide the key and initialization vector) */ - private static final String DIGEST_ALGORITHM = "SHA-256"; - - /** key algorithm (must be compatible with CIPHER_ALGORITHM) */ - private static final String KEY_ALGORITHM = "AES"; - - /** cipher algorithm (must be compatible with KEY_ALGORITHM) */ - private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; - - - /** - * Private constructor that should never be called. - */ - private Encryptor() - {} - - - /** - * Encrypt the specified cleartext using the given password. - * With the correct salt, number of iterations, and password, the decrypt() method reverses - * the effect of this method. - * This method generates and uses a random salt, and the user-specified number of iterations - * and password to create a 16-byte secret key and 16-byte initialization vector. - * The secret key and initialization vector are then used in the AES-128 cipher to encrypt - * the given cleartext. - * - * @param salt - * salt that was used in the encryption (to be populated) - * @param iterations - * number of iterations to use in salting - * @param password - * password to be used for encryption - * @param cleartext - * cleartext to be encrypted - * @return - * ciphertext - * @throws Exception - * on any error encountered in encryption - */ - public static byte[] encrypt( - final byte[] salt, - final int iterations, - final String password, - final byte[] cleartext) - throws Exception { - /* generate salt randomly */ - SecureRandom.getInstance(RNG_ALGORITHM).nextBytes(salt); - /* compute key and initialization vector */ - final MessageDigest shaDigest = MessageDigest.getInstance(DIGEST_ALGORITHM); - byte[] pw = password.getBytes(CHARSET_NAME); - - for (int i = 0; i < iterations; i++) { - /* add salt */ - final byte[] salted = new byte[pw.length + salt.length]; - System.arraycopy(pw, 0, salted, 0, pw.length); - System.arraycopy(salt, 0, salted, pw.length, salt.length); - Arrays.fill(pw, (byte) 0x00); - /* compute SHA-256 digest */ - shaDigest.reset(); - pw = shaDigest.digest(salted); - Arrays.fill(salted, (byte) 0x00); - } - - /* extract the 16-byte key and initialization vector from the SHA-256 digest */ - final byte[] key = new byte[16]; - final byte[] iv = new byte[16]; - System.arraycopy(pw, 0, key, 0, 16); - System.arraycopy(pw, 16, iv, 0, 16); - Arrays.fill(pw, (byte) 0x00); - /* perform AES-128 encryption */ - final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); - cipher.init( - Cipher.ENCRYPT_MODE, - new SecretKeySpec(key, KEY_ALGORITHM), - new IvParameterSpec(iv)); - Arrays.fill(key, (byte) 0x00); - Arrays.fill(iv, (byte) 0x00); - return cipher.doFinal(cleartext); - } - - - /** - * Decrypt the specified ciphertext using the given password. - * With the correct salt, number of iterations, and password, this method reverses the effect - * of the encrypt() method. - * This method uses the user-specified salt, number of iterations, and password - * to recreate the 16-byte secret key and 16-byte initialization vector. - * The secret key and initialization vector are then used in the AES-128 cipher to decrypt - * the given ciphertext. - * - * @param salt - * salt to be used in decryption - * @param iterations - * number of iterations to use in salting - * @param password - * password to be used for decryption - * @param ciphertext - * ciphertext to be decrypted - * @return - * cleartext - * @throws Exception - * on any error encountered in decryption - */ - public static byte[] decrypt( - final byte[] salt, - final int iterations, - final String password, - final byte[] ciphertext) - throws Exception { - /* compute key and initialization vector */ - final MessageDigest shaDigest = MessageDigest.getInstance(DIGEST_ALGORITHM); - byte[] pw = password.getBytes(CHARSET_NAME); - - for (int i = 0; i < iterations; i++) { - /* add salt */ - final byte[] salted = new byte[pw.length + salt.length]; - System.arraycopy(pw, 0, salted, 0, pw.length); - System.arraycopy(salt, 0, salted, pw.length, salt.length); - Arrays.fill(pw, (byte) 0x00); - /* compute SHA-256 digest */ - shaDigest.reset(); - pw = shaDigest.digest(salted); - Arrays.fill(salted, (byte) 0x00); - } - - /* extract the 16-byte key and initialization vector from the SHA-256 digest */ - final byte[] key = new byte[16]; - final byte[] iv = new byte[16]; - System.arraycopy(pw, 0, key, 0, 16); - System.arraycopy(pw, 16, iv, 0, 16); - Arrays.fill(pw, (byte) 0x00); - /* perform AES-128 decryption */ - final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); - cipher.init( - Cipher.DECRYPT_MODE, - new SecretKeySpec(key, KEY_ALGORITHM), - new IvParameterSpec(iv)); - Arrays.fill(key, (byte) 0x00); - Arrays.fill(iv, (byte) 0x00); - return cipher.doFinal(ciphertext); - } -}
--- a/src/com/five_ten_sg/connectbot/util/EntropyDialog.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import com.five_ten_sg.connectbot.R; -import android.app.Dialog; -import android.content.Context; -import android.view.View; - -public class EntropyDialog extends Dialog implements OnEntropyGatheredListener { - - public EntropyDialog(Context context) { - super(context); - this.setContentView(R.layout.dia_gatherentropy); - this.setTitle(R.string.pubkey_gather_entropy); - ((EntropyView) findViewById(R.id.entropy)).addOnEntropyGatheredListener(this); - } - - public EntropyDialog(Context context, View view) { - super(context); - this.setContentView(view); - this.setTitle(R.string.pubkey_gather_entropy); - ((EntropyView) findViewById(R.id.entropy)).addOnEntropyGatheredListener(this); - } - - public void onEntropyGathered(byte[] entropy) { - this.dismiss(); - } - -}
--- a/src/com/five_ten_sg/connectbot/util/EntropyView.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import java.util.Vector; - -import com.five_ten_sg.connectbot.R; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.FontMetrics; -import android.graphics.Typeface; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - -public class EntropyView extends View { - private static final int SHA1_MAX_BYTES = 20; - private static final int MILLIS_BETWEEN_INPUTS = 50; - - private Paint mPaint; - private FontMetrics mFontMetrics; - private boolean mFlipFlop; - private long mLastTime; - private Vector<OnEntropyGatheredListener> listeners; - - private byte[] mEntropy; - private int mEntropyByteIndex; - private int mEntropyBitIndex; - - private int splitText = 0; - - private float lastX = 0.0f, lastY = 0.0f; - - public EntropyView(Context context) { - super(context); - setUpEntropy(); - } - - public EntropyView(Context context, AttributeSet attrs) { - super(context, attrs); - setUpEntropy(); - } - - private void setUpEntropy() { - mPaint = new Paint(); - mPaint.setAntiAlias(true); - mPaint.setTypeface(Typeface.DEFAULT); - mPaint.setTextAlign(Paint.Align.CENTER); - mPaint.setTextSize(16); - mPaint.setColor(Color.WHITE); - mFontMetrics = mPaint.getFontMetrics(); - mEntropy = new byte[SHA1_MAX_BYTES]; - mEntropyByteIndex = 0; - mEntropyBitIndex = 0; - listeners = new Vector<OnEntropyGatheredListener>(); - } - - public void addOnEntropyGatheredListener(OnEntropyGatheredListener listener) { - listeners.add(listener); - } - - public void removeOnEntropyGatheredListener(OnEntropyGatheredListener listener) { - listeners.remove(listener); - } - - @Override - public void onDraw(Canvas c) { - String prompt = String.format(getResources().getString(R.string.pubkey_touch_prompt), - (int)(100.0 * (mEntropyByteIndex / 20.0)) + (int)(5.0 * (mEntropyBitIndex / 8.0))); - - if (splitText > 0 || - mPaint.measureText(prompt) > (getWidth() * 0.8)) { - if (splitText == 0) - splitText = prompt.indexOf(" ", prompt.length() / 2); - - c.drawText(prompt.substring(0, splitText), - getWidth() / 2.0f, - getHeight() / 2.0f + (mPaint.ascent() + mPaint.descent()), - mPaint); - c.drawText(prompt.substring(splitText), - getWidth() / 2.0f, - getHeight() / 2.0f - (mPaint.ascent() + mPaint.descent()), - mPaint); - } - else { - c.drawText(prompt, - getWidth() / 2.0f, - getHeight() / 2.0f - (mFontMetrics.ascent + mFontMetrics.descent) / 2, - mPaint); - } - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mEntropyByteIndex >= SHA1_MAX_BYTES - || lastX == event.getX() - || lastY == event.getY()) - return true; - - // Only get entropy every 200 milliseconds to ensure the user has moved around. - long now = System.currentTimeMillis(); - - if ((now - mLastTime) < MILLIS_BETWEEN_INPUTS) - return true; - else - mLastTime = now; - - byte input; - lastX = event.getX(); - lastY = event.getY(); - - // Get the lowest 4 bits of each X, Y input and concat to the entropy-gathering - // string. - if (mFlipFlop) - input = (byte)((((int)lastX & 0x0F) << 4) | ((int)lastY & 0x0F)); - else - input = (byte)((((int)lastY & 0x0F) << 4) | ((int)lastX & 0x0F)); - - mFlipFlop = !mFlipFlop; - - for (int i = 0; i < 4 && mEntropyByteIndex < SHA1_MAX_BYTES; i++) { - if ((input & 0x3) == 0x1) { - mEntropy[mEntropyByteIndex] <<= 1; - mEntropy[mEntropyByteIndex] |= 1; - mEntropyBitIndex++; - input >>= 2; - } - else if ((input & 0x3) == 0x2) { - mEntropy[mEntropyByteIndex] <<= 1; - mEntropyBitIndex++; - input >>= 2; - } - - if (mEntropyBitIndex >= 8) { - mEntropyBitIndex = 0; - mEntropyByteIndex++; - } - } - - // SHA1PRNG only keeps 160 bits of entropy. - if (mEntropyByteIndex >= SHA1_MAX_BYTES) { - for (OnEntropyGatheredListener listener : listeners) { - listener.onEntropyGathered(mEntropy); - } - } - - invalidate(); - return true; - } -}
--- a/src/com/five_ten_sg/connectbot/util/FileChooser.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * File Chooser Class for VX ConnectBot - * Copyright 2012 Martin Matuska - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.five_ten_sg.connectbot.util; - -import java.io.File; -import java.net.URI; - -import org.openintents.intents.FileManagerIntents; - -import com.five_ten_sg.connectbot.R; -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.Uri; -import android.os.Environment; -import android.preference.PreferenceManager; -import android.util.Log; -import android.widget.Toast; - -import com.lamerman.FileDialog; -import com.lamerman.SelectionMode; - -public class FileChooser { - public final static String TAG = "ConnectBot.FileChooser"; - - public static final int REQUEST_CODE_SELECT_FILE = 1; - - // Constants for AndExplorer's file picking intent - private static final String ANDEXPLORER_TITLE = "explorer_title"; - private static final String MIME_TYPE_ANDEXPLORER_FILE = "vnd.android.cursor.dir/lysesoft.andexplorer.file"; - - public static void selectFile(Activity source, FileChooserCallback callback, int requestcode) { - selectFile(source, callback, requestcode, null); - } - - public static void selectFile(Activity source, FileChooserCallback callback, int requestcode, String title) { - final File sdcard = Environment.getExternalStorageDirectory(); - - if (title == null) - title = source.getString(R.string.file_chooser_select_file); - - int mode = SelectionMode.MODE_OPEN; - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(source); - Intent intent = null; - String filedialog; - String appString = null; - - if (prefs == null) - return; - - filedialog = prefs.getString(PreferenceConstants.FILE_DIALOG, "built-in"); - - if (filedialog.equals("OI")) { - appString = "OpenIntents File Manager"; - intent = new Intent(FileManagerIntents.ACTION_PICK_FILE); - intent.setData(Uri.fromFile(sdcard)); - intent.putExtra(FileManagerIntents.EXTRA_TITLE, title); - intent.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, source.getString(android.R.string.ok)); - } - else if (filedialog.equals("AE")) { - appString = "AndExplorer"; - intent = new Intent(Intent.ACTION_PICK); - intent.setDataAndType(Uri.fromFile(sdcard), MIME_TYPE_ANDEXPLORER_FILE); - intent.putExtra(ANDEXPLORER_TITLE, title); - } - - if (intent != null && appString != null) { - try { - source.startActivityForResult(intent, requestcode); - return; - } - catch (ActivityNotFoundException e1) { - Toast.makeText(source, - source.getString(R.string.error_starting_app, appString), - Toast.LENGTH_LONG).show(); - } - } - - intent = new Intent(source.getBaseContext(), FileDialog.class); - intent.putExtra(FileDialog.START_PATH, sdcard.toString()); - intent.putExtra(FileDialog.TITLE, title); - intent.putExtra(FileDialog.SELECTION_MODE, mode); - source.startActivityForResult(intent, requestcode); - } - - public static File getSelectedFile(Intent intent) { - File file = null; - - if (intent == null) - return null; - - Uri uri = intent.getData(); - - try { - if (uri != null) { - file = new File(URI.create(uri.toString())); - } - else { - String filename = intent.getDataString(); - - if (filename != null) - file = new File(URI.create(filename)); - } - } - catch (IllegalArgumentException e) { - Log.e(TAG, "Couldn't read selected file", e); - return null; - } - - return file; - } -} \ No newline at end of file
--- a/src/com/five_ten_sg/connectbot/util/FileChooserCallback.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/* - * File Chooser Callback Class for VX ConnectBot - * Copyright 2012 Martin Matuska - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.five_ten_sg.connectbot.util; - -import java.io.File; - -public interface FileChooserCallback { - public void fileSelected(File f); -}
--- a/src/com/five_ten_sg/connectbot/util/HelpTopicView.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import com.five_ten_sg.connectbot.HelpActivity; -import android.content.Context; -import android.util.AttributeSet; -import android.webkit.WebSettings; -import android.webkit.WebView; - -/** - * @author Kenny Root - * - */ -public class HelpTopicView extends WebView { - public final static String HELPDIR = "help"; - public final static String SUFFIX = ".html"; - - public HelpTopicView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initialize(); - } - - public HelpTopicView(Context context, AttributeSet attrs) { - super(context, attrs); - initialize(); - } - - public HelpTopicView(Context context) { - super(context); - initialize(); - } - - private void initialize() { - WebSettings wSet = getSettings(); - wSet.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS); - wSet.setUseWideViewPort(false); - } - - public HelpTopicView setTopic(String topic) { - String path = String.format("file:///android_asset/%s/%s%s", HELPDIR, topic, SUFFIX); - loadUrl(path); - computeScroll(); - return this; - } -}
--- a/src/com/five_ten_sg/connectbot/util/HostDatabase.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,762 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import java.nio.charset.Charset; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.bean.PortForwardBean; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.util.Log; - -import ch.ethz.ssh2.KnownHosts; - -/** - * Contains information about various SSH hosts, include public hostkey if known - * from previous sessions. - * - * @author jsharkey - */ -public class HostDatabase extends RobustSQLiteOpenHelper { - - public final static String TAG = "ConnectBot.HostDatabase"; - - public final static String DB_NAME = "hosts"; - public final static int DB_VERSION = 28; - - public final static String TABLE_HOSTS = "hosts"; - public final static String FIELD_HOST_NICKNAME = "nickname"; - public final static String FIELD_HOST_PROTOCOL = "protocol"; - public final static String FIELD_HOST_USERNAME = "username"; - public final static String FIELD_HOST_HOSTNAME = "hostname"; - public final static String FIELD_HOST_PORT = "port"; - public final static String FIELD_HOST_HOSTKEYALGO = "hostkeyalgo"; - public final static String FIELD_HOST_HOSTKEY = "hostkey"; - public final static String FIELD_HOST_LASTCONNECT = "lastconnect"; - public final static String FIELD_HOST_COLOR = "color"; - public final static String FIELD_HOST_USEKEYS = "usekeys"; - public final static String FIELD_HOST_USEAUTHAGENT = "useauthagent"; - public final static String FIELD_HOST_POSTLOGIN = "postlogin"; - public final static String FIELD_HOST_PUBKEYID = "pubkeyid"; - public final static String FIELD_HOST_WANTSESSION = "wantsession"; - public final static String FIELD_HOST_DELKEY = "delkey"; - public final static String FIELD_HOST_FONTSIZE = "fontsize"; - public final static String FIELD_HOST_FIXEDSIZE = "fixed_size"; - public final static String FIELD_HOST_FIXEDWIDTH = "fixed_width"; - public final static String FIELD_HOST_FIXEDHEIGHT = "fixed_height"; - public final static String FIELD_HOST_COMPRESSION = "compression"; - public final static String FIELD_HOST_HTTPPROXY = "httpproxy"; - public final static String FIELD_HOST_ENCODING = "encoding"; - public final static String FIELD_HOST_STAYCONNECTED = "stayconnected"; - public final static String FIELD_HOST_WANTX11FORWARD = "wantx11forward"; - public final static String FIELD_HOST_X11HOST = "x11host"; - public final static String FIELD_HOST_X11PORT = "x11port"; - public final static String FIELD_HOST_MONITOR = "monitor"; - public final static String FIELD_HOST_EMULATION = "emulation"; - public final static String FIELD_HOST_ENCRYPTION5250 = "encryption5250"; - public final static String FIELD_HOST_LIBRARY5250 = "library5250"; - public final static String FIELD_HOST_MENU5250 = "menu5250"; - public final static String FIELD_HOST_PROGRAM5250 = "program5250"; - public final static String CATEGORY_5250 = "5250"; - public final static String CATEGORY_X11 = "x11"; - - public final static String TABLE_PORTFORWARDS = "portforwards"; - public final static String FIELD_PORTFORWARD_HOSTID = "hostid"; - public final static String FIELD_PORTFORWARD_NICKNAME = "nickname"; - public final static String FIELD_PORTFORWARD_TYPE = "type"; - public final static String FIELD_PORTFORWARD_SOURCEPORT = "sourceport"; - public final static String FIELD_PORTFORWARD_DESTADDR = "destaddr"; - public final static String FIELD_PORTFORWARD_DESTPORT = "destport"; - - public final static String TABLE_COLORS = "colors"; - public final static String FIELD_COLOR_SCHEME = "scheme"; - public final static String FIELD_COLOR_NUMBER = "number"; - public final static String FIELD_COLOR_VALUE = "value"; - - public final static String TABLE_COLOR_DEFAULTS = "colorDefaults"; - public final static String FIELD_COLOR_FG = "fg"; - public final static String FIELD_COLOR_BG = "bg"; - - public final static int DEFAULT_FG_COLOR = 7; - public final static int DEFAULT_BG_COLOR = 0; - - public final static String COLOR_RED = "red"; - public final static String COLOR_GREEN = "green"; - public final static String COLOR_BLUE = "blue"; - public final static String COLOR_GRAY = "gray"; - - public final static String PORTFORWARD_LOCAL = "local"; - public final static String PORTFORWARD_REMOTE = "remote"; - public final static String PORTFORWARD_DYNAMIC4 = "dynamic4"; - public final static String PORTFORWARD_DYNAMIC5 = "dynamic5"; - - public final static String DELKEY_DEL = "del"; - public final static String DELKEY_BACKSPACE = "backspace"; - - public final static String AUTHAGENT_NO = "no"; - public final static String AUTHAGENT_CONFIRM = "confirm"; - public final static String AUTHAGENT_YES = "yes"; - - public final static String ENCODING_DEFAULT = Charset.defaultCharset().name(); - - public final static String X11HOST_DEFAULT = "localhost"; - public final static int X11PORT_DEFAULT = 6000; - - public final static long PUBKEYID_NEVER = -2; - public final static long PUBKEYID_ANY = -1; - - public static final int DEFAULT_COLOR_SCHEME = 0; - - // Table creation strings - public static final String CREATE_TABLE_COLOR_DEFAULTS = - "CREATE TABLE " + TABLE_COLOR_DEFAULTS - + " (" + FIELD_COLOR_SCHEME + " INTEGER NOT NULL, " - + FIELD_COLOR_FG + " INTEGER NOT NULL DEFAULT " + DEFAULT_FG_COLOR + ", " - + FIELD_COLOR_BG + " INTEGER NOT NULL DEFAULT " + DEFAULT_BG_COLOR + ")"; - public static final String CREATE_TABLE_COLOR_DEFAULTS_INDEX = - "CREATE INDEX " + TABLE_COLOR_DEFAULTS + FIELD_COLOR_SCHEME + "index ON " - + TABLE_COLOR_DEFAULTS + " (" + FIELD_COLOR_SCHEME + ");"; - - private static final String WHERE_SCHEME_AND_COLOR = FIELD_COLOR_SCHEME + " = ? AND " - + FIELD_COLOR_NUMBER + " = ?"; - - static { - addTableName(TABLE_HOSTS); - addTableName(TABLE_PORTFORWARDS); - addIndexName(TABLE_PORTFORWARDS + FIELD_PORTFORWARD_HOSTID + "index"); - addTableName(TABLE_COLORS); - addIndexName(TABLE_COLORS + FIELD_COLOR_SCHEME + "index"); - addTableName(TABLE_COLOR_DEFAULTS); - addIndexName(TABLE_COLOR_DEFAULTS + FIELD_COLOR_SCHEME + "index"); - } - - public static final Object[] dbLock = new Object[0]; - - public HostDatabase(Context context) { - super(context, DB_NAME, null, DB_VERSION); - getWritableDatabase().close(); - } - - @Override - public void onCreate(SQLiteDatabase db) { - super.onCreate(db); - db.execSQL("CREATE TABLE " + TABLE_HOSTS - + " (_id INTEGER PRIMARY KEY, " - + FIELD_HOST_NICKNAME + " TEXT, " - + FIELD_HOST_PROTOCOL + " TEXT DEFAULT 'ssh', " - + FIELD_HOST_USERNAME + " TEXT, " - + FIELD_HOST_HOSTNAME + " TEXT, " - + FIELD_HOST_PORT + " INTEGER, " - + FIELD_HOST_HOSTKEYALGO + " TEXT, " - + FIELD_HOST_HOSTKEY + " BLOB, " - + FIELD_HOST_LASTCONNECT + " INTEGER, " - + FIELD_HOST_COLOR + " TEXT, " - + FIELD_HOST_USEKEYS + " TEXT, " - + FIELD_HOST_USEAUTHAGENT + " TEXT, " - + FIELD_HOST_POSTLOGIN + " TEXT, " - + FIELD_HOST_PUBKEYID + " INTEGER DEFAULT " + PUBKEYID_ANY + ", " - + FIELD_HOST_DELKEY + " TEXT DEFAULT '" + DELKEY_DEL + "', " - + FIELD_HOST_FONTSIZE + " REAL, " - + FIELD_HOST_FIXEDSIZE + " TEXT DEFAULT '" + Boolean.toString(false) + "', " - + FIELD_HOST_FIXEDWIDTH + " INTEGER, " - + FIELD_HOST_FIXEDHEIGHT + " INTEGER, " - + FIELD_HOST_WANTSESSION + " TEXT DEFAULT '" + Boolean.toString(true) + "', " - + FIELD_HOST_COMPRESSION + " TEXT DEFAULT '" + Boolean.toString(false) + "', " - + FIELD_HOST_HTTPPROXY + " TEXT, " - + FIELD_HOST_ENCODING + " TEXT DEFAULT '" + ENCODING_DEFAULT + "', " - + FIELD_HOST_STAYCONNECTED + " TEXT, " - + FIELD_HOST_WANTX11FORWARD + " TEXT DEFAULT '" + Boolean.toString(false) + "', " - + FIELD_HOST_X11HOST + " TEXT DEFAULT '" + X11HOST_DEFAULT + "', " - + FIELD_HOST_X11PORT + " INTEGER DEFAULT " + X11PORT_DEFAULT + ", " - + FIELD_HOST_MONITOR + " TEXT, " - + FIELD_HOST_EMULATION + " TEXT, " - + FIELD_HOST_ENCRYPTION5250 + " TEXT, " - + FIELD_HOST_LIBRARY5250 + " TEXT, " - + FIELD_HOST_MENU5250 + " TEXT, " - + FIELD_HOST_PROGRAM5250 + " TEXT)"); - db.execSQL("CREATE TABLE " + TABLE_PORTFORWARDS - + " (_id INTEGER PRIMARY KEY, " - + FIELD_PORTFORWARD_HOSTID + " INTEGER, " - + FIELD_PORTFORWARD_NICKNAME + " TEXT, " - + FIELD_PORTFORWARD_TYPE + " TEXT NOT NULL DEFAULT " + PORTFORWARD_LOCAL + ", " - + FIELD_PORTFORWARD_SOURCEPORT + " INTEGER NOT NULL DEFAULT 8080, " - + FIELD_PORTFORWARD_DESTADDR + " TEXT, " - + FIELD_PORTFORWARD_DESTPORT + " TEXT)"); - db.execSQL("CREATE INDEX " + TABLE_PORTFORWARDS + FIELD_PORTFORWARD_HOSTID + "index ON " - + TABLE_PORTFORWARDS + " (" + FIELD_PORTFORWARD_HOSTID + ");"); - db.execSQL("CREATE TABLE " + TABLE_COLORS - + " (_id INTEGER PRIMARY KEY, " - + FIELD_COLOR_NUMBER + " INTEGER, " - + FIELD_COLOR_VALUE + " INTEGER, " - + FIELD_COLOR_SCHEME + " INTEGER)"); - db.execSQL("CREATE INDEX " + TABLE_COLORS + FIELD_COLOR_SCHEME + "index ON " - + TABLE_COLORS + " (" + FIELD_COLOR_SCHEME + ");"); - db.execSQL(CREATE_TABLE_COLOR_DEFAULTS); - db.execSQL(CREATE_TABLE_COLOR_DEFAULTS_INDEX); - } - - @Override - public void onRobustUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLiteException { - // Versions of the database before 510ConnectBot will be shot without warning. - if (oldVersion < 24) { - db.execSQL("DROP TABLE IF EXISTS " + TABLE_HOSTS); - onCreate(db); - return; - } - - switch (oldVersion) { - case 24: - db.execSQL("ALTER TABLE " + TABLE_HOSTS - + " ADD COLUMN " + FIELD_HOST_MONITOR + " TEXT"); - - case 25: - db.execSQL("ALTER TABLE " + TABLE_HOSTS - + " ADD COLUMN " + FIELD_HOST_EMULATION + " TEXT"); - db.execSQL("ALTER TABLE " + TABLE_HOSTS - + " ADD COLUMN " + FIELD_HOST_ENCRYPTION5250 + " TEXT"); - - case 26: - db.execSQL("ALTER TABLE " + TABLE_HOSTS - + " ADD COLUMN " + FIELD_HOST_LIBRARY5250 + " TEXT"); - db.execSQL("ALTER TABLE " + TABLE_HOSTS - + " ADD COLUMN " + FIELD_HOST_MENU5250 + " TEXT"); - db.execSQL("ALTER TABLE " + TABLE_HOSTS - + " ADD COLUMN " + FIELD_HOST_PROGRAM5250 + " TEXT"); - - case 27: - db.execSQL("ALTER TABLE " + TABLE_HOSTS - + " ADD COLUMN " + FIELD_HOST_FIXEDSIZE + " TEXT DEFAULT '" + Boolean.toString(false) + "'"); - db.execSQL("ALTER TABLE " + TABLE_HOSTS - + " ADD COLUMN " + FIELD_HOST_FIXEDWIDTH + " INTEGER"); - db.execSQL("ALTER TABLE " + TABLE_HOSTS - + " ADD COLUMN " + FIELD_HOST_FIXEDHEIGHT + " INTEGER"); - } - } - - /** - * Touch a specific host to update its "last connected" field. - * @param nickname Nickname field of host to update - */ - public void touchHost(HostBean host) { - long now = System.currentTimeMillis() / 1000; - ContentValues values = new ContentValues(); - values.put(FIELD_HOST_LASTCONNECT, now); - - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); - db.update(TABLE_HOSTS, values, "_id = ?", new String[] { String.valueOf(host.getId()) }); - } - } - - /** - * Create a new host using the given parameters. - */ - public HostBean saveHost(HostBean host) { - long id; - - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); - id = db.insert(TABLE_HOSTS, null, host.getValues()); - } - - host.setId(id); - return host; - } - - /** - * Update a field in a host record. - */ - public boolean updateFontSize(HostBean host) { - long id = host.getId(); - - if (id < 0) - return false; - - ContentValues updates = new ContentValues(); - updates.put(FIELD_HOST_FONTSIZE, host.getFontSize()); - - synchronized (dbLock) { - SQLiteDatabase db = getWritableDatabase(); - db.update(TABLE_HOSTS, updates, "_id = ?", - new String[] { String.valueOf(id) }); - } - - return true; - } - - /** - * Delete a specific host by its <code>_id</code> value. - */ - public void deleteHost(HostBean host) { - if (host.getId() < 0) - return; - - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); - db.delete(TABLE_HOSTS, "_id = ?", new String[] { String.valueOf(host.getId()) }); - } - } - - /** - * Return a cursor that contains information about all known hosts. - * @param sortColors If true, sort by color, otherwise sort by nickname. - */ - public List<HostBean> getHosts(boolean sortColors) { - String sortField = sortColors ? FIELD_HOST_COLOR : FIELD_HOST_NICKNAME; - List<HostBean> hosts; - - synchronized (dbLock) { - SQLiteDatabase db = this.getReadableDatabase(); - Cursor c = db.query(TABLE_HOSTS, null, null, null, null, null, sortField + " ASC"); - hosts = createHostBeans(c); - c.close(); - } - - return hosts; - } - - /** - * @param hosts - * @param c - */ - private List<HostBean> createHostBeans(Cursor c) { - List<HostBean> hosts = new LinkedList<HostBean>(); - final int COL_ID = c.getColumnIndexOrThrow("_id"), - COL_NICKNAME = c.getColumnIndexOrThrow(FIELD_HOST_NICKNAME), - COL_PROTOCOL = c.getColumnIndexOrThrow(FIELD_HOST_PROTOCOL), - COL_USERNAME = c.getColumnIndexOrThrow(FIELD_HOST_USERNAME), - COL_HOSTNAME = c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME), - COL_PORT = c.getColumnIndexOrThrow(FIELD_HOST_PORT), - COL_LASTCONNECT = c.getColumnIndexOrThrow(FIELD_HOST_LASTCONNECT), - COL_COLOR = c.getColumnIndexOrThrow(FIELD_HOST_COLOR), - COL_USEKEYS = c.getColumnIndexOrThrow(FIELD_HOST_USEKEYS), - COL_USEAUTHAGENT = c.getColumnIndexOrThrow(FIELD_HOST_USEAUTHAGENT), - COL_POSTLOGIN = c.getColumnIndexOrThrow(FIELD_HOST_POSTLOGIN), - COL_PUBKEYID = c.getColumnIndexOrThrow(FIELD_HOST_PUBKEYID), - COL_WANTSESSION = c.getColumnIndexOrThrow(FIELD_HOST_WANTSESSION), - COL_DELKEY = c.getColumnIndexOrThrow(FIELD_HOST_DELKEY), - COL_FONTSIZE = c.getColumnIndexOrThrow(FIELD_HOST_FONTSIZE), - COL_FIXEDSIZE = c.getColumnIndexOrThrow(FIELD_HOST_FIXEDSIZE), - COL_FIXEDWIDTH = c.getColumnIndexOrThrow(FIELD_HOST_FIXEDWIDTH), - COL_FIXEDHEIGHT = c.getColumnIndexOrThrow(FIELD_HOST_FIXEDHEIGHT), - COL_COMPRESSION = c.getColumnIndexOrThrow(FIELD_HOST_COMPRESSION), - COL_HTTPPROXY = c.getColumnIndexOrThrow(FIELD_HOST_HTTPPROXY), - COL_ENCODING = c.getColumnIndexOrThrow(FIELD_HOST_ENCODING), - COL_STAYCONNECTED = c.getColumnIndexOrThrow(FIELD_HOST_STAYCONNECTED), - COL_WANTX11FORWARD = c.getColumnIndexOrThrow(FIELD_HOST_WANTX11FORWARD), - COL_X11HOST = c.getColumnIndexOrThrow(FIELD_HOST_X11HOST), - COL_X11PORT = c.getColumnIndexOrThrow(FIELD_HOST_X11PORT), - COL_MONITOR = c.getColumnIndexOrThrow(FIELD_HOST_MONITOR), - COL_EMULATION = c.getColumnIndexOrThrow(FIELD_HOST_EMULATION), - COL_ENCRYPTION5250 = c.getColumnIndexOrThrow(FIELD_HOST_ENCRYPTION5250), - COL_LIBRARY5250 = c.getColumnIndexOrThrow(FIELD_HOST_LIBRARY5250), - COL_MENU5250 = c.getColumnIndexOrThrow(FIELD_HOST_MENU5250), - COL_PROGRAM5250 = c.getColumnIndexOrThrow(FIELD_HOST_PROGRAM5250); - - while (c.moveToNext()) { - HostBean host = new HostBean(); - host.setId(c.getLong(COL_ID)); - host.setNickname(c.getString(COL_NICKNAME)); - host.setProtocol(c.getString(COL_PROTOCOL)); - host.setUsername(c.getString(COL_USERNAME)); - host.setHostname(c.getString(COL_HOSTNAME)); - host.setPort(c.getInt(COL_PORT)); - host.setLastConnect(c.getLong(COL_LASTCONNECT)); - host.setColor(c.getString(COL_COLOR)); - host.setUseKeys(Boolean.valueOf(c.getString(COL_USEKEYS))); - host.setUseAuthAgent(c.getString(COL_USEAUTHAGENT)); - host.setPostLogin(c.getString(COL_POSTLOGIN)); - host.setPubkeyId(c.getLong(COL_PUBKEYID)); - host.setDelKey(c.getString(COL_DELKEY)); - host.setFontSize(c.getFloat(COL_FONTSIZE)); - host.setFixedSize(Boolean.valueOf(c.getString(COL_FIXEDSIZE))); - host.setFixedWidth(c.getInt(COL_FIXEDWIDTH)); - host.setFixedHeight(c.getInt(COL_FIXEDHEIGHT)); - host.setWantSession(Boolean.valueOf(c.getString(COL_WANTSESSION))); - host.setCompression(Boolean.valueOf(c.getString(COL_COMPRESSION))); - host.setHttpproxy(c.getString(COL_HTTPPROXY)); - host.setEncoding(c.getString(COL_ENCODING)); - host.setStayConnected(Boolean.valueOf(c.getString(COL_STAYCONNECTED))); - host.setWantX11Forward(Boolean.valueOf(c.getString(COL_WANTX11FORWARD))); - host.setX11Host(c.getString(COL_X11HOST)); - host.setX11Port(c.getInt(COL_X11PORT)); - host.setMonitor(c.getString(COL_MONITOR)); - host.setHostEmulation(c.getString(COL_EMULATION)); - host.setEncryption5250(c.getString(COL_ENCRYPTION5250)); - host.setLibrary(c.getString(COL_LIBRARY5250)); - host.setInitialMenu(c.getString(COL_MENU5250)); - host.setProgram(c.getString(COL_PROGRAM5250)); - hosts.add(host); - } - - return hosts; - } - - /** - * @param c - * @return - */ - private HostBean getFirstHostBean(Cursor c) { - HostBean host = null; - List<HostBean> hosts = createHostBeans(c); - - if (hosts.size() > 0) - host = hosts.get(0); - - c.close(); - return host; - } - - /** - * @param nickname - * @param protocol - * @param username - * @param hostname - * @param hostname2 - * @param port - * @return - */ - public HostBean findHost(Map<String, String> selection) { - StringBuilder selectionBuilder = new StringBuilder(); - Iterator<Entry<String, String>> i = selection.entrySet().iterator(); - List<String> selectionValuesList = new LinkedList<String>(); - int n = 0; - - while (i.hasNext()) { - Entry<String, String> entry = i.next(); - - if (entry.getValue() == null) - continue; - - if (n++ > 0) - selectionBuilder.append(" AND "); - - selectionBuilder.append(entry.getKey()) - .append(" = ?"); - selectionValuesList.add(entry.getValue()); - } - - String selectionValues[] = new String[selectionValuesList.size()]; - selectionValuesList.toArray(selectionValues); - selectionValuesList = null; - HostBean host; - - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); - Cursor c = db.query(TABLE_HOSTS, null, - selectionBuilder.toString(), - selectionValues, - null, null, null); - host = getFirstHostBean(c); - } - - return host; - } - - /** - * @param hostId - * @return - */ - public HostBean findHostById(long hostId) { - HostBean host; - - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); - Cursor c = db.query(TABLE_HOSTS, null, - "_id = ?", new String[] { String.valueOf(hostId) }, - null, null, null); - host = getFirstHostBean(c); - } - - return host; - } - - /** - * Record the given hostkey into database under this nickname. - * @param hostname - * @param port - * @param hostkeyalgo - * @param hostkey - */ - public void saveKnownHost(String hostname, int port, String hostkeyalgo, byte[] hostkey) { - ContentValues values = new ContentValues(); - values.put(FIELD_HOST_HOSTKEYALGO, hostkeyalgo); - values.put(FIELD_HOST_HOSTKEY, hostkey); - - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); - db.update(TABLE_HOSTS, values, - FIELD_HOST_HOSTNAME + " = ? AND " + FIELD_HOST_PORT + " = ?", - new String[] { hostname, String.valueOf(port) }); - Log.d(TAG, String.format("Finished saving hostkey information for '%s'", hostname)); - } - } - - /** - * Build list of known hosts for Trilead library. - * @return - */ - public KnownHosts getKnownHosts() { - KnownHosts known = new KnownHosts(); - - synchronized (dbLock) { - SQLiteDatabase db = this.getReadableDatabase(); - Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_HOSTNAME, - FIELD_HOST_PORT, FIELD_HOST_HOSTKEYALGO, FIELD_HOST_HOSTKEY - }, - null, null, null, null, null); - - if (c != null) { - int COL_HOSTNAME = c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME), - COL_PORT = c.getColumnIndexOrThrow(FIELD_HOST_PORT), - COL_HOSTKEYALGO = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEYALGO), - COL_HOSTKEY = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEY); - - while (c.moveToNext()) { - String hostname = c.getString(COL_HOSTNAME), - hostkeyalgo = c.getString(COL_HOSTKEYALGO); - int port = c.getInt(COL_PORT); - byte[] hostkey = c.getBlob(COL_HOSTKEY); - - if (hostkeyalgo == null || hostkeyalgo.length() == 0) continue; - - if (hostkey == null || hostkey.length == 0) continue; - - try { - known.addHostkey(new String[] { String.format("%s:%d", hostname, port) }, hostkeyalgo, hostkey); - } - catch (Exception e) { - Log.e(TAG, "Problem while adding a known host from database", e); - } - } - - c.close(); - } - } - - return known; - } - - /** - * Unset any hosts using a pubkey ID that has been deleted. - * @param pubkeyId - */ - public void stopUsingPubkey(long pubkeyId) { - if (pubkeyId < 0) return; - - ContentValues values = new ContentValues(); - values.put(FIELD_HOST_PUBKEYID, PUBKEYID_ANY); - - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); - db.update(TABLE_HOSTS, values, FIELD_HOST_PUBKEYID + " = ?", new String[] { String.valueOf(pubkeyId) }); - } - - Log.d(TAG, String.format("Set all hosts using pubkey id %d to -1", pubkeyId)); - } - - /* - * Methods for dealing with port forwards attached to hosts - */ - - /** - * Returns a list of all the port forwards associated with a particular host ID. - * @param host the host for which we want the port forward list - * @return port forwards associated with host ID - */ - public List<PortForwardBean> getPortForwardsForHost(HostBean host) { - List<PortForwardBean> portForwards = new LinkedList<PortForwardBean>(); - - synchronized (dbLock) { - SQLiteDatabase db = this.getReadableDatabase(); - Cursor c = db.query(TABLE_PORTFORWARDS, new String[] { - "_id", FIELD_PORTFORWARD_NICKNAME, FIELD_PORTFORWARD_TYPE, FIELD_PORTFORWARD_SOURCEPORT, - FIELD_PORTFORWARD_DESTADDR, FIELD_PORTFORWARD_DESTPORT - }, - FIELD_PORTFORWARD_HOSTID + " = ?", new String[] { String.valueOf(host.getId()) }, - null, null, null); - - while (c.moveToNext()) { - PortForwardBean pfb = new PortForwardBean( - c.getInt(0), - host.getId(), - c.getString(1), - c.getString(2), - c.getInt(3), - c.getString(4), - c.getInt(5)); - portForwards.add(pfb); - } - - c.close(); - } - - return portForwards; - } - - /** - * Update the parameters of a port forward in the database. - * @param pfb {@link PortForwardBean} to save - * @return true on success - */ - public boolean savePortForward(PortForwardBean pfb) { - boolean success = false; - - synchronized (dbLock) { - SQLiteDatabase db = getWritableDatabase(); - - if (pfb.getId() < 0) { - long id = db.insert(TABLE_PORTFORWARDS, null, pfb.getValues()); - pfb.setId(id); - success = true; - } - else { - if (db.update(TABLE_PORTFORWARDS, pfb.getValues(), "_id = ?", new String[] { String.valueOf(pfb.getId()) }) > 0) - success = true; - } - } - - return success; - } - - /** - * Deletes a port forward from the database. - * @param pfb {@link PortForwardBean} to delete - */ - public void deletePortForward(PortForwardBean pfb) { - if (pfb.getId() < 0) - return; - - synchronized (dbLock) { - SQLiteDatabase db = this.getWritableDatabase(); - db.delete(TABLE_PORTFORWARDS, "_id = ?", new String[] { String.valueOf(pfb.getId()) }); - } - } - - public Integer[] getColorsForScheme(int scheme) { - Integer[] colors = Colors.defaults.clone(); - - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); - Cursor c = db.query(TABLE_COLORS, new String[] { - FIELD_COLOR_NUMBER, FIELD_COLOR_VALUE - }, - FIELD_COLOR_SCHEME + " = ?", - new String[] { String.valueOf(scheme) }, - null, null, null); - - while (c.moveToNext()) { - colors[c.getInt(0)] = Integer.valueOf(c.getInt(1)); - } - - c.close(); - } - - return colors; - } - - public void setColorForScheme(int scheme, int number, int value) { - final SQLiteDatabase db; - final String[] whereArgs = new String[] { String.valueOf(scheme), String.valueOf(number) }; - - if (value == Colors.defaults[number]) { - synchronized (dbLock) { - db = getWritableDatabase(); - db.delete(TABLE_COLORS, - WHERE_SCHEME_AND_COLOR, whereArgs); - } - } - else { - final ContentValues values = new ContentValues(); - values.put(FIELD_COLOR_VALUE, value); - - synchronized (dbLock) { - db = getWritableDatabase(); - final int rowsAffected = db.update(TABLE_COLORS, values, - WHERE_SCHEME_AND_COLOR, whereArgs); - - if (rowsAffected == 0) { - values.put(FIELD_COLOR_SCHEME, scheme); - values.put(FIELD_COLOR_NUMBER, number); - db.insert(TABLE_COLORS, null, values); - } - } - } - } - - public void setGlobalColor(int number, int value) { - setColorForScheme(DEFAULT_COLOR_SCHEME, number, value); - } - - public int[] getDefaultColorsForScheme(int scheme) { - int[] colors = new int[] { DEFAULT_FG_COLOR, DEFAULT_BG_COLOR }; - - synchronized (dbLock) { - SQLiteDatabase db = getReadableDatabase(); - Cursor c = db.query(TABLE_COLOR_DEFAULTS, - new String[] { FIELD_COLOR_FG, FIELD_COLOR_BG }, - FIELD_COLOR_SCHEME + " = ?", - new String[] { String.valueOf(scheme) }, - null, null, null); - - if (c.moveToFirst()) { - colors[0] = c.getInt(0); - colors[1] = c.getInt(1); - } - - c.close(); - } - - return colors; - } - - public int[] getGlobalDefaultColors() { - return getDefaultColorsForScheme(DEFAULT_COLOR_SCHEME); - } - - public void setDefaultColorsForScheme(int scheme, int fg, int bg) { - SQLiteDatabase db; - String schemeWhere = null; - String[] whereArgs; - schemeWhere = FIELD_COLOR_SCHEME + " = ?"; - whereArgs = new String[] { String.valueOf(scheme) }; - ContentValues values = new ContentValues(); - values.put(FIELD_COLOR_FG, fg); - values.put(FIELD_COLOR_BG, bg); - - synchronized (dbLock) { - db = getWritableDatabase(); - int rowsAffected = db.update(TABLE_COLOR_DEFAULTS, values, - schemeWhere, whereArgs); - - if (rowsAffected == 0) { - values.put(FIELD_COLOR_SCHEME, scheme); - db.insert(TABLE_COLOR_DEFAULTS, null, values); - } - } - } -}
--- a/src/com/five_ten_sg/connectbot/util/OnDbWrittenListener.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2010 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -/** - * @author kroot - * - */ -public interface OnDbWrittenListener { - public void onDbWritten(); -}
--- a/src/com/five_ten_sg/connectbot/util/OnEntropyGatheredListener.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -public interface OnEntropyGatheredListener { - void onEntropyGathered(byte[] entropy); -}
--- a/src/com/five_ten_sg/connectbot/util/PreferenceConstants.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import android.os.Build; - - -/** - * @author Kenny Root - * - */ -public class PreferenceConstants { - public static final boolean PRE_HONEYCOMB = - (Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.HONEYCOMB); - - public static final String CATEGORY_UI = "category_ui"; - - public static final String MEMKEYS = "memkeys"; - public static final String SCROLLBACK = "scrollback"; - public static final String EMULATION = "emulation"; - public static final String ROTATION = "rotation"; - - public static final String ROTATION_DEFAULT = "Default"; - public static final String ROTATION_LANDSCAPE = "Force landscape"; - public static final String ROTATION_PORTRAIT = "Force portrait"; - public static final String ROTATION_AUTOMATIC = "Automatic"; - - public static final String KEYMODE = "keymode"; - - public static final String KEYMODE_RIGHT = "Use right-side keys"; - public static final String KEYMODE_LEFT = "Use left-side keys"; - - // must match android:key values in preferences.xml - public static final String CAMERA = "camera"; - public static final String VOLUP = "volup"; - public static final String VOLDN = "voldn"; - public static final String SEARCH = "search"; - public static final String PTT = "ptt"; - - // must match arrays.xml/list_hw_button_values - public static final String HWBUTTON_CTRL = "CTRL"; - public static final String HWBUTTON_ESC = "Esc"; - public static final String HWBUTTON_TAB = "Tab"; - public static final String HWBUTTON_SCREEN_CAPTURE = "Screen Capture"; - public static final String HWBUTTON_CTRLA_SPACE = "Ctrl+A then Space"; - public static final String HWBUTTON_CTRLA = "Ctrl+A"; - public static final String HWBUTTON_ESC_A = "Esc+A"; - public static final String HWBUTTON_MONITOR = "Monitor Key"; - public static final String HWBUTTON_FUNCTION_KEYS = "Soft Function Keypad"; - public static final String HWBUTTON_INCREASE_FONTSIZE = "Increase Font Size"; - public static final String HWBUTTON_DECREASE_FONTSIZE = "Decrease Font Size"; - public static final String HWBUTTON_NONE = "None"; - - public static final String KEEP_ALIVE = "keepalive"; - - public static final String WIFI_LOCK = "wifilock"; - - public static final String BUMPY_ARROWS = "bumpyarrows"; - - public static final String EULA = "eula"; - - public static final String SORT_BY_COLOR = "sortByColor"; - - public static final String BELL = "bell"; - public static final String BELL_VOLUME = "bellVolume"; - public static final String BELL_VIBRATE = "bellVibrate"; - public static final String BELL_NOTIFICATION = "bellNotification"; - public static final float DEFAULT_BELL_VOLUME = 0.25f; - - public static final String CONNECTION_PERSIST = "connPersist"; - - public static final String SHIFT_FKEYS = "shiftfkeys"; - public static final String CTRL_FKEYS = "ctrlfkeys"; - - /* Backup identifiers */ - public static final String BACKUP_PREF_KEY = "prefs"; - - public static final String CTRL_STRING = "ctrl_string"; - public static final String PICKER_STRING = "picker_string"; - public static final String PICKER_KEEP_OPEN = "picker_keep_open"; - public static final String EXTENDED_LONGPRESS = "extended_longpress"; - public static final String SCREEN_CAPTURE_POPUP = "screen_capture_popup"; - public static final String SCREEN_CAPTURE_FOLDER = "screen_capture_folder"; - public static final String FILE_DIALOG = "file_dialog"; - public static final String DOWNLOAD_FOLDER = "download_folder"; - public static final String REMOTE_UPLOAD_FOLDER = "remote_upload_folder"; - public static final String BACKGROUND_FILE_TRANSFER = "background_file_transfer"; - public static final String UPLOAD_DESTINATION_PROMPT = "upload_dest_prompt"; - - /* Debug */ - public static final String DEBUG_KEYCODES = "debug_keycodes"; - - /* Device keyboard mapping */ - public static final String CUSTOM_KEYMAP = "list_custom_keymap"; - // must match arrays.xml/list_custom_keymap_values - public static final String CUSTOM_KEYMAP_DISABLED = "none"; - public static final String CUSTOM_KEYMAP_FULL = "full"; - public static final String CUSTOM_KEYMAP_ASUS_TF = "asus_tf"; - public static final String CUSTOM_KEYMAP_SGH_I927 = "sgh_i927"; - public static final String CUSTOM_KEYMAP_SGH_I927_ICS = "sgh_i927_ics"; - public static final String CUSTOM_KEYMAP_SE_XPPRO = "se_xppro"; -}
--- a/src/com/five_ten_sg/connectbot/util/PubkeyDatabase.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,311 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import java.util.LinkedList; -import java.util.List; - -import com.five_ten_sg.connectbot.bean.PubkeyBean; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; - -/** - * Public Key Encryption database. Contains private and public key pairs - * for public key authentication. - * - * @author Kenny Root - */ -public class PubkeyDatabase extends RobustSQLiteOpenHelper { - public final static String TAG = "ConnectBot.PubkeyDatabase"; - - public final static String DB_NAME = "pubkeys"; - public final static int DB_VERSION = 2; - - public final static String TABLE_PUBKEYS = "pubkeys"; - public final static String FIELD_PUBKEY_NICKNAME = "nickname"; - public final static String FIELD_PUBKEY_TYPE = "type"; - public final static String FIELD_PUBKEY_PRIVATE = "private"; - public final static String FIELD_PUBKEY_PUBLIC = "public"; - public final static String FIELD_PUBKEY_ENCRYPTED = "encrypted"; - public final static String FIELD_PUBKEY_STARTUP = "startup"; - public final static String FIELD_PUBKEY_CONFIRMUSE = "confirmuse"; - public final static String FIELD_PUBKEY_LIFETIME = "lifetime"; - - public final static String KEY_TYPE_RSA = "RSA", - KEY_TYPE_DSA = "DSA", - KEY_TYPE_IMPORTED = "IMPORTED", - KEY_TYPE_EC = "EC"; - - private Context context; - - static { - addTableName(TABLE_PUBKEYS); - } - - public PubkeyDatabase(Context context) { - super(context, DB_NAME, null, DB_VERSION); - this.context = context; - } - - @Override - public void onCreate(SQLiteDatabase db) { - super.onCreate(db); - db.execSQL("CREATE TABLE " + TABLE_PUBKEYS - + " (_id INTEGER PRIMARY KEY, " - + FIELD_PUBKEY_NICKNAME + " TEXT, " - + FIELD_PUBKEY_TYPE + " TEXT, " - + FIELD_PUBKEY_PRIVATE + " BLOB, " - + FIELD_PUBKEY_PUBLIC + " BLOB, " - + FIELD_PUBKEY_ENCRYPTED + " INTEGER, " - + FIELD_PUBKEY_STARTUP + " INTEGER, " - + FIELD_PUBKEY_CONFIRMUSE + " INTEGER DEFAULT 0, " - + FIELD_PUBKEY_LIFETIME + " INTEGER DEFAULT 0)"); - } - - @Override - public void onRobustUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLiteException { - switch (oldVersion) { - case 1: - db.execSQL("ALTER TABLE " + TABLE_PUBKEYS - + " ADD COLUMN " + FIELD_PUBKEY_CONFIRMUSE + " INTEGER DEFAULT 0"); - db.execSQL("ALTER TABLE " + TABLE_PUBKEYS - + " ADD COLUMN " + FIELD_PUBKEY_LIFETIME + " INTEGER DEFAULT 0"); - } - } - - /** - * Delete a specific host by its <code>_id</code> value. - */ - public void deletePubkey(PubkeyBean pubkey) { - HostDatabase hostdb = new HostDatabase(context); - hostdb.stopUsingPubkey(pubkey.getId()); - hostdb.close(); - SQLiteDatabase db = getWritableDatabase(); - db.delete(TABLE_PUBKEYS, "_id = ?", new String[] { Long.toString(pubkey.getId()) }); - db.close(); - } - - /** - * Return a cursor that contains information about all known hosts. - */ - /* - public Cursor allPubkeys() { - SQLiteDatabase db = this.getReadableDatabase(); - return db.query(TABLE_PUBKEYS, new String[] { "_id", - FIELD_PUBKEY_NICKNAME, FIELD_PUBKEY_TYPE, FIELD_PUBKEY_PRIVATE, - FIELD_PUBKEY_PUBLIC, FIELD_PUBKEY_ENCRYPTED, FIELD_PUBKEY_STARTUP }, - null, null, null, null, null); - }*/ - - public List<PubkeyBean> allPubkeys() { - return getPubkeys(null, null); - } - - public List<PubkeyBean> getAllStartPubkeys() { - return getPubkeys(FIELD_PUBKEY_STARTUP + " = 1 AND " + FIELD_PUBKEY_ENCRYPTED + " = 0", null); - } - - private List<PubkeyBean> getPubkeys(String selection, String[] selectionArgs) { - SQLiteDatabase db = getReadableDatabase(); - List<PubkeyBean> pubkeys = new LinkedList<PubkeyBean>(); - Cursor c = db.query(TABLE_PUBKEYS, null, selection, selectionArgs, null, null, null); - - if (c != null) { - final int COL_ID = c.getColumnIndexOrThrow("_id"), - COL_NICKNAME = c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME), - COL_TYPE = c.getColumnIndexOrThrow(FIELD_PUBKEY_TYPE), - COL_PRIVATE = c.getColumnIndexOrThrow(FIELD_PUBKEY_PRIVATE), - COL_PUBLIC = c.getColumnIndexOrThrow(FIELD_PUBKEY_PUBLIC), - COL_ENCRYPTED = c.getColumnIndexOrThrow(FIELD_PUBKEY_ENCRYPTED), - COL_STARTUP = c.getColumnIndexOrThrow(FIELD_PUBKEY_STARTUP), - COL_CONFIRMUSE = c.getColumnIndexOrThrow(FIELD_PUBKEY_CONFIRMUSE), - COL_LIFETIME = c.getColumnIndexOrThrow(FIELD_PUBKEY_LIFETIME); - - while (c.moveToNext()) { - PubkeyBean pubkey = new PubkeyBean(); - pubkey.setId(c.getLong(COL_ID)); - pubkey.setNickname(c.getString(COL_NICKNAME)); - pubkey.setType(c.getString(COL_TYPE)); - pubkey.setPrivateKey(c.getBlob(COL_PRIVATE)); - pubkey.setPublicKey(c.getBlob(COL_PUBLIC)); - pubkey.setEncrypted(c.getInt(COL_ENCRYPTED) > 0); - pubkey.setStartup(c.getInt(COL_STARTUP) > 0); - pubkey.setConfirmUse(c.getInt(COL_CONFIRMUSE) > 0); - pubkey.setLifetime(c.getInt(COL_LIFETIME)); - pubkeys.add(pubkey); - } - - c.close(); - } - - db.close(); - return pubkeys; - } - - /** - * @param hostId - * @return - */ - public PubkeyBean findPubkeyById(long pubkeyId) { - SQLiteDatabase db = getReadableDatabase(); - Cursor c = db.query(TABLE_PUBKEYS, null, - "_id = ?", new String[] { String.valueOf(pubkeyId) }, - null, null, null); - PubkeyBean pubkey = null; - - if (c != null) { - if (c.moveToFirst()) - pubkey = createPubkeyBean(c); - - c.close(); - } - - db.close(); - return pubkey; - } - - private PubkeyBean createPubkeyBean(Cursor c) { - PubkeyBean pubkey = new PubkeyBean(); - pubkey.setId(c.getLong(c.getColumnIndexOrThrow("_id"))); - pubkey.setNickname(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME))); - pubkey.setType(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_TYPE))); - pubkey.setPrivateKey(c.getBlob(c.getColumnIndexOrThrow(FIELD_PUBKEY_PRIVATE))); - pubkey.setPublicKey(c.getBlob(c.getColumnIndexOrThrow(FIELD_PUBKEY_PUBLIC))); - pubkey.setEncrypted(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_ENCRYPTED)) > 0); - pubkey.setStartup(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_STARTUP)) > 0); - pubkey.setConfirmUse(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_CONFIRMUSE)) > 0); - pubkey.setLifetime(c.getInt(c.getColumnIndexOrThrow(FIELD_PUBKEY_LIFETIME))); - return pubkey; - } - - /** - * Pull all values for a given column as a list of Strings, probably for use - * in a ListPreference. Sorted by <code>_id</code> ascending. - */ - public List<CharSequence> allValues(String column) { - List<CharSequence> list = new LinkedList<CharSequence>(); - SQLiteDatabase db = this.getReadableDatabase(); - Cursor c = db.query(TABLE_PUBKEYS, new String[] { "_id", column }, - null, null, null, null, "_id ASC"); - - if (c != null) { - int COL = c.getColumnIndexOrThrow(column); - - while (c.moveToNext()) - list.add(c.getString(COL)); - - c.close(); - } - - db.close(); - return list; - } - - public String getNickname(long id) { - String nickname = null; - SQLiteDatabase db = this.getReadableDatabase(); - Cursor c = db.query(TABLE_PUBKEYS, new String[] { "_id", - FIELD_PUBKEY_NICKNAME - }, "_id = ?", - new String[] { Long.toString(id) }, null, null, null); - - if (c != null) { - if (c.moveToFirst()) - nickname = c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME)); - - c.close(); - } - - db.close(); - return nickname; - } - - /* - public void setOnStart(long id, boolean onStart) { - - SQLiteDatabase db = this.getWritableDatabase(); - - ContentValues values = new ContentValues(); - values.put(FIELD_PUBKEY_STARTUP, onStart ? 1 : 0); - - db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { Long.toString(id) }); - - } - - public boolean changePassword(long id, String oldPassword, String newPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException { - SQLiteDatabase db = this.getWritableDatabase(); - - Cursor c = db.query(TABLE_PUBKEYS, new String[] { FIELD_PUBKEY_TYPE, - FIELD_PUBKEY_PRIVATE, FIELD_PUBKEY_ENCRYPTED }, - "_id = ?", new String[] { String.valueOf(id) }, - null, null, null); - - if (!c.moveToFirst()) - return false; - - String keyType = c.getString(0); - byte[] encPriv = c.getBlob(1); - c.close(); - - PrivateKey priv; - try { - priv = PubkeyUtils.decodePrivate(encPriv, keyType, oldPassword); - } catch (InvalidKeyException e) { - return false; - } catch (BadPaddingException e) { - return false; - } catch (InvalidKeySpecException e) { - return false; - } - - ContentValues values = new ContentValues(); - values.put(FIELD_PUBKEY_PRIVATE, PubkeyUtils.getEncodedPrivate(priv, newPassword)); - values.put(FIELD_PUBKEY_ENCRYPTED, newPassword.length() > 0 ? 1 : 0); - db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(id) }); - - return true; - } - */ - - /** - * @param pubkey - */ - public PubkeyBean savePubkey(PubkeyBean pubkey) { - SQLiteDatabase db = this.getWritableDatabase(); - boolean success = false; - ContentValues values = pubkey.getValues(); - - if (pubkey.getId() > 0) { - values.remove("_id"); - - if (db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(pubkey.getId()) }) > 0) - success = true; - } - - if (!success) { - long id = db.insert(TABLE_PUBKEYS, null, pubkey.getValues()); - pubkey.setId(id); - } - - db.close(); - return pubkey; - } -}
--- a/src/com/five_ten_sg/connectbot/util/PubkeyUtils.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,392 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.AlgorithmParameters; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.interfaces.DSAParams; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.DSAPublicKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPrivateCrtKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.DSAPublicKeySpec; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.InvalidParameterSpecException; -import java.security.spec.KeySpec; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.RSAPublicKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.Arrays; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.EncryptedPrivateKeyInfo; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import org.keyczar.jce.EcCore; - -import com.five_ten_sg.connectbot.bean.PubkeyBean; -import android.util.Log; - -import ch.ethz.ssh2.crypto.Base64; -import ch.ethz.ssh2.crypto.SecureRandomFix; -import ch.ethz.ssh2.crypto.SimpleDERReader; -import ch.ethz.ssh2.signature.DSASHA1Verify; -import ch.ethz.ssh2.signature.ECDSASHA2Verify; -import ch.ethz.ssh2.signature.RSASHA1Verify; - -public class PubkeyUtils { - private static final String TAG = "PubkeyUtils"; - - public static final String PKCS8_START = "-----BEGIN PRIVATE KEY-----"; - public static final String PKCS8_END = "-----END PRIVATE KEY-----"; - - // Size in bytes of salt to use. - private static final int SALT_SIZE = 8; - - // Number of iterations for password hashing. PKCS#5 recommends 1000 - private static final int ITERATIONS = 1000; - - // Cannot be instantiated - private PubkeyUtils() { - } - - public static String formatKey(Key key) { - String algo = key.getAlgorithm(); - String fmt = key.getFormat(); - byte[] encoded = key.getEncoded(); - return "Key[algorithm=" + algo + ", format=" + fmt + - ", bytes=" + encoded.length + "]"; - } - - public static byte[] sha256(byte[] data) throws NoSuchAlgorithmException { - return MessageDigest.getInstance("SHA-256").digest(data); - } - - public static byte[] cipher(int mode, byte[] data, byte[] secret) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { - SecretKeySpec secretKeySpec = new SecretKeySpec(sha256(secret), "AES"); - Cipher c = Cipher.getInstance("AES"); - c.init(mode, secretKeySpec); - return c.doFinal(data); - } - - public static byte[] encrypt(byte[] cleartext, String secret) throws Exception { - byte[] salt = new byte[SALT_SIZE]; - byte[] ciphertext = Encryptor.encrypt(salt, ITERATIONS, secret, cleartext); - byte[] complete = new byte[salt.length + ciphertext.length]; - System.arraycopy(salt, 0, complete, 0, salt.length); - System.arraycopy(ciphertext, 0, complete, salt.length, ciphertext.length); - Arrays.fill(salt, (byte) 0x00); - Arrays.fill(ciphertext, (byte) 0x00); - return complete; - } - - public static byte[] decrypt(byte[] saltAndCiphertext, String secret) throws Exception { - try { - byte[] salt = new byte[SALT_SIZE]; - byte[] ciphertext = new byte[saltAndCiphertext.length - salt.length]; - System.arraycopy(saltAndCiphertext, 0, salt, 0, salt.length); - System.arraycopy(saltAndCiphertext, salt.length, ciphertext, 0, ciphertext.length); - return Encryptor.decrypt(salt, ITERATIONS, secret, ciphertext); - } - catch (Exception e) { - Log.d("decrypt", "Could not decrypt with new method", e); - // We might be using the old encryption method. - return cipher(Cipher.DECRYPT_MODE, saltAndCiphertext, secret.getBytes()); - } - } - - public static byte[] getEncodedPrivate(PrivateKey pk, String secret) throws Exception { - final byte[] encoded = pk.getEncoded(); - - if (secret == null || secret.length() == 0) { - return encoded; - } - - return encrypt(pk.getEncoded(), secret); - } - - public static PrivateKey decodePrivate(byte[] encoded, String keyType) throws NoSuchAlgorithmException, InvalidKeySpecException { - PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(encoded); - KeyFactory kf = KeyFactory.getInstance(keyType); - return kf.generatePrivate(privKeySpec); - } - - public static PrivateKey decodePrivate(byte[] encoded, String keyType, String secret) throws Exception { - if (secret != null && secret.length() > 0) - return decodePrivate(decrypt(encoded, secret), keyType); - else - return decodePrivate(encoded, keyType); - } - - public static PublicKey decodePublic(byte[] encoded, String keyType) throws NoSuchAlgorithmException, InvalidKeySpecException { - X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encoded); - KeyFactory kf = KeyFactory.getInstance(keyType); - return kf.generatePublic(pubKeySpec); - } - - static String getAlgorithmForOid(String oid) throws NoSuchAlgorithmException { - if ("1.2.840.10045.2.1".equals(oid)) { - return "EC"; - } - else if ("1.2.840.113549.1.1.1".equals(oid)) { - return "RSA"; - } - else if ("1.2.840.10040.4.1".equals(oid)) { - return "DSA"; - } - else { - throw new NoSuchAlgorithmException("Unknown algorithm OID " + oid); - } - } - - static String getOidFromPkcs8Encoded(byte[] encoded) throws NoSuchAlgorithmException { - if (encoded == null) { - throw new NoSuchAlgorithmException("encoding is null"); - } - - try { - SimpleDERReader reader = new SimpleDERReader(encoded); - reader.resetInput(reader.readSequenceAsByteArray()); - reader.readInt(); - reader.resetInput(reader.readSequenceAsByteArray()); - return reader.readOid(); - } - catch (IOException e) { - Log.w(TAG, "Could not read OID", e); - throw new NoSuchAlgorithmException("Could not read key", e); - } - } - - public static KeyPair recoverKeyPair(byte[] encoded) throws NoSuchAlgorithmException, - InvalidKeySpecException { - final String algo = getAlgorithmForOid(getOidFromPkcs8Encoded(encoded)); - final KeySpec privKeySpec = new PKCS8EncodedKeySpec(encoded); - final KeyFactory kf = KeyFactory.getInstance(algo); - final PrivateKey priv = kf.generatePrivate(privKeySpec); - return new KeyPair(recoverPublicKey(kf, priv), priv); - } - - - static PublicKey recoverPublicKey(KeyFactory kf, PrivateKey priv) - throws NoSuchAlgorithmException, InvalidKeySpecException { - if (priv instanceof RSAPrivateCrtKey) { - RSAPrivateCrtKey rsaPriv = (RSAPrivateCrtKey) priv; - return kf.generatePublic(new RSAPublicKeySpec(rsaPriv.getModulus(), rsaPriv - .getPublicExponent())); - } - else if (priv instanceof DSAPrivateKey) { - DSAPrivateKey dsaPriv = (DSAPrivateKey) priv; - DSAParams params = dsaPriv.getParams(); - // Calculate public key Y - BigInteger y = params.getG().modPow(dsaPriv.getX(), params.getP()); - return kf.generatePublic(new DSAPublicKeySpec(y, params.getP(), params.getQ(), params - .getG())); - } - else if (priv instanceof ECPrivateKey) { - ECPrivateKey ecPriv = (ECPrivateKey) priv; - ECParameterSpec params = ecPriv.getParams(); - // Calculate public key Y - ECPoint generator = params.getGenerator(); - BigInteger[] wCoords = EcCore.multiplyPointA(new BigInteger[] { generator.getAffineX(), - generator.getAffineY() - }, ecPriv.getS(), params); - ECPoint w = new ECPoint(wCoords[0], wCoords[1]); - return kf.generatePublic(new ECPublicKeySpec(w, params)); - } - else { - throw new NoSuchAlgorithmException("Key type must be RSA, DSA, or EC"); - } - } - - /* - * OpenSSH compatibility methods - */ - - public static String convertToOpenSSHFormat(PublicKey pk, String origNickname) throws IOException, InvalidKeyException { - String nickname = origNickname; - - if (nickname == null) - nickname = "connectbot@android"; - - if (pk instanceof RSAPublicKey) { - String data = "ssh-rsa "; - data += String.valueOf(Base64.encode(RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey) pk))); - return data + " " + nickname; - } - else if (pk instanceof DSAPublicKey) { - String data = "ssh-dss "; - data += String.valueOf(Base64.encode(DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey) pk))); - return data + " " + nickname; - } - else if (pk instanceof ECPublicKey) { - ECPublicKey ecPub = (ECPublicKey) pk; - String keyType = ECDSASHA2Verify.getCurveName(ecPub.getParams().getCurve().getField().getFieldSize()); - String keyData = String.valueOf(Base64.encode(ECDSASHA2Verify.encodeSSHECDSAPublicKey(ecPub))); - return ECDSASHA2Verify.ECDSA_SHA2_PREFIX + keyType + " " + keyData + " " + nickname; - } - - throw new InvalidKeyException("Unknown key type"); - } - - /* - * OpenSSH compatibility methods - */ - - /** - * @param pair - * @return OpenSSH-encoded pubkey - */ - public static byte[] extractOpenSSHPublic(KeyPair pair) { - try { - PublicKey pubKey = pair.getPublic(); - - if (pubKey instanceof RSAPublicKey) { - return RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey) pair.getPublic()); - } - else if (pubKey instanceof DSAPublicKey) { - return DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey) pair.getPublic()); - } - else if (pubKey instanceof ECPublicKey) { - return ECDSASHA2Verify.encodeSSHECDSAPublicKey((ECPublicKey) pair.getPublic()); - } - else { - return null; - } - } - catch (IOException e) { - return null; - } - } - - public static String exportPEM(PrivateKey key, String secret) throws NoSuchAlgorithmException, InvalidParameterSpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, InvalidKeySpecException, IllegalBlockSizeException, IOException { - StringBuilder sb = new StringBuilder(); - byte[] data = key.getEncoded(); - sb.append(PKCS8_START); - sb.append('\n'); - - if (secret != null) { - byte[] salt = new byte[8]; - SecureRandomFix random = new SecureRandomFix(); - random.nextBytes(salt); - PBEParameterSpec defParams = new PBEParameterSpec(salt, 1); - AlgorithmParameters params = AlgorithmParameters.getInstance(key.getAlgorithm()); - params.init(defParams); - PBEKeySpec pbeSpec = new PBEKeySpec(secret.toCharArray()); - SecretKeyFactory keyFact = SecretKeyFactory.getInstance(key.getAlgorithm()); - Cipher cipher = Cipher.getInstance(key.getAlgorithm()); - cipher.init(Cipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), params); - byte[] wrappedKey = cipher.wrap(key); - EncryptedPrivateKeyInfo pinfo = new EncryptedPrivateKeyInfo(params, wrappedKey); - data = pinfo.getEncoded(); - sb.append("Proc-Type: 4,ENCRYPTED\n"); - sb.append("DEK-Info: DES-EDE3-CBC,"); - sb.append(encodeHex(salt)); - sb.append("\n\n"); - } - - int i = sb.length(); - sb.append(Base64.encode(data)); - - for (i += 63; i < sb.length(); i += 64) { - sb.insert(i, "\n"); - } - - sb.append('\n'); - sb.append(PKCS8_END); - sb.append('\n'); - return sb.toString(); - } - - private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', - '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - protected static String encodeHex(byte[] bytes) { - final char[] hex = new char[bytes.length * 2]; - int i = 0; - - for (byte b : bytes) { - hex[i++] = HEX_DIGITS[(b >> 4) & 0x0f]; - hex[i++] = HEX_DIGITS[b & 0x0f]; - } - - return String.valueOf(hex); - } - - public static String getPubkeyString(PubkeyBean pubkey) { - try { - PublicKey pk = decodePublic(pubkey.getPublicKey(), pubkey.getType()); - return convertToOpenSSHFormat(pk, pubkey.getNickname()); - } - catch (Exception e) { - e.printStackTrace(); - } - - return null; - } - - public static String getPrivkeyString(PubkeyBean pubkey, String passphrase) { - String data = null; - boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType()); - - if (imported) - try { - data = new String(pubkey.getPrivateKey()); - } - catch (Exception e) { - e.printStackTrace(); - } - else { - try { - PrivateKey pk = null; - - if (passphrase == null) - pk = decodePrivate(pubkey.getPrivateKey(), pubkey.getType()); - else - pk = decodePrivate(pubkey.getPrivateKey(), pubkey.getType(), passphrase); - - data = exportPEM(pk, passphrase); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - return data; - } -}
--- a/src/com/five_ten_sg/connectbot/util/RobustSQLiteOpenHelper.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import java.util.LinkedList; -import java.util.List; - -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabase.CursorFactory; -import android.database.sqlite.SQLiteException; -import android.database.sqlite.SQLiteOpenHelper; - -/** - * @author Kenny Root - * - */ -public abstract class RobustSQLiteOpenHelper extends SQLiteOpenHelper { - private static List<String> mTableNames = new LinkedList<String>(); - private static List<String> mIndexNames = new LinkedList<String>(); - - public RobustSQLiteOpenHelper(Context context, String name, - CursorFactory factory, int version) { - super(context, name, factory, version); - } - - protected static void addTableName(String tableName) { - mTableNames.add(tableName); - } - - protected static void addIndexName(String indexName) { - mIndexNames.add(indexName); - } - - @Override - public void onCreate(SQLiteDatabase db) { - dropAllTables(db); - } - - @Override - public final void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - try { - onRobustUpgrade(db, oldVersion, newVersion); - } - catch (SQLiteException e) { - // The database has entered an unknown state. Try to recover. - try { - regenerateTables(db); - } - catch (SQLiteException e2) { - dropAndCreateTables(db); - } - } - } - - public abstract void onRobustUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLiteException; - - private void regenerateTables(SQLiteDatabase db) { - dropAllTablesWithPrefix(db, "OLD_"); - - for (String tableName : mTableNames) - db.execSQL("ALTER TABLE " + tableName + " RENAME TO OLD_" - + tableName); - - onCreate(db); - - for (String tableName : mTableNames) - repopulateTable(db, tableName); - - dropAllTablesWithPrefix(db, "OLD_"); - } - - private void repopulateTable(SQLiteDatabase db, String tableName) { - String columns = getTableColumnNames(db, tableName); - StringBuilder sb = new StringBuilder(); - sb.append("INSERT INTO ") - .append(tableName) - .append(" (") - .append(columns) - .append(") SELECT ") - .append(columns) - .append(" FROM OLD_") - .append(tableName); - String sql = sb.toString(); - db.execSQL(sql); - } - - private String getTableColumnNames(SQLiteDatabase db, String tableName) { - StringBuilder sb = new StringBuilder(); - Cursor fields = db.rawQuery("PRAGMA table_info(" + tableName + ")", null); - - while (fields.moveToNext()) { - if (!fields.isFirst()) - sb.append(", "); - - sb.append(fields.getString(1)); - } - - fields.close(); - return sb.toString(); - } - - private void dropAndCreateTables(SQLiteDatabase db) { - dropAllTables(db); - onCreate(db); - } - - private void dropAllTablesWithPrefix(SQLiteDatabase db, String prefix) { - for (String indexName : mIndexNames) - db.execSQL("DROP INDEX IF EXISTS " + prefix + indexName); - - for (String tableName : mTableNames) - db.execSQL("DROP TABLE IF EXISTS " + prefix + tableName); - } - - private void dropAllTables(SQLiteDatabase db) { - dropAllTablesWithPrefix(db, ""); - } -}
--- a/src/com/five_ten_sg/connectbot/util/StringPickerDialog.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import com.five_ten_sg.connectbot.R; - -import android.app.Dialog; -import android.content.Context; -import android.os.Bundle; -import android.text.*; -import android.view.LayoutInflater; -import android.view.View.OnClickListener; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.Button; -import android.widget.GridView; - -/** - * Dialog for choosing accented characters related to a base character. - */ -public class StringPickerDialog extends Dialog - implements OnItemClickListener, OnClickListener { - private View mView; - private Editable mText; - private String []mOptions; - private boolean mInsert; - private LayoutInflater mInflater; - private Button mCancelButton; - - /** - * Creates a new StringPickerDialog that presents the specified - * <code>options</code> for insertion or replacement (depending on - * the sense of <code>insert</code>) into <code>text</code>. - */ - public StringPickerDialog(Context context, View view, - Editable text, String []options, - boolean insert) { - //super(context, com.android.internal.R.style.Theme_Panel); - //Resources res = Resources.getSystem(); - //int id = res.getIdentifier("Theme_Panel", "style", "android"); - //int id = android.R.style.Theme_Panel; - super(context, android.R.style.Theme_Panel); - mView = view; - mText = text; - mOptions = options; - mInsert = insert; - mInflater = LayoutInflater.from(context); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - WindowManager.LayoutParams params = getWindow().getAttributes(); - params.token = mView.getApplicationWindowToken(); - params.type = params.TYPE_APPLICATION_ATTACHED_DIALOG; - params.flags = params.flags | Window.FEATURE_NO_TITLE; - setContentView(R.layout.string_picker); - GridView grid = (GridView) findViewById(R.id.stringPicker); - grid.setAdapter(new OptionsAdapter(getContext())); - grid.setOnItemClickListener(this); - mCancelButton = (Button) findViewById(R.id.cancel); - mCancelButton.setOnClickListener(this); - } - - /** - * Handles clicks on the character buttons. - */ - public void onItemClick(AdapterView parent, View view, int position, long id) { - String result = mOptions[position]; - replaceCharacterAndClose(result); - } - - private void replaceCharacterAndClose(CharSequence replace) { - int selEnd = Selection.getSelectionEnd(mText); - - if (mInsert || selEnd == 0) { - mText.insert(selEnd, replace); - } - else { - mText.replace(selEnd - 1, selEnd, replace); - } - - dismiss(); - } - - /** - * Handles clicks on the Cancel button. - */ - public void onClick(View v) { - if (v == mCancelButton) { - dismiss(); - } - else if (v instanceof Button) { - CharSequence result = ((Button) v).getText(); - replaceCharacterAndClose(result); - } - } - - private class OptionsAdapter extends BaseAdapter { - - public OptionsAdapter(Context context) { - super(); - } - - public View getView(int position, View convertView, ViewGroup parent) { - Button b = (Button) - mInflater.inflate(R.layout.string_picker_button, null); - b.setText(mOptions[position]); - b.setOnClickListener(StringPickerDialog.this); - return b; - } - - public final int getCount() { - return mOptions.length; - } - - public final Object getItem(int position) { - return mOptions[position]; - } - - public final long getItemId(int position) { - return position; - } - } -}
--- a/src/com/five_ten_sg/connectbot/util/TransferThread.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -/* - * TransferThread Class for VX ConnectBot - * Copyright 2012 Martin Matuska - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.five_ten_sg.connectbot.util; - -import java.util.StringTokenizer; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.ProgressDialog; -import android.content.SharedPreferences; -import android.content.res.Resources; -import android.os.Handler; -import android.preference.PreferenceManager; -import android.util.Log; -import android.widget.Toast; - -public class TransferThread extends Thread { - public final static String TAG = "ConnectBot.TransferThread"; - private final Activity activity; - private final SharedPreferences prefs; - private String dialogMessage = null; - private Handler handler = new Handler(); - private TerminalBridge bridge; - private String files, destName, destFolder; - private ProgressDialog progress = null; - private boolean upload; - private Toast progressToast = null; - - public TransferThread(Activity activity, Handler handler) { - this.activity = activity; -// this.handler = handler; - this.prefs = PreferenceManager.getDefaultSharedPreferences(this.activity); - } - - public void setProgressDialogMessage(String message) { - this.dialogMessage = message; - } - - public void download(TerminalBridge bridge, String files, String destName, String destFolder) { - this.bridge = bridge; - this.files = files; - this.destName = destName; - this.destFolder = destFolder; - this.upload = false; - this.configureProgressDialog(); - this.start(); - } - - public void upload(TerminalBridge bridge, String files, String destName, String destFolder) { - this.bridge = bridge; - this.files = files; - this.destName = destName; - this.destFolder = destFolder; - this.upload = true; - this.configureProgressDialog(); - this.start(); - } - - @Override - public void run() { - if (this.activity == null || this.handler == null || this.bridge == null) - return; - - Log.d(TAG, "Requested " + (upload ? "upload" : "download") + " of [" + files + "]"); - Resources res = activity.getResources(); - String fail = ""; - - try { - StringTokenizer fileSet = new StringTokenizer(files, "\n"); - - while (fileSet.hasMoreTokens()) { - String file = fileSet.nextToken(); - final String newMessage = res.getString(upload ? R.string.transfer_uploading_file : R.string.transfer_downloading_file, file); - handler.post(new Runnable() { - public void run() { - if (prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) { - if (progressToast == null) - progressToast = Toast.makeText(activity, newMessage, Toast.LENGTH_LONG); - else - progressToast.setText(newMessage); - - progressToast.show(); - } - else if (progress != null) { - progress.setMessage(newMessage); - } - } - }); - boolean success = (upload ? bridge.uploadFile(file, destName, destFolder, null) : bridge.downloadFile(file, destFolder)); - - if (! success) - fail += " " + file; - } - } - finally { - final String failMessage = (fail.length() == 0 ? null : res.getString(upload ? R.string.transfer_upload_failed : R.string.transfer_download_failed, fail)); - final String sucMessage = (res.getString(upload ? R.string.transfer_upload_complete : R.string.transfer_download_complete)); - handler.post(new Runnable() { - public void run() { - if (progress != null) - progress.dismiss(); - - if (prefs.getBoolean(PreferenceConstants.BACKGROUND_FILE_TRANSFER, true)) { - Toast.makeText(activity, - failMessage != null ? failMessage : sucMessage, - Toast.LENGTH_LONG) - .show(); - } - else if (failMessage != null) { - new AlertDialog.Builder(activity) - .setMessage(failMessage) - .setNegativeButton(android.R.string.ok, null).create().show(); - } - } - }); - } - } - - private void configureProgressDialog() { - if (dialogMessage != null) - progress = fileProgressDialog(activity, this.dialogMessage); - else - progress = null; - } - - private ProgressDialog fileProgressDialog(Activity activity, String message) { - ProgressDialog progress = new ProgressDialog(activity); - progress.setIndeterminate(true); - progress.setMessage(message); - progress.setCancelable(false); - progress.show(); - return progress; - } -} \ No newline at end of file
--- a/src/com/five_ten_sg/connectbot/util/UberColorPickerDialog.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,947 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * 090408 - * Keith Wiley - * kwiley@keithwiley.com - * http://keithwiley.com - * - * UberColorPickerDialog v1.1 - * - * This color picker was implemented as a (significant) extension of the - * ColorPickerDialog class provided in the Android API Demos. You are free - * to drop it unchanged into your own projects or to modify it as you see - * fit. I would appreciate it if this comment block were let intact, - * merely for credit's sake. - * - * Enjoy! - */ - -package com.five_ten_sg.connectbot.util; - -import android.app.Dialog; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorMatrix; -import android.graphics.ComposeShader; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.RadialGradient; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Shader; -import android.graphics.SweepGradient; -import android.graphics.drawable.GradientDrawable; -import android.graphics.drawable.GradientDrawable.Orientation; -import android.os.Bundle; -import android.util.DisplayMetrics; -import android.util.FloatMath; -import android.view.MotionEvent; -import android.view.View; - -/** - * UberColorPickerDialog is a seriously enhanced version of the UberColorPickerDialog - * class provided in the Android API Demos.<p> - * - * NOTE (from Kenny Root): This is a VERY slimmed down version custom for ConnectBot. - * Visit Keith's site for the full version at the URL listed in the author line.<p> - * - * @author Keith Wiley, kwiley@keithwiley.com, http://keithwiley.com - */ -public class UberColorPickerDialog extends Dialog { - private final OnColorChangedListener mListener; - private final int mInitialColor; - - /** - * Callback to the creator of the dialog, informing the creator of a new color and notifying that the dialog is about to dismiss. - */ - public interface OnColorChangedListener { - void colorChanged(int color); - } - - /** - * Ctor - * @param context - * @param listener - * @param initialColor - * @param showTitle If true, a title is shown across the top of the dialog. If false a toast is shown instead. - */ - public UberColorPickerDialog(Context context, - OnColorChangedListener listener, - int initialColor) { - super(context); - mListener = listener; - mInitialColor = initialColor; - } - - /** - * Activity entry point - */ - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - OnColorChangedListener l = new OnColorChangedListener() { - public void colorChanged(int color) { - mListener.colorChanged(color); - dismiss(); - } - }; - DisplayMetrics dm = new DisplayMetrics(); - getWindow().getWindowManager().getDefaultDisplay().getMetrics(dm); - int screenWidth = dm.widthPixels; - int screenHeight = dm.heightPixels; - setTitle("Pick a color (try the trackball)"); - - try { - setContentView(new ColorPickerView(getContext(), l, screenWidth, screenHeight, mInitialColor)); - } - catch (Exception e) { - //There is currently only one kind of ctor exception, that where no methods are enabled. - dismiss(); //This doesn't work! The dialog is still shown (its title at least, the layout is empty from the exception being thrown). <sigh> - } - } - - /** - * ColorPickerView is the meat of this color picker (as opposed to the enclosing class). - * All the heavy lifting is done directly by this View subclass. - * <P> - * You can enable/disable whichever color chooser methods you want by modifying the ENABLED_METHODS switches. They *should* - * do all the work required to properly enable/disable methods without losing track of what goes with what and what maps to what. - * <P> - * If you add a new color chooser method, do a text search for "NEW_METHOD_WORK_NEEDED_HERE". That tag indicates all - * the locations in the code that will have to be amended in order to properly add a new color chooser method. - * I highly recommend adding new methods to the end of the list. If you want to try to reorder the list, you're on your own. - */ - private static class ColorPickerView extends View { - private static int SWATCH_WIDTH = 95; - private static final int SWATCH_HEIGHT = 60; - - private static int PALETTE_POS_X = 0; - private static int PALETTE_POS_Y = SWATCH_HEIGHT; - private static final int PALETTE_DIM = SWATCH_WIDTH * 2; - private static final int PALETTE_RADIUS = PALETTE_DIM / 2; - private static final int PALETTE_CENTER_X = PALETTE_RADIUS; - private static final int PALETTE_CENTER_Y = PALETTE_RADIUS; - - private static final int SLIDER_THICKNESS = 40; - - private static int VIEW_DIM_X = PALETTE_DIM; - private static int VIEW_DIM_Y = SWATCH_HEIGHT; - - //NEW_METHOD_WORK_NEEDED_HERE - private static final int METHOD_HS_V_PALETTE = 0; - - //NEW_METHOD_WORK_NEEDED_HERE - //Add a new entry to the list for each controller in the new method - private static final int TRACKED_NONE = -1; //No object on screen is currently being tracked - private static final int TRACK_SWATCH_OLD = 10; - private static final int TRACK_SWATCH_NEW = 11; - private static final int TRACK_HS_PALETTE = 30; - private static final int TRACK_VER_VALUE_SLIDER = 31; - - private static final int TEXT_SIZE = 12; - private static int[] TEXT_HSV_POS = new int[2]; - private static int[] TEXT_RGB_POS = new int[2]; - private static int[] TEXT_YUV_POS = new int[2]; - private static int[] TEXT_HEX_POS = new int[2]; - - private static final float PI = 3.141592653589793f; - - private int mMethod = METHOD_HS_V_PALETTE; - private int mTracking = TRACKED_NONE; //What object on screen is currently being tracked for movement - - //Zillions of persistant Paint objecs for drawing the View - - private Paint mSwatchOld, mSwatchNew; - - //NEW_METHOD_WORK_NEEDED_HERE - //Add Paints to represent the palettes of the new method's UI controllers - private Paint mOvalHueSat; - - private Bitmap mVerSliderBM; - private Canvas mVerSliderCv; - - private Bitmap[] mHorSlidersBM = new Bitmap[3]; - private Canvas[] mHorSlidersCv = new Canvas[3]; - - private Paint mValDimmer; - - //NEW_METHOD_WORK_NEEDED_HERE - //Add Paints to represent the icon for the new method - private Paint mOvalHueSatSmall; - - private Paint mPosMarker; - private Paint mText; - - private Rect mOldSwatchRect = new Rect(); - private Rect mNewSwatchRect = new Rect(); - private Rect mPaletteRect = new Rect(); - private Rect mVerSliderRect = new Rect(); - - private int[] mSpectrumColorsRev; - private int mOriginalColor = 0; //The color passed in at the beginning, which can be reverted to at any time by tapping the old swatch. - private float[] mHSV = new float[3]; - private int[] mRGB = new int[3]; - private float[] mYUV = new float[3]; - private String mHexStr = ""; - private boolean mHSVenabled = true; //Only true if an HSV method is enabled - private boolean mRGBenabled = true; //Only true if an RGB method is enabled - private boolean mYUVenabled = true; //Only true if a YUV method is enabled - private boolean mHexenabled = true; //Only true if an RGB method is enabled - private int[] mCoord = new int[3]; //For drawing slider/palette markers - private int mFocusedControl = -1; //Which control receives trackball events. - private OnColorChangedListener mListener; - - /** - * Ctor. - * @param c - * @param l - * @param width Used to determine orientation and adjust layout accordingly - * @param height Used to determine orientation and adjust layout accordingly - * @param color The initial color - * @throws Exception - */ - ColorPickerView(Context c, OnColorChangedListener l, int width, int height, int color) - throws Exception { - super(c); - //We need to make the dialog focusable to retrieve trackball events. - setFocusable(true); - mListener = l; - mOriginalColor = color; - Color.colorToHSV(color, mHSV); - updateAllFromHSV(); - - //Setup the layout based on whether this is a portrait or landscape orientation. - if (width <= height) { //Portrait layout - SWATCH_WIDTH = (PALETTE_DIM + SLIDER_THICKNESS) / 2; - PALETTE_POS_X = 0; - PALETTE_POS_Y = TEXT_SIZE * 4 + SWATCH_HEIGHT; - //Set more rects, lots of rects - mOldSwatchRect.set(0, TEXT_SIZE * 4, SWATCH_WIDTH, TEXT_SIZE * 4 + SWATCH_HEIGHT); - mNewSwatchRect.set(SWATCH_WIDTH, TEXT_SIZE * 4, SWATCH_WIDTH * 2, TEXT_SIZE * 4 + SWATCH_HEIGHT); - mPaletteRect.set(0, PALETTE_POS_Y, PALETTE_DIM, PALETTE_POS_Y + PALETTE_DIM); - mVerSliderRect.set(PALETTE_DIM, PALETTE_POS_Y, PALETTE_DIM + SLIDER_THICKNESS, PALETTE_POS_Y + PALETTE_DIM); - TEXT_HSV_POS[0] = 3; - TEXT_HSV_POS[1] = 0; - TEXT_RGB_POS[0] = TEXT_HSV_POS[0] + 50; - TEXT_RGB_POS[1] = TEXT_HSV_POS[1]; - TEXT_YUV_POS[0] = TEXT_HSV_POS[0] + 100; - TEXT_YUV_POS[1] = TEXT_HSV_POS[1]; - TEXT_HEX_POS[0] = TEXT_HSV_POS[0] + 150; - TEXT_HEX_POS[1] = TEXT_HSV_POS[1]; - VIEW_DIM_X = PALETTE_DIM + SLIDER_THICKNESS; - VIEW_DIM_Y = SWATCH_HEIGHT + PALETTE_DIM + TEXT_SIZE * 4; - } - else { //Landscape layout - SWATCH_WIDTH = 110; - PALETTE_POS_X = SWATCH_WIDTH; - PALETTE_POS_Y = 0; - //Set more rects, lots of rects - mOldSwatchRect.set(0, TEXT_SIZE * 7, SWATCH_WIDTH, TEXT_SIZE * 7 + SWATCH_HEIGHT); - mNewSwatchRect.set(0, TEXT_SIZE * 7 + SWATCH_HEIGHT, SWATCH_WIDTH, TEXT_SIZE * 7 + SWATCH_HEIGHT * 2); - mPaletteRect.set(SWATCH_WIDTH, PALETTE_POS_Y, SWATCH_WIDTH + PALETTE_DIM, PALETTE_POS_Y + PALETTE_DIM); - mVerSliderRect.set(SWATCH_WIDTH + PALETTE_DIM, PALETTE_POS_Y, SWATCH_WIDTH + PALETTE_DIM + SLIDER_THICKNESS, PALETTE_POS_Y + PALETTE_DIM); - TEXT_HSV_POS[0] = 3; - TEXT_HSV_POS[1] = 0; - TEXT_RGB_POS[0] = TEXT_HSV_POS[0]; - TEXT_RGB_POS[1] = (int)(TEXT_HSV_POS[1] + TEXT_SIZE * 3.5); - TEXT_YUV_POS[0] = TEXT_HSV_POS[0] + 50; - TEXT_YUV_POS[1] = (int)(TEXT_HSV_POS[1] + TEXT_SIZE * 3.5); - TEXT_HEX_POS[0] = TEXT_HSV_POS[0] + 50; - TEXT_HEX_POS[1] = TEXT_HSV_POS[1]; - VIEW_DIM_X = PALETTE_POS_X + PALETTE_DIM + SLIDER_THICKNESS; - VIEW_DIM_Y = Math.max(mNewSwatchRect.bottom, PALETTE_DIM); - } - - //Rainbows make everybody happy! - mSpectrumColorsRev = new int[] { - 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF, - 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000, - }; - //Setup all the Paint and Shader objects. There are lots of them! - //NEW_METHOD_WORK_NEEDED_HERE - //Add Paints to represent the palettes of the new method's UI controllers - mSwatchOld = new Paint(Paint.ANTI_ALIAS_FLAG); - mSwatchOld.setStyle(Paint.Style.FILL); - mSwatchOld.setColor(Color.HSVToColor(mHSV)); - mSwatchNew = new Paint(Paint.ANTI_ALIAS_FLAG); - mSwatchNew.setStyle(Paint.Style.FILL); - mSwatchNew.setColor(Color.HSVToColor(mHSV)); - Shader shaderA = new SweepGradient(0, 0, mSpectrumColorsRev, null); - Shader shaderB = new RadialGradient(0, 0, PALETTE_CENTER_X, 0xFFFFFFFF, 0xFF000000, Shader.TileMode.CLAMP); - Shader shader = new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SCREEN); - mOvalHueSat = new Paint(Paint.ANTI_ALIAS_FLAG); - mOvalHueSat.setShader(shader); - mOvalHueSat.setStyle(Paint.Style.FILL); - mOvalHueSat.setDither(true); - mVerSliderBM = Bitmap.createBitmap(SLIDER_THICKNESS, PALETTE_DIM, Bitmap.Config.RGB_565); - mVerSliderCv = new Canvas(mVerSliderBM); - - for (int i = 0; i < 3; i++) { - mHorSlidersBM[i] = Bitmap.createBitmap(PALETTE_DIM, SLIDER_THICKNESS, Bitmap.Config.RGB_565); - mHorSlidersCv[i] = new Canvas(mHorSlidersBM[i]); - } - - mValDimmer = new Paint(Paint.ANTI_ALIAS_FLAG); - mValDimmer.setStyle(Paint.Style.FILL); - mValDimmer.setDither(true); - mValDimmer.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); - //Whew, we're done making the big Paints and Shaders for the swatches, palettes, and sliders. - //Now we need to make the Paints and Shaders that will draw the little method icons in the method selector list. - //NEW_METHOD_WORK_NEEDED_HERE - //Add Paints to represent the icon for the new method - shaderA = new SweepGradient(0, 0, mSpectrumColorsRev, null); - shaderB = new RadialGradient(0, 0, PALETTE_DIM / 2, 0xFFFFFFFF, 0xFF000000, Shader.TileMode.CLAMP); - shader = new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SCREEN); - mOvalHueSatSmall = new Paint(Paint.ANTI_ALIAS_FLAG); - mOvalHueSatSmall.setShader(shader); - mOvalHueSatSmall.setStyle(Paint.Style.FILL); - //Make a simple stroking Paint for drawing markers and borders and stuff like that. - mPosMarker = new Paint(Paint.ANTI_ALIAS_FLAG); - mPosMarker.setStyle(Paint.Style.STROKE); - mPosMarker.setStrokeWidth(2); - //Make a basic text Paint. - mText = new Paint(Paint.ANTI_ALIAS_FLAG); - mText.setTextSize(TEXT_SIZE); - mText.setColor(Color.WHITE); - //Kickstart - initUI(); - } - - /** - * Draw the entire view (the entire dialog). - */ - @Override - protected void onDraw(Canvas canvas) { - //Draw the old and new swatches - drawSwatches(canvas); - //Write the text - writeColorParams(canvas); - - //Draw the palette and sliders (the UI) - if (mMethod == METHOD_HS_V_PALETTE) - drawHSV1Palette(canvas); - } - - /** - * Draw the old and new swatches. - * @param canvas - */ - private void drawSwatches(Canvas canvas) { - float[] hsv = new float[3]; - mText.setTextSize(16); - //Draw the original swatch - canvas.drawRect(mOldSwatchRect, mSwatchOld); - Color.colorToHSV(mOriginalColor, hsv); - - //if (UberColorPickerDialog.isGray(mColor)) //Don't need this right here, but imp't to note - // hsv[1] = 0; - if (hsv[2] > .5) - mText.setColor(Color.BLACK); - - canvas.drawText("Revert", mOldSwatchRect.left + SWATCH_WIDTH / 2 - mText.measureText("Revert") / 2, mOldSwatchRect.top + 16, mText); - mText.setColor(Color.WHITE); - //Draw the new swatch - canvas.drawRect(mNewSwatchRect, mSwatchNew); - - if (mHSV[2] > .5) - mText.setColor(Color.BLACK); - - canvas.drawText("Accept", mNewSwatchRect.left + SWATCH_WIDTH / 2 - mText.measureText("Accept") / 2, mNewSwatchRect.top + 16, mText); - mText.setColor(Color.WHITE); - mText.setTextSize(TEXT_SIZE); - } - - /** - * Write the color parametes (HSV, RGB, YUV, Hex, etc.). - * @param canvas - */ - private void writeColorParams(Canvas canvas) { - if (mHSVenabled) { - canvas.drawText("H: " + Integer.toString((int)(mHSV[0] / 360.0f * 255)), TEXT_HSV_POS[0], TEXT_HSV_POS[1] + TEXT_SIZE, mText); - canvas.drawText("S: " + Integer.toString((int)(mHSV[1] * 255)), TEXT_HSV_POS[0], TEXT_HSV_POS[1] + TEXT_SIZE * 2, mText); - canvas.drawText("V: " + Integer.toString((int)(mHSV[2] * 255)), TEXT_HSV_POS[0], TEXT_HSV_POS[1] + TEXT_SIZE * 3, mText); - } - - if (mRGBenabled) { - canvas.drawText("R: " + mRGB[0], TEXT_RGB_POS[0], TEXT_RGB_POS[1] + TEXT_SIZE, mText); - canvas.drawText("G: " + mRGB[1], TEXT_RGB_POS[0], TEXT_RGB_POS[1] + TEXT_SIZE * 2, mText); - canvas.drawText("B: " + mRGB[2], TEXT_RGB_POS[0], TEXT_RGB_POS[1] + TEXT_SIZE * 3, mText); - } - - if (mYUVenabled) { - canvas.drawText("Y: " + Integer.toString((int)(mYUV[0] * 255)), TEXT_YUV_POS[0], TEXT_YUV_POS[1] + TEXT_SIZE, mText); - canvas.drawText("U: " + Integer.toString((int)((mYUV[1] + .5f) * 255)), TEXT_YUV_POS[0], TEXT_YUV_POS[1] + TEXT_SIZE * 2, mText); - canvas.drawText("V: " + Integer.toString((int)((mYUV[2] + .5f) * 255)), TEXT_YUV_POS[0], TEXT_YUV_POS[1] + TEXT_SIZE * 3, mText); - } - - if (mHexenabled) - canvas.drawText("#" + mHexStr, TEXT_HEX_POS[0], TEXT_HEX_POS[1] + TEXT_SIZE, mText); - } - - /** - * Place a small circle on the 2D palette to indicate the current values. - * @param canvas - * @param markerPosX - * @param markerPosY - */ - private void mark2DPalette(Canvas canvas, int markerPosX, int markerPosY) { - mPosMarker.setColor(Color.BLACK); - canvas.drawOval(new RectF(markerPosX - 5, markerPosY - 5, markerPosX + 5, markerPosY + 5), mPosMarker); - mPosMarker.setColor(Color.WHITE); - canvas.drawOval(new RectF(markerPosX - 3, markerPosY - 3, markerPosX + 3, markerPosY + 3), mPosMarker); - } - - /** - * Draw a line across the slider to indicate its current value. - * @param canvas - * @param markerPos - */ - private void markVerSlider(Canvas canvas, int markerPos) { - mPosMarker.setColor(Color.BLACK); - canvas.drawRect(new Rect(0, markerPos - 2, SLIDER_THICKNESS, markerPos + 3), mPosMarker); - mPosMarker.setColor(Color.WHITE); - canvas.drawRect(new Rect(0, markerPos, SLIDER_THICKNESS, markerPos + 1), mPosMarker); - } - - /** - * Frame the slider to indicate that it has trackball focus. - * @param canvas - */ - private void hilightFocusedVerSlider(Canvas canvas) { - mPosMarker.setColor(Color.WHITE); - canvas.drawRect(new Rect(0, 0, SLIDER_THICKNESS, PALETTE_DIM), mPosMarker); - mPosMarker.setColor(Color.BLACK); - canvas.drawRect(new Rect(2, 2, SLIDER_THICKNESS - 2, PALETTE_DIM - 2), mPosMarker); - } - - /** - * Frame the 2D palette to indicate that it has trackball focus. - * @param canvas - */ - private void hilightFocusedOvalPalette(Canvas canvas) { - mPosMarker.setColor(Color.WHITE); - canvas.drawOval(new RectF(-PALETTE_RADIUS, -PALETTE_RADIUS, PALETTE_RADIUS, PALETTE_RADIUS), mPosMarker); - mPosMarker.setColor(Color.BLACK); - canvas.drawOval(new RectF(-PALETTE_RADIUS + 2, -PALETTE_RADIUS + 2, PALETTE_RADIUS - 2, PALETTE_RADIUS - 2), mPosMarker); - } - - //NEW_METHOD_WORK_NEEDED_HERE - //To add a new method, replicate the basic draw functions here. Use the 2D palette or 1D sliders as templates for the new method. - /** - * Draw the UI for HSV with angular H and radial S combined in 2D and a 1D V slider. - * @param canvas - */ - private void drawHSV1Palette(Canvas canvas) { - canvas.save(); - canvas.translate(PALETTE_POS_X, PALETTE_POS_Y); - //Draw the 2D palette - canvas.translate(PALETTE_CENTER_X, PALETTE_CENTER_Y); - canvas.drawOval(new RectF(-PALETTE_RADIUS, -PALETTE_RADIUS, PALETTE_RADIUS, PALETTE_RADIUS), mOvalHueSat); - canvas.drawOval(new RectF(-PALETTE_RADIUS, -PALETTE_RADIUS, PALETTE_RADIUS, PALETTE_RADIUS), mValDimmer); - - if (mFocusedControl == 0) - hilightFocusedOvalPalette(canvas); - - mark2DPalette(canvas, mCoord[0], mCoord[1]); - canvas.translate(-PALETTE_CENTER_X, -PALETTE_CENTER_Y); - //Draw the 1D slider - canvas.translate(PALETTE_DIM, 0); - canvas.drawBitmap(mVerSliderBM, 0, 0, null); - - if (mFocusedControl == 1) - hilightFocusedVerSlider(canvas); - - markVerSlider(canvas, mCoord[2]); - canvas.restore(); - } - - /** - * Initialize the current color chooser's UI (set its color parameters and set its palette and slider values accordingly). - */ - private void initUI() { - initHSV1Palette(); - //Focus on the first controller (arbitrary). - mFocusedControl = 0; - } - - //NEW_METHOD_WORK_NEEDED_HERE - //To add a new method, replicate and extend the last init function shown below - /** - * Initialize a color chooser. - */ - private void initHSV1Palette() { - setOvalValDimmer(); - setVerValSlider(); - float angle = 2 * PI - mHSV[0] / (180 / 3.1415927f); - float radius = mHSV[1] * PALETTE_RADIUS; - mCoord[0] = (int)(FloatMath.cos(angle) * radius); - mCoord[1] = (int)(FloatMath.sin(angle) * radius); - mCoord[2] = PALETTE_DIM - (int)(mHSV[2] * PALETTE_DIM); - } - - //NEW_METHOD_WORK_NEEDED_HERE - //To add a new method, replicate and extend the set functions below, one per UI controller in the new method - /** - * Adjust a Paint which, when painted, dims its underlying object to show the effects of varying value (brightness). - */ - private void setOvalValDimmer() { - float[] hsv = new float[3]; - hsv[0] = mHSV[0]; - hsv[1] = 0; - hsv[2] = mHSV[2]; - int gray = Color.HSVToColor(hsv); - mValDimmer.setColor(gray); - } - - /** - * Create a linear gradient shader to show variations in value. - */ - private void setVerValSlider() { - float[] hsv = new float[3]; - hsv[0] = mHSV[0]; - hsv[1] = mHSV[1]; - hsv[2] = 1; - int col = Color.HSVToColor(hsv); - int colors[] = new int[2]; - colors[0] = col; - colors[1] = 0xFF000000; - GradientDrawable gradDraw = new GradientDrawable(Orientation.TOP_BOTTOM, colors); - gradDraw.setDither(true); - gradDraw.setLevel(10000); - gradDraw.setBounds(0, 0, SLIDER_THICKNESS, PALETTE_DIM); - gradDraw.draw(mVerSliderCv); - } - - /** - * Report the correct tightly bounded dimensions of the view. - */ - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(VIEW_DIM_X, VIEW_DIM_Y); - } - - /** - * Wrap Math.round(). I'm not a Java expert. Is this the only way to avoid writing "(int)Math.round" everywhere? - * @param x - * @return - */ - private int round(double x) { - return (int)Math.round(x); - } - - /** - * Limit a value to the range [0,1]. - * @param n - * @return - */ - private float pinToUnit(float n) { - if (n < 0) { - n = 0; - } - else if (n > 1) { - n = 1; - } - - return n; - } - - /** - * Limit a value to the range [0,max]. - * @param n - * @param max - * @return - */ - private float pin(float n, float max) { - if (n < 0) { - n = 0; - } - else if (n > max) { - n = max; - } - - return n; - } - - /** - * Limit a value to the range [min,max]. - * @param n - * @param min - * @param max - * @return - */ - private float pin(float n, float min, float max) { - if (n < min) { - n = min; - } - else if (n > max) { - n = max; - } - - return n; - } - - /** - * No clue what this does (some sort of average/mean I presume). It came with the original UberColorPickerDialog - * in the API Demos and wasn't documented. I don't feel like spending any time figuring it out, I haven't looked at it at all. - * @param s - * @param d - * @param p - * @return - */ - private int ave(int s, int d, float p) { - return s + round(p * (d - s)); - } - - /** - * Came with the original UberColorPickerDialog in the API Demos, wasn't documented. I believe it takes an array of - * colors and a value in the range [0,1] and interpolates a resulting color in a seemingly predictable manner. - * I haven't looked at it at all. - * @param colors - * @param unit - * @return - */ - private int interpColor(int colors[], float unit) { - if (unit <= 0) { - return colors[0]; - } - - if (unit >= 1) { - return colors[colors.length - 1]; - } - - float p = unit * (colors.length - 1); - int i = (int)p; - p -= i; - // now p is just the fractional part [0...1) and i is the index - int c0 = colors[i]; - int c1 = colors[i + 1]; - int a = ave(Color.alpha(c0), Color.alpha(c1), p); - int r = ave(Color.red(c0), Color.red(c1), p); - int g = ave(Color.green(c0), Color.green(c1), p); - int b = ave(Color.blue(c0), Color.blue(c1), p); - return Color.argb(a, r, g, b); - } - - /** - * A standard point-in-rect routine. - * @param x - * @param y - * @param r - * @return true if point x,y is in rect r - */ - public boolean ptInRect(int x, int y, Rect r) { - return x > r.left && x < r.right && y > r.top && y < r.bottom; - } - - /** - * Process trackball events. Used mainly for fine-tuned color adjustment, or alternatively to switch between slider controls. - */ - @Override - public boolean dispatchTrackballEvent(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - //A longer event history implies faster trackball movement. - //Use it to infer a larger jump and therefore faster palette/slider adjustment. - int jump = event.getHistorySize() + 1; - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: { - } - break; - - case MotionEvent.ACTION_MOVE: { - //NEW_METHOD_WORK_NEEDED_HERE - //To add a new method, replicate and extend the appropriate entry in this list, - //depending on whether you use 1D or 2D controllers - switch (mMethod) { - case METHOD_HS_V_PALETTE: - if (mFocusedControl == 0) { - changeHSPalette(x, y, jump); - } - else if (mFocusedControl == 1) { - if (y < 0) - changeSlider(mFocusedControl, true, jump); - else if (y > 0) - changeSlider(mFocusedControl, false, jump); - } - - break; - } - } - break; - - case MotionEvent.ACTION_UP: { - } - break; - } - - return true; - } - - //NEW_METHOD_WORK_NEEDED_HERE - //To add a new method, replicate and extend the appropriate functions below, - //one per UI controller in the new method - /** - * Effect a trackball change to a 2D palette. - * @param x -1: negative x change, 0: no x change, +1: positive x change. - * @param y -1: negative y change, 0, no y change, +1: positive y change. - * @param jump the amount by which to change. - */ - private void changeHSPalette(float x, float y, int jump) { - int x2 = 0, y2 = 0; - - if (x < 0) - x2 = -jump; - else if (x > 0) - x2 = jump; - - if (y < 0) - y2 = -jump; - else if (y > 0) - y2 = jump; - - mCoord[0] += x2; - mCoord[1] += y2; - - if (mCoord[0] < -PALETTE_RADIUS) - mCoord[0] = -PALETTE_RADIUS; - else if (mCoord[0] > PALETTE_RADIUS) - mCoord[0] = PALETTE_RADIUS; - - if (mCoord[1] < -PALETTE_RADIUS) - mCoord[1] = -PALETTE_RADIUS; - else if (mCoord[1] > PALETTE_RADIUS) - mCoord[1] = PALETTE_RADIUS; - - float radius = FloatMath.sqrt(mCoord[0] * mCoord[0] + mCoord[1] * mCoord[1]); - - if (radius > PALETTE_RADIUS) - radius = PALETTE_RADIUS; - - float angle = (float)Math.atan2(mCoord[1], mCoord[0]); - // need to turn angle [-PI ... PI] into unit [0....1] - float unit = angle / (2 * PI); - - if (unit < 0) { - unit += 1; - } - - mCoord[0] = round(FloatMath.cos(angle) * radius); - mCoord[1] = round(FloatMath.sin(angle) * radius); - int c = interpColor(mSpectrumColorsRev, unit); - float[] hsv = new float[3]; - Color.colorToHSV(c, hsv); - mHSV[0] = hsv[0]; - mHSV[1] = radius / PALETTE_RADIUS; - updateAllFromHSV(); - mSwatchNew.setColor(Color.HSVToColor(mHSV)); - setVerValSlider(); - invalidate(); - } - - /** - * Effect a trackball change to a 1D slider. - * @param slider id of the slider to be effected - * @param increase true if the change is an increase, false if a decrease - * @param jump the amount by which to change in units of the range [0,255] - */ - private void changeSlider(int slider, boolean increase, int jump) { - //NEW_METHOD_WORK_NEEDED_HERE - //It is only necessary to add an entry here for a new method if the new method uses a 1D slider. - //Note, some sliders are horizontal and others are vertical. - //They differ a bit, especially in a sign flip on the vertical axis. - if (mMethod == METHOD_HS_V_PALETTE) { - //slider *must* equal 1 - mHSV[2] += (increase ? jump : -jump) / 256.0f; - mHSV[2] = pinToUnit(mHSV[2]); - updateAllFromHSV(); - mCoord[2] = PALETTE_DIM - (int)(mHSV[2] * PALETTE_DIM); - mSwatchNew.setColor(Color.HSVToColor(mHSV)); - setOvalValDimmer(); - invalidate(); - } - } - - /** - * Keep all colorspace representations in sync. - */ - private void updateRGBfromHSV() { - int color = Color.HSVToColor(mHSV); - mRGB[0] = Color.red(color); - mRGB[1] = Color.green(color); - mRGB[2] = Color.blue(color); - } - - /** - * Keep all colorspace representations in sync. - */ - private void updateYUVfromRGB() { - float r = mRGB[0] / 255.0f; - float g = mRGB[1] / 255.0f; - float b = mRGB[2] / 255.0f; - ColorMatrix cm = new ColorMatrix(); - cm.setRGB2YUV(); - final float[] a = cm.getArray(); - mYUV[0] = a[0] * r + a[1] * g + a[2] * b; - mYUV[0] = pinToUnit(mYUV[0]); - mYUV[1] = a[5] * r + a[6] * g + a[7] * b; - mYUV[1] = pin(mYUV[1], -.5f, .5f); - mYUV[2] = a[10] * r + a[11] * g + a[12] * b; - mYUV[2] = pin(mYUV[2], -.5f, .5f); - } - - /** - * Keep all colorspace representations in sync. - */ - private void updateHexFromHSV() { - //For now, assume 100% opacity - mHexStr = Integer.toHexString(Color.HSVToColor(mHSV)).toUpperCase(); - mHexStr = mHexStr.substring(2, mHexStr.length()); - } - - /** - * Keep all colorspace representations in sync. - */ - private void updateAllFromHSV() { - //Update mRGB - if (mRGBenabled || mYUVenabled) - updateRGBfromHSV(); - - //Update mYUV - if (mYUVenabled) - updateYUVfromRGB(); - - //Update mHexStr - if (mRGBenabled) - updateHexFromHSV(); - } - - /** - * Process touch events: down, move, and up - */ - @Override - public boolean onTouchEvent(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - //Generate coordinates which are palette=local with the origin at the upper left of the main 2D palette - int y2 = (int)(pin(round(y - PALETTE_POS_Y), PALETTE_DIM)); - //Generate coordinates which are palette-local with the origin at the center of the main 2D palette - float circlePinnedX = x - PALETTE_POS_X - PALETTE_CENTER_X; - float circlePinnedY = y - PALETTE_POS_Y - PALETTE_CENTER_Y; - //Is the event in a swatch? - boolean inSwatchOld = ptInRect(round(x), round(y), mOldSwatchRect); - boolean inSwatchNew = ptInRect(round(x), round(y), mNewSwatchRect); - //Get the event's distance from the center of the main 2D palette - float radius = FloatMath.sqrt(circlePinnedX * circlePinnedX + circlePinnedY * circlePinnedY); - //Is the event in a circle-pinned 2D palette? - boolean inOvalPalette = radius <= PALETTE_RADIUS; - - //Pin the radius - if (radius > PALETTE_RADIUS) - radius = PALETTE_RADIUS; - - //Is the event in a vertical slider to the right of the main 2D palette - boolean inVerSlider = ptInRect(round(x), round(y), mVerSliderRect); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - mTracking = TRACKED_NONE; - - if (inSwatchOld) - mTracking = TRACK_SWATCH_OLD; - else if (inSwatchNew) - mTracking = TRACK_SWATCH_NEW; - //NEW_METHOD_WORK_NEEDED_HERE - //To add a new method, replicate and extend the last entry in this list - else if (mMethod == METHOD_HS_V_PALETTE) { - if (inOvalPalette) { - mTracking = TRACK_HS_PALETTE; - mFocusedControl = 0; - } - else if (inVerSlider) { - mTracking = TRACK_VER_VALUE_SLIDER; - mFocusedControl = 1; - } - } - - case MotionEvent.ACTION_MOVE: - - //NEW_METHOD_WORK_NEEDED_HERE - //To add a new method, replicate and extend the entries in this list, - //one per UI controller the new method requires. - if (mTracking == TRACK_HS_PALETTE) { - float angle = (float)java.lang.Math.atan2(circlePinnedY, circlePinnedX); - // need to turn angle [-PI ... PI] into unit [0....1] - float unit = angle / (2 * PI); - - if (unit < 0) { - unit += 1; - } - - mCoord[0] = round(FloatMath.cos(angle) * radius); - mCoord[1] = round(FloatMath.sin(angle) * radius); - int c = interpColor(mSpectrumColorsRev, unit); - float[] hsv = new float[3]; - Color.colorToHSV(c, hsv); - mHSV[0] = hsv[0]; - mHSV[1] = radius / PALETTE_RADIUS; - updateAllFromHSV(); - mSwatchNew.setColor(Color.HSVToColor(mHSV)); - setVerValSlider(); - invalidate(); - } - else if (mTracking == TRACK_VER_VALUE_SLIDER) { - if (mCoord[2] != y2) { - mCoord[2] = y2; - float value = 1.0f - (float)y2 / (float)PALETTE_DIM; - mHSV[2] = value; - updateAllFromHSV(); - mSwatchNew.setColor(Color.HSVToColor(mHSV)); - setOvalValDimmer(); - invalidate(); - } - } - - break; - - case MotionEvent.ACTION_UP: - - //NEW_METHOD_WORK_NEEDED_HERE - //To add a new method, replicate and extend the last entry in this list. - if (mTracking == TRACK_SWATCH_OLD && inSwatchOld) { - Color.colorToHSV(mOriginalColor, mHSV); - mSwatchNew.setColor(mOriginalColor); - initUI(); - invalidate(); - } - else if (mTracking == TRACK_SWATCH_NEW && inSwatchNew) { - mListener.colorChanged(mSwatchNew.getColor()); - invalidate(); - } - - mTracking = TRACKED_NONE; - break; - } - - return true; - } - } -}
--- a/src/com/five_ten_sg/connectbot/util/VolumePreference.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import android.content.Context; -import android.preference.DialogPreference; -import android.util.AttributeSet; -import android.view.View; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; - -/** - * @author kenny - * - */ -public class VolumePreference extends DialogPreference implements OnSeekBarChangeListener { - /** - * @param context - * @param attrs - */ - public VolumePreference(Context context, AttributeSet attrs) { - super(context, attrs); - setupLayout(context, attrs); - } - - public VolumePreference(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - setupLayout(context, attrs); - } - - private void setupLayout(Context context, AttributeSet attrs) { - setPersistent(true); - } - - @Override - protected View onCreateDialogView() { - SeekBar sb = new SeekBar(getContext()); - sb.setMax(100); - sb.setProgress((int)(getPersistedFloat( - PreferenceConstants.DEFAULT_BELL_VOLUME) * 100)); - sb.setPadding(10, 10, 10, 10); - sb.setOnSeekBarChangeListener(this); - return sb; - } - - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - persistFloat(progress / 100f); - } - - public void onStartTrackingTouch(SeekBar seekBar) { } - - public void onStopTrackingTouch(SeekBar seekBar) { } -}
--- a/src/com/five_ten_sg/connectbot/util/XmlBuilder.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.five_ten_sg.connectbot.util; - -import ch.ethz.ssh2.crypto.Base64; - -/** - * @author Kenny Root - * - */ -public class XmlBuilder { - private StringBuilder sb; - - public XmlBuilder() { - sb = new StringBuilder(); - } - - public XmlBuilder append(String data) { - sb.append(data); - return this; - } - - public XmlBuilder append(String field, Object data) { - if (data == null) { - sb.append(String.format("<%s/>", field)); - } - else if (data instanceof String) { - String input = (String) data; - boolean binary = false; - - for (byte b : input.getBytes()) { - if (b < 0x20 || b > 0x7e) { - binary = true; - break; - } - } - - sb.append(String.format("<%s>%s</%s>", field, - binary ? new String(Base64.encode(input.getBytes())) : input, field)); - } - else if (data instanceof Integer) { - sb.append(String.format("<%s>%d</%s>", field, data, field)); - } - else if (data instanceof Long) { - sb.append(String.format("<%s>%d</%s>", field, data, field)); - } - else if (data instanceof byte[]) { - sb.append(String.format("<%s>%s</%s>", field, new String(Base64.encode((byte[]) data)), field)); - } - else if (data instanceof Boolean) { - sb.append(String.format("<%s>%s</%s>", field, data, field)); - } - - return this; - } - - @Override - public String toString() { - return sb.toString(); - } -}
--- a/src/com/google/ase/Exec.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.ase; - -import java.io.FileDescriptor; - -/** - * Tools for executing commands. - */ -public class Exec { - /** - * @param cmd - * The command to execute - * @param arg0 - * The first argument to the command, may be null - * @param arg1 - * the second argument to the command, may be null - * @return the file descriptor of the started process. - * - */ - public static FileDescriptor createSubprocess(String cmd, String arg0, String arg1) { - return createSubprocess(cmd, arg0, arg1, null); - } - - /** - * @param cmd - * The command to execute - * @param arg0 - * The first argument to the command, may be null - * @param arg1 - * the second argument to the command, may be null - * @param processId - * A one-element array to which the process ID of the started process will be written. - * @return the file descriptor of the started process. - * - */ - public static native FileDescriptor createSubprocess(String cmd, String arg0, String arg1, - int[] processId); - - public static native void setPtyWindowSize(FileDescriptor fd, int row, int col, int xpixel, - int ypixel); - - /** - * Causes the calling thread to wait for the process associated with the receiver to finish - * executing. - * - * @return The exit value of the Process being waited on - * - */ - public static native int waitFor(int processId); - - static { - System.loadLibrary("com_google_ase_Exec"); - } -}
--- a/src/com/jcraft/jzlib/Adler32.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final public class Adler32 implements Checksum { - - // largest prime smaller than 65536 - static final private int BASE=65521; - // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 - static final private int NMAX=5552; - - private long s1=1L; - private long s2=0L; - - public void reset(long init){ - s1=init&0xffff; - s2=(init>>16)&0xffff; - } - - public void reset(){ - s1=1L; - s2=0L; - } - - public long getValue(){ - return ((s2<<16)|s1); - } - - public void update(byte[] buf, int index, int len){ - - if(len==1){ - s1+=buf[index++]&0xff; s2+=s1; - s1%=BASE; - s2%=BASE; - return; - } - - int len1 = len/NMAX; - int len2 = len%NMAX; - while(len1-->0) { - int k=NMAX; - len-=k; - while(k-->0){ - s1+=buf[index++]&0xff; s2+=s1; - } - s1%=BASE; - s2%=BASE; - } - - int k=len2; - len-=k; - while(k-->0){ - s1+=buf[index++]&0xff; s2+=s1; - } - s1%=BASE; - s2%=BASE; - } - - public Adler32 copy(){ - Adler32 foo = new Adler32(); - foo.s1 = this.s1; - foo.s2 = this.s2; - return foo; - } - - // The following logic has come from zlib.1.2. - static long combine(long adler1, long adler2, long len2){ - long BASEL = (long)BASE; - long sum1; - long sum2; - long rem; // unsigned int - - rem = len2 % BASEL; - sum1 = adler1 & 0xffffL; - sum2 = rem * sum1; - sum2 %= BASEL; // MOD(sum2); - sum1 += (adler2 & 0xffffL) + BASEL - 1; - sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem; - if (sum1 >= BASEL) sum1 -= BASEL; - if (sum1 >= BASEL) sum1 -= BASEL; - if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1); - if (sum2 >= BASEL) sum2 -= BASEL; - return sum1 | (sum2 << 16); - } - -/* - private java.util.zip.Adler32 adler=new java.util.zip.Adler32(); - public void update(byte[] buf, int index, int len){ - if(buf==null) {adler.reset();} - else{adler.update(buf, index, len);} - } - public void reset(){ - adler.reset(); - } - public void reset(long init){ - if(init==1L){ - adler.reset(); - } - else{ - System.err.println("unsupported operation"); - } - } - public long getValue(){ - return adler.getValue(); - } -*/ -}
--- a/src/com/jcraft/jzlib/CRC32.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final public class CRC32 implements Checksum { - - /* - * The following logic has come from RFC1952. - */ - private int v = 0; - private static int[] crc_table = null; - static { - crc_table = new int[256]; - for (int n = 0; n < 256; n++) { - int c = n; - for (int k = 8; --k >= 0; ) { - if ((c & 1) != 0) - c = 0xedb88320 ^ (c >>> 1); - else - c = c >>> 1; - } - crc_table[n] = c; - } - } - - public void update (byte[] buf, int index, int len) { - int c = ~v; - while (--len >= 0) - c = crc_table[(c^buf[index++])&0xff]^(c >>> 8); - v = ~c; - } - - public void reset(){ - v = 0; - } - - public void reset(long vv){ - v = (int)(vv&0xffffffffL); - } - - public long getValue(){ - return (long)(v&0xffffffffL); - } - - // The following logic has come from zlib.1.2. - private static final int GF2_DIM = 32; - static long combine(long crc1, long crc2, long len2){ - long row; - long[] even = new long[GF2_DIM]; - long[] odd = new long[GF2_DIM]; - - // degenerate case (also disallow negative lengths) - if (len2 <= 0) - return crc1; - - // put operator for one zero bit in odd - odd[0] = 0xedb88320L; // CRC-32 polynomial - row = 1; - for (int n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - // put operator for two zero bits in even - gf2_matrix_square(even, odd); - - // put operator for four zero bits in odd - gf2_matrix_square(odd, even); - - // apply len2 zeros to crc1 (first square will put the operator for one - // zero byte, eight zero bits, in even) - do { - // apply zeros operator for this bit of len2 - gf2_matrix_square(even, odd); - if ((len2 & 1)!=0) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - // if no more bits set, then done - if (len2 == 0) - break; - - // another iteration of the loop with odd and even swapped - gf2_matrix_square(odd, even); - if ((len2 & 1)!=0) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - // if no more bits set, then done - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; - } - - private static long gf2_matrix_times(long[] mat, long vec){ - long sum = 0; - int index = 0; - while (vec!=0) { - if ((vec & 1)!=0) - sum ^= mat[index]; - vec >>= 1; - index++; - } - return sum; - } - - static final void gf2_matrix_square(long[] square, long[] mat) { - for (int n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); - } - - /* - private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32(); - - public void update(byte[] buf, int index, int len){ - if(buf==null) {crc32.reset();} - else{crc32.update(buf, index, len);} - } - public void reset(){ - crc32.reset(); - } - public void reset(long init){ - if(init==0L){ - crc32.reset(); - } - else{ - System.err.println("unsupported operation"); - } - } - public long getValue(){ - return crc32.getValue(); - } -*/ - public CRC32 copy(){ - CRC32 foo = new CRC32(); - foo.v = this.v; - return foo; - } - - public static int[] getCRC32Table(){ - int[] tmp = new int[crc_table.length]; - System.arraycopy(crc_table, 0, tmp, 0, tmp.length); - return tmp; - } -}
--- a/src/com/jcraft/jzlib/Checksum.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -interface Checksum { - void update(byte[] buf, int index, int len); - void reset(); - void reset(long init); - long getValue(); - Checksum copy(); -}
--- a/src/com/jcraft/jzlib/Deflate.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1757 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -public -final class Deflate implements Cloneable { - - static final private int MAX_MEM_LEVEL=9; - - static final private int Z_DEFAULT_COMPRESSION=-1; - - static final private int MAX_WBITS=15; // 32K LZ77 window - static final private int DEF_MEM_LEVEL=8; - - static class Config{ - int good_length; // reduce lazy search above this match length - int max_lazy; // do not perform lazy search above this match length - int nice_length; // quit search above this match length - int max_chain; - int func; - Config(int good_length, int max_lazy, - int nice_length, int max_chain, int func){ - this.good_length=good_length; - this.max_lazy=max_lazy; - this.nice_length=nice_length; - this.max_chain=max_chain; - this.func=func; - } - } - - static final private int STORED=0; - static final private int FAST=1; - static final private int SLOW=2; - static final private Config[] config_table; - static{ - config_table=new Config[10]; - // good lazy nice chain - config_table[0]=new Config(0, 0, 0, 0, STORED); - config_table[1]=new Config(4, 4, 8, 4, FAST); - config_table[2]=new Config(4, 5, 16, 8, FAST); - config_table[3]=new Config(4, 6, 32, 32, FAST); - - config_table[4]=new Config(4, 4, 16, 16, SLOW); - config_table[5]=new Config(8, 16, 32, 32, SLOW); - config_table[6]=new Config(8, 16, 128, 128, SLOW); - config_table[7]=new Config(8, 32, 128, 256, SLOW); - config_table[8]=new Config(32, 128, 258, 1024, SLOW); - config_table[9]=new Config(32, 258, 258, 4096, SLOW); - } - - static final private String[] z_errmsg = { - "need dictionary", // Z_NEED_DICT 2 - "stream end", // Z_STREAM_END 1 - "", // Z_OK 0 - "file error", // Z_ERRNO (-1) - "stream error", // Z_STREAM_ERROR (-2) - "data error", // Z_DATA_ERROR (-3) - "insufficient memory", // Z_MEM_ERROR (-4) - "buffer error", // Z_BUF_ERROR (-5) - "incompatible version",// Z_VERSION_ERROR (-6) - "" - }; - - // block not completed, need more input or more output - static final private int NeedMore=0; - - // block flush performed - static final private int BlockDone=1; - - // finish started, need only more output at next deflate - static final private int FinishStarted=2; - - // finish done, accept no more input or output - static final private int FinishDone=3; - - // preset dictionary flag in zlib header - static final private int PRESET_DICT=0x20; - - static final private int Z_FILTERED=1; - static final private int Z_HUFFMAN_ONLY=2; - static final private int Z_DEFAULT_STRATEGY=0; - - static final private int Z_NO_FLUSH=0; - static final private int Z_PARTIAL_FLUSH=1; - static final private int Z_SYNC_FLUSH=2; - static final private int Z_FULL_FLUSH=3; - static final private int Z_FINISH=4; - - static final private int Z_OK=0; - static final private int Z_STREAM_END=1; - static final private int Z_NEED_DICT=2; - static final private int Z_ERRNO=-1; - static final private int Z_STREAM_ERROR=-2; - static final private int Z_DATA_ERROR=-3; - static final private int Z_MEM_ERROR=-4; - static final private int Z_BUF_ERROR=-5; - static final private int Z_VERSION_ERROR=-6; - - static final private int INIT_STATE=42; - static final private int BUSY_STATE=113; - static final private int FINISH_STATE=666; - - // The deflate compression method - static final private int Z_DEFLATED=8; - - static final private int STORED_BLOCK=0; - static final private int STATIC_TREES=1; - static final private int DYN_TREES=2; - - // The three kinds of block type - static final private int Z_BINARY=0; - static final private int Z_ASCII=1; - static final private int Z_UNKNOWN=2; - - static final private int Buf_size=8*2; - - // repeat previous bit length 3-6 times (2 bits of repeat count) - static final private int REP_3_6=16; - - // repeat a zero length 3-10 times (3 bits of repeat count) - static final private int REPZ_3_10=17; - - // repeat a zero length 11-138 times (7 bits of repeat count) - static final private int REPZ_11_138=18; - - static final private int MIN_MATCH=3; - static final private int MAX_MATCH=258; - static final private int MIN_LOOKAHEAD=(MAX_MATCH+MIN_MATCH+1); - - static final private int MAX_BITS=15; - static final private int D_CODES=30; - static final private int BL_CODES=19; - static final private int LENGTH_CODES=29; - static final private int LITERALS=256; - static final private int L_CODES=(LITERALS+1+LENGTH_CODES); - static final private int HEAP_SIZE=(2*L_CODES+1); - - static final private int END_BLOCK=256; - - ZStream strm; // pointer back to this zlib stream - int status; // as the name implies - byte[] pending_buf; // output still pending - int pending_buf_size; // size of pending_buf - int pending_out; // next pending byte to output to the stream - int pending; // nb of bytes in the pending buffer - int wrap = 1; - byte data_type; // UNKNOWN, BINARY or ASCII - byte method; // STORED (for zip only) or DEFLATED - int last_flush; // value of flush param for previous deflate call - - int w_size; // LZ77 window size (32K by default) - int w_bits; // log2(w_size) (8..16) - int w_mask; // w_size - 1 - - byte[] window; - // Sliding window. Input bytes are read into the second half of the window, - // and move to the first half later to keep a dictionary of at least wSize - // bytes. With this organization, matches are limited to a distance of - // wSize-MAX_MATCH bytes, but this ensures that IO is always - // performed with a length multiple of the block size. Also, it limits - // the window size to 64K, which is quite useful on MSDOS. - // To do: use the user input buffer as sliding window. - - int window_size; - // Actual size of window: 2*wSize, except when the user input buffer - // is directly used as sliding window. - - short[] prev; - // Link to older string with same hash index. To limit the size of this - // array to 64K, this link is maintained only for the last 32K strings. - // An index in this array is thus a window index modulo 32K. - - short[] head; // Heads of the hash chains or NIL. - - int ins_h; // hash index of string to be inserted - int hash_size; // number of elements in hash table - int hash_bits; // log2(hash_size) - int hash_mask; // hash_size-1 - - // Number of bits by which ins_h must be shifted at each input - // step. It must be such that after MIN_MATCH steps, the oldest - // byte no longer takes part in the hash key, that is: - // hash_shift * MIN_MATCH >= hash_bits - int hash_shift; - - // Window position at the beginning of the current output block. Gets - // negative when the window is moved backwards. - - int block_start; - - int match_length; // length of best match - int prev_match; // previous match - int match_available; // set if previous match exists - int strstart; // start of string to insert - int match_start; // start of matching string - int lookahead; // number of valid bytes ahead in window - - // Length of the best match at previous step. Matches not greater than this - // are discarded. This is used in the lazy match evaluation. - int prev_length; - - // To speed up deflation, hash chains are never searched beyond this - // length. A higher limit improves compression ratio but degrades the speed. - int max_chain_length; - - // Attempt to find a better match only when the current match is strictly - // smaller than this value. This mechanism is used only for compression - // levels >= 4. - int max_lazy_match; - - // Insert new strings in the hash table only if the match length is not - // greater than this length. This saves time but degrades compression. - // max_insert_length is used only for compression levels <= 3. - - int level; // compression level (1..9) - int strategy; // favor or force Huffman coding - - // Use a faster search when the previous match is longer than this - int good_match; - - // Stop searching when current match exceeds this - int nice_match; - - short[] dyn_ltree; // literal and length tree - short[] dyn_dtree; // distance tree - short[] bl_tree; // Huffman tree for bit lengths - - Tree l_desc=new Tree(); // desc for literal tree - Tree d_desc=new Tree(); // desc for distance tree - Tree bl_desc=new Tree(); // desc for bit length tree - - // number of codes at each bit length for an optimal tree - short[] bl_count=new short[MAX_BITS+1]; - // working area to be used in Tree#gen_codes() - short[] next_code=new short[MAX_BITS+1]; - - // heap used to build the Huffman trees - int[] heap=new int[2*L_CODES+1]; - - int heap_len; // number of elements in the heap - int heap_max; // element of largest frequency - // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - // The same heap array is used to build all trees. - - // Depth of each subtree used as tie breaker for trees of equal frequency - byte[] depth=new byte[2*L_CODES+1]; - - byte[] l_buf; // index for literals or lengths */ - - // Size of match buffer for literals/lengths. There are 4 reasons for - // limiting lit_bufsize to 64K: - // - frequencies can be kept in 16 bit counters - // - if compression is not successful for the first block, all input - // data is still in the window so we can still emit a stored block even - // when input comes from standard input. (This can also be done for - // all blocks if lit_bufsize is not greater than 32K.) - // - if compression is not successful for a file smaller than 64K, we can - // even emit a stored file instead of a stored block (saving 5 bytes). - // This is applicable only for zip (not gzip or zlib). - // - creating new Huffman trees less frequently may not provide fast - // adaptation to changes in the input data statistics. (Take for - // example a binary file with poorly compressible code followed by - // a highly compressible string table.) Smaller buffer sizes give - // fast adaptation but have of course the overhead of transmitting - // trees more frequently. - // - I can't count above 4 - int lit_bufsize; - - int last_lit; // running index in l_buf - - // Buffer for distances. To simplify the code, d_buf and l_buf have - // the same number of elements. To use different lengths, an extra flag - // array would be necessary. - - int d_buf; // index of pendig_buf - - int opt_len; // bit length of current block with optimal trees - int static_len; // bit length of current block with static trees - int matches; // number of string matches in current block - int last_eob_len; // bit length of EOB code for last block - - // Output buffer. bits are inserted starting at the bottom (least - // significant bits). - short bi_buf; - - // Number of valid bits in bi_buf. All bits above the last valid bit - // are always zero. - int bi_valid; - - GZIPHeader gheader = null; - - Deflate(ZStream strm){ - this.strm=strm; - dyn_ltree=new short[HEAP_SIZE*2]; - dyn_dtree=new short[(2*D_CODES+1)*2]; // distance tree - bl_tree=new short[(2*BL_CODES+1)*2]; // Huffman tree for bit lengths - } - - void lm_init() { - window_size=2*w_size; - - head[hash_size-1]=0; - for(int i=0; i<hash_size-1; i++){ - head[i]=0; - } - - // Set the default configuration parameters: - max_lazy_match = Deflate.config_table[level].max_lazy; - good_match = Deflate.config_table[level].good_length; - nice_match = Deflate.config_table[level].nice_length; - max_chain_length = Deflate.config_table[level].max_chain; - - strstart = 0; - block_start = 0; - lookahead = 0; - match_length = prev_length = MIN_MATCH-1; - match_available = 0; - ins_h = 0; - } - - // Initialize the tree data structures for a new zlib stream. - void tr_init(){ - - l_desc.dyn_tree = dyn_ltree; - l_desc.stat_desc = StaticTree.static_l_desc; - - d_desc.dyn_tree = dyn_dtree; - d_desc.stat_desc = StaticTree.static_d_desc; - - bl_desc.dyn_tree = bl_tree; - bl_desc.stat_desc = StaticTree.static_bl_desc; - - bi_buf = 0; - bi_valid = 0; - last_eob_len = 8; // enough lookahead for inflate - - // Initialize the first block of the first file: - init_block(); - } - - void init_block(){ - // Initialize the trees. - for(int i = 0; i < L_CODES; i++) dyn_ltree[i*2] = 0; - for(int i= 0; i < D_CODES; i++) dyn_dtree[i*2] = 0; - for(int i= 0; i < BL_CODES; i++) bl_tree[i*2] = 0; - - dyn_ltree[END_BLOCK*2] = 1; - opt_len = static_len = 0; - last_lit = matches = 0; - } - - // Restore the heap property by moving down the tree starting at node k, - // exchanging a node with the smallest of its two sons if necessary, stopping - // when the heap property is re-established (each father smaller than its - // two sons). - void pqdownheap(short[] tree, // the tree to restore - int k // node to move down - ){ - int v = heap[k]; - int j = k << 1; // left son of k - while (j <= heap_len) { - // Set j to the smallest of the two sons: - if (j < heap_len && - smaller(tree, heap[j+1], heap[j], depth)){ - j++; - } - // Exit if v is smaller than both sons - if(smaller(tree, v, heap[j], depth)) break; - - // Exchange v with the smallest son - heap[k]=heap[j]; k = j; - // And continue down the tree, setting j to the left son of k - j <<= 1; - } - heap[k] = v; - } - - static boolean smaller(short[] tree, int n, int m, byte[] depth){ - short tn2=tree[n*2]; - short tm2=tree[m*2]; - return (tn2<tm2 || - (tn2==tm2 && depth[n] <= depth[m])); - } - - // Scan a literal or distance tree to determine the frequencies of the codes - // in the bit length tree. - void scan_tree (short[] tree,// the tree to be scanned - int max_code // and its largest code of non zero frequency - ){ - int n; // iterates over all tree elements - int prevlen = -1; // last emitted length - int curlen; // length of current code - int nextlen = tree[0*2+1]; // length of next code - int count = 0; // repeat count of the current code - int max_count = 7; // max repeat count - int min_count = 4; // min repeat count - - if (nextlen == 0){ max_count = 138; min_count = 3; } - tree[(max_code+1)*2+1] = (short)0xffff; // guard - - for(n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[(n+1)*2+1]; - if(++count < max_count && curlen == nextlen) { - continue; - } - else if(count < min_count) { - bl_tree[curlen*2] += count; - } - else if(curlen != 0) { - if(curlen != prevlen) bl_tree[curlen*2]++; - bl_tree[REP_3_6*2]++; - } - else if(count <= 10) { - bl_tree[REPZ_3_10*2]++; - } - else{ - bl_tree[REPZ_11_138*2]++; - } - count = 0; prevlen = curlen; - if(nextlen == 0) { - max_count = 138; min_count = 3; - } - else if(curlen == nextlen) { - max_count = 6; min_count = 3; - } - else{ - max_count = 7; min_count = 4; - } - } - } - - // Construct the Huffman tree for the bit lengths and return the index in - // bl_order of the last bit length code to send. - int build_bl_tree(){ - int max_blindex; // index of last bit length code of non zero freq - - // Determine the bit length frequencies for literal and distance trees - scan_tree(dyn_ltree, l_desc.max_code); - scan_tree(dyn_dtree, d_desc.max_code); - - // Build the bit length tree: - bl_desc.build_tree(this); - // opt_len now includes the length of the tree representations, except - // the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - - // Determine the number of bit length codes to send. The pkzip format - // requires that at least 4 bit length codes be sent. (appnote.txt says - // 3 but the actual value used is 4.) - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (bl_tree[Tree.bl_order[max_blindex]*2+1] != 0) break; - } - // Update opt_len to include the bit length tree and counts - opt_len += 3*(max_blindex+1) + 5+5+4; - - return max_blindex; - } - - - // Send the header for a block using dynamic Huffman trees: the counts, the - // lengths of the bit length codes, the literal tree and the distance tree. - // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - void send_all_trees(int lcodes, int dcodes, int blcodes){ - int rank; // index in bl_order - - send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt - send_bits(dcodes-1, 5); - send_bits(blcodes-4, 4); // not -3 as stated in appnote.txt - for (rank = 0; rank < blcodes; rank++) { - send_bits(bl_tree[Tree.bl_order[rank]*2+1], 3); - } - send_tree(dyn_ltree, lcodes-1); // literal tree - send_tree(dyn_dtree, dcodes-1); // distance tree - } - - // Send a literal or distance tree in compressed form, using the codes in - // bl_tree. - void send_tree (short[] tree,// the tree to be sent - int max_code // and its largest code of non zero frequency - ){ - int n; // iterates over all tree elements - int prevlen = -1; // last emitted length - int curlen; // length of current code - int nextlen = tree[0*2+1]; // length of next code - int count = 0; // repeat count of the current code - int max_count = 7; // max repeat count - int min_count = 4; // min repeat count - - if (nextlen == 0){ max_count = 138; min_count = 3; } - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[(n+1)*2+1]; - if(++count < max_count && curlen == nextlen) { - continue; - } - else if(count < min_count) { - do { send_code(curlen, bl_tree); } while (--count != 0); - } - else if(curlen != 0){ - if(curlen != prevlen){ - send_code(curlen, bl_tree); count--; - } - send_code(REP_3_6, bl_tree); - send_bits(count-3, 2); - } - else if(count <= 10){ - send_code(REPZ_3_10, bl_tree); - send_bits(count-3, 3); - } - else{ - send_code(REPZ_11_138, bl_tree); - send_bits(count-11, 7); - } - count = 0; prevlen = curlen; - if(nextlen == 0){ - max_count = 138; min_count = 3; - } - else if(curlen == nextlen){ - max_count = 6; min_count = 3; - } - else{ - max_count = 7; min_count = 4; - } - } - } - - // Output a byte on the stream. - // IN assertion: there is enough room in pending_buf. - final void put_byte(byte[] p, int start, int len){ - System.arraycopy(p, start, pending_buf, pending, len); - pending+=len; - } - - final void put_byte(byte c){ - pending_buf[pending++]=c; - } - final void put_short(int w) { - put_byte((byte)(w/*&0xff*/)); - put_byte((byte)(w>>>8)); - } - final void putShortMSB(int b){ - put_byte((byte)(b>>8)); - put_byte((byte)(b/*&0xff*/)); - } - - final void send_code(int c, short[] tree){ - int c2=c*2; - send_bits((tree[c2]&0xffff), (tree[c2+1]&0xffff)); - } - - void send_bits(int value, int length){ - int len = length; - if (bi_valid > (int)Buf_size - len) { - int val = value; -// bi_buf |= (val << bi_valid); - bi_buf |= ((val << bi_valid)&0xffff); - put_short(bi_buf); - bi_buf = (short)(val >>> (Buf_size - bi_valid)); - bi_valid += len - Buf_size; - } else { -// bi_buf |= (value) << bi_valid; - bi_buf |= (((value) << bi_valid)&0xffff); - bi_valid += len; - } - } - - // Send one empty static block to give enough lookahead for inflate. - // This takes 10 bits, of which 7 may remain in the bit buffer. - // The current inflate code requires 9 bits of lookahead. If the - // last two codes for the previous block (real code plus EOB) were coded - // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - // the last real code. In this case we send two empty static blocks instead - // of one. (There are no problems if the previous block is stored or fixed.) - // To simplify the code, we assume the worst case of last real code encoded - // on one bit only. - void _tr_align(){ - send_bits(STATIC_TREES<<1, 3); - send_code(END_BLOCK, StaticTree.static_ltree); - - bi_flush(); - - // Of the 10 bits for the empty block, we have already sent - // (10 - bi_valid) bits. The lookahead for the last real code (before - // the EOB of the previous block) was thus at least one plus the length - // of the EOB plus what we have just sent of the empty static block. - if (1 + last_eob_len + 10 - bi_valid < 9) { - send_bits(STATIC_TREES<<1, 3); - send_code(END_BLOCK, StaticTree.static_ltree); - bi_flush(); - } - last_eob_len = 7; - } - - - // Save the match info and tally the frequency counts. Return true if - // the current block must be flushed. - boolean _tr_tally (int dist, // distance of matched string - int lc // match length-MIN_MATCH or unmatched char (if dist==0) - ){ - - pending_buf[d_buf+last_lit*2] = (byte)(dist>>>8); - pending_buf[d_buf+last_lit*2+1] = (byte)dist; - - l_buf[last_lit] = (byte)lc; last_lit++; - - if (dist == 0) { - // lc is the unmatched char - dyn_ltree[lc*2]++; - } - else { - matches++; - // Here, lc is the match length - MIN_MATCH - dist--; // dist = match distance - 1 - dyn_ltree[(Tree._length_code[lc]+LITERALS+1)*2]++; - dyn_dtree[Tree.d_code(dist)*2]++; - } - - if ((last_lit & 0x1fff) == 0 && level > 2) { - // Compute an upper bound for the compressed length - int out_length = last_lit*8; - int in_length = strstart - block_start; - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (int)dyn_dtree[dcode*2] * - (5L+Tree.extra_dbits[dcode]); - } - out_length >>>= 3; - if ((matches < (last_lit/2)) && out_length < in_length/2) return true; - } - - return (last_lit == lit_bufsize-1); - // We avoid equality with lit_bufsize because of wraparound at 64K - // on 16 bit machines and because stored blocks are restricted to - // 64K-1 bytes. - } - - // Send the block data compressed using the given Huffman trees - void compress_block(short[] ltree, short[] dtree){ - int dist; // distance of matched string - int lc; // match length or unmatched char (if dist == 0) - int lx = 0; // running index in l_buf - int code; // the code to send - int extra; // number of extra bits to send - - if (last_lit != 0){ - do{ - dist=((pending_buf[d_buf+lx*2]<<8)&0xff00)| - (pending_buf[d_buf+lx*2+1]&0xff); - lc=(l_buf[lx])&0xff; lx++; - - if(dist == 0){ - send_code(lc, ltree); // send a literal byte - } - else{ - // Here, lc is the match length - MIN_MATCH - code = Tree._length_code[lc]; - - send_code(code+LITERALS+1, ltree); // send the length code - extra = Tree.extra_lbits[code]; - if(extra != 0){ - lc -= Tree.base_length[code]; - send_bits(lc, extra); // send the extra length bits - } - dist--; // dist is now the match distance - 1 - code = Tree.d_code(dist); - - send_code(code, dtree); // send the distance code - extra = Tree.extra_dbits[code]; - if (extra != 0) { - dist -= Tree.base_dist[code]; - send_bits(dist, extra); // send the extra distance bits - } - } // literal or match pair ? - - // Check that the overlay between pending_buf and d_buf+l_buf is ok: - } - while (lx < last_lit); - } - - send_code(END_BLOCK, ltree); - last_eob_len = ltree[END_BLOCK*2+1]; - } - - // Set the data type to ASCII or BINARY, using a crude approximation: - // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. - // IN assertion: the fields freq of dyn_ltree are set and the total of all - // frequencies does not exceed 64K (to fit in an int on 16 bit machines). - void set_data_type(){ - int n = 0; - int ascii_freq = 0; - int bin_freq = 0; - while(n<7){ bin_freq += dyn_ltree[n*2]; n++;} - while(n<128){ ascii_freq += dyn_ltree[n*2]; n++;} - while(n<LITERALS){ bin_freq += dyn_ltree[n*2]; n++;} - data_type=(byte)(bin_freq > (ascii_freq >>> 2) ? Z_BINARY : Z_ASCII); - } - - // Flush the bit buffer, keeping at most 7 bits in it. - void bi_flush(){ - if (bi_valid == 16) { - put_short(bi_buf); - bi_buf=0; - bi_valid=0; - } - else if (bi_valid >= 8) { - put_byte((byte)bi_buf); - bi_buf>>>=8; - bi_valid-=8; - } - } - - // Flush the bit buffer and align the output on a byte boundary - void bi_windup(){ - if (bi_valid > 8) { - put_short(bi_buf); - } else if (bi_valid > 0) { - put_byte((byte)bi_buf); - } - bi_buf = 0; - bi_valid = 0; - } - - // Copy a stored block, storing first the length and its - // one's complement if requested. - void copy_block(int buf, // the input data - int len, // its length - boolean header // true if block header must be written - ){ - int index=0; - bi_windup(); // align on byte boundary - last_eob_len = 8; // enough lookahead for inflate - - if (header) { - put_short((short)len); - put_short((short)~len); - } - - // while(len--!=0) { - // put_byte(window[buf+index]); - // index++; - // } - put_byte(window, buf, len); - } - - void flush_block_only(boolean eof){ - _tr_flush_block(block_start>=0 ? block_start : -1, - strstart-block_start, - eof); - block_start=strstart; - strm.flush_pending(); - } - - // Copy without compression as much as possible from the input stream, return - // the current block state. - // This function does not insert new strings in the dictionary since - // uncompressible data is probably not useful. This function is used - // only for the level=0 compression option. - // NOTE: this function should be optimized to avoid extra copying from - // window to pending_buf. - int deflate_stored(int flush){ - // Stored blocks are limited to 0xffff bytes, pending_buf is limited - // to pending_buf_size, and each stored block has a 5 byte header: - - int max_block_size = 0xffff; - int max_start; - - if(max_block_size > pending_buf_size - 5) { - max_block_size = pending_buf_size - 5; - } - - // Copy as much as possible from input to output: - while(true){ - // Fill the window as much as possible: - if(lookahead<=1){ - fill_window(); - if(lookahead==0 && flush==Z_NO_FLUSH) return NeedMore; - if(lookahead==0) break; // flush the current block - } - - strstart+=lookahead; - lookahead=0; - - // Emit a stored block if pending_buf will be full: - max_start=block_start+max_block_size; - if(strstart==0|| strstart>=max_start) { - // strstart == 0 is possible when wraparound on 16-bit machine - lookahead = (int)(strstart-max_start); - strstart = (int)max_start; - - flush_block_only(false); - if(strm.avail_out==0) return NeedMore; - - } - - // Flush if we may have to slide, otherwise block_start may become - // negative and the data will be gone: - if(strstart-block_start >= w_size-MIN_LOOKAHEAD) { - flush_block_only(false); - if(strm.avail_out==0) return NeedMore; - } - } - - flush_block_only(flush == Z_FINISH); - if(strm.avail_out==0) - return (flush == Z_FINISH) ? FinishStarted : NeedMore; - - return flush == Z_FINISH ? FinishDone : BlockDone; - } - - // Send a stored block - void _tr_stored_block(int buf, // input block - int stored_len, // length of input block - boolean eof // true if this is the last block for a file - ){ - send_bits((STORED_BLOCK<<1)+(eof?1:0), 3); // send block type - copy_block(buf, stored_len, true); // with header - } - - // Determine the best encoding for the current block: dynamic trees, static - // trees or store, and output the encoded block to the zip file. - void _tr_flush_block(int buf, // input block, or NULL if too old - int stored_len, // length of input block - boolean eof // true if this is the last block for a file - ) { - int opt_lenb, static_lenb;// opt_len and static_len in bytes - int max_blindex = 0; // index of last bit length code of non zero freq - - // Build the Huffman trees unless a stored block is forced - if(level > 0) { - // Check if the file is ascii or binary - if(data_type == Z_UNKNOWN) set_data_type(); - - // Construct the literal and distance trees - l_desc.build_tree(this); - - d_desc.build_tree(this); - - // At this point, opt_len and static_len are the total bit lengths of - // the compressed block data, excluding the tree representations. - - // Build the bit length tree for the above two trees, and get the index - // in bl_order of the last bit length code to send. - max_blindex=build_bl_tree(); - - // Determine the best encoding. Compute first the block length in bytes - opt_lenb=(opt_len+3+7)>>>3; - static_lenb=(static_len+3+7)>>>3; - - if(static_lenb<=opt_lenb) opt_lenb=static_lenb; - } - else { - opt_lenb=static_lenb=stored_len+5; // force a stored block - } - - if(stored_len+4<=opt_lenb && buf != -1){ - // 4: two words for the lengths - // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - // Otherwise we can't have processed more than WSIZE input bytes since - // the last block flush, because compression would have been - // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - // transform a block into a stored block. - _tr_stored_block(buf, stored_len, eof); - } - else if(static_lenb == opt_lenb){ - send_bits((STATIC_TREES<<1)+(eof?1:0), 3); - compress_block(StaticTree.static_ltree, StaticTree.static_dtree); - } - else{ - send_bits((DYN_TREES<<1)+(eof?1:0), 3); - send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); - compress_block(dyn_ltree, dyn_dtree); - } - - // The above check is made mod 2^32, for files larger than 512 MB - // and uLong implemented on 32 bits. - - init_block(); - - if(eof){ - bi_windup(); - } - } - - // Fill the window when the lookahead becomes insufficient. - // Updates strstart and lookahead. - // - // IN assertion: lookahead < MIN_LOOKAHEAD - // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - // At least one byte has been read, or avail_in == 0; reads are - // performed for at least two bytes (required for the zip translate_eol - // option -- not supported here). - void fill_window(){ - int n, m; - int p; - int more; // Amount of free space at the end of the window. - - do{ - more = (window_size-lookahead-strstart); - - // Deal with !@#$% 64K limit: - if(more==0 && strstart==0 && lookahead==0){ - more = w_size; - } - else if(more==-1) { - // Very unlikely, but possible on 16 bit machine if strstart == 0 - // and lookahead == 1 (input done one byte at time) - more--; - - // If the window is almost full and there is insufficient lookahead, - // move the upper half to the lower one to make room in the upper half. - } - else if(strstart >= w_size+ w_size-MIN_LOOKAHEAD) { - System.arraycopy(window, w_size, window, 0, w_size); - match_start-=w_size; - strstart-=w_size; // we now have strstart >= MAX_DIST - block_start-=w_size; - - // Slide the hash table (could be avoided with 32 bit values - // at the expense of memory usage). We slide even when level == 0 - // to keep the hash table consistent if we switch back to level > 0 - // later. (Using level 0 permanently is not an optimal usage of - // zlib, so we don't care about this pathological case.) - - n = hash_size; - p=n; - do { - m = (head[--p]&0xffff); - head[p]=(m>=w_size ? (short)(m-w_size) : 0); - } - while (--n != 0); - - n = w_size; - p = n; - do { - m = (prev[--p]&0xffff); - prev[p] = (m >= w_size ? (short)(m-w_size) : 0); - // If n is not on any hash chain, prev[n] is garbage but - // its value will never be used. - } - while (--n!=0); - more += w_size; - } - - if (strm.avail_in == 0) return; - - // If there was no sliding: - // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - // more == window_size - lookahead - strstart - // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - // => more >= window_size - 2*WSIZE + 2 - // In the BIG_MEM or MMAP case (not yet supported), - // window_size == input_size + MIN_LOOKAHEAD && - // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - // Otherwise, window_size == 2*WSIZE so more >= 2. - // If there was sliding, more >= WSIZE. So in all cases, more >= 2. - - n = strm.read_buf(window, strstart + lookahead, more); - lookahead += n; - - // Initialize the hash value now that we have some input: - if(lookahead >= MIN_MATCH) { - ins_h = window[strstart]&0xff; - ins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask; - } - // If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - // but this is not important since only literal bytes will be emitted. - } - while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0); - } - - // Compress as much as possible from the input stream, return the current - // block state. - // This function does not perform lazy evaluation of matches and inserts - // new strings in the dictionary only for unmatched strings or for short - // matches. It is used only for the fast compression options. - int deflate_fast(int flush){ -// short hash_head = 0; // head of the hash chain - int hash_head = 0; // head of the hash chain - boolean bflush; // set if current block must be flushed - - while(true){ - // Make sure that we always have enough lookahead, except - // at the end of the input file. We need MAX_MATCH bytes - // for the next match, plus MIN_MATCH bytes to insert the - // string following the next match. - if(lookahead < MIN_LOOKAHEAD){ - fill_window(); - if(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH){ - return NeedMore; - } - if(lookahead == 0) break; // flush the current block - } - - // Insert the string window[strstart .. strstart+2] in the - // dictionary, and set hash_head to the head of the hash chain: - if(lookahead >= MIN_MATCH){ - ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask; - -// prev[strstart&w_mask]=hash_head=head[ins_h]; - hash_head=(head[ins_h]&0xffff); - prev[strstart&w_mask]=head[ins_h]; - head[ins_h]=(short)strstart; - } - - // Find the longest match, discarding those <= prev_length. - // At this point we have always match_length < MIN_MATCH - - if(hash_head!=0L && - ((strstart-hash_head)&0xffff) <= w_size-MIN_LOOKAHEAD - ){ - // To simplify the code, we prevent matches with the string - // of window index 0 (in particular we have to avoid a match - // of the string with itself at the start of the input file). - if(strategy != Z_HUFFMAN_ONLY){ - match_length=longest_match (hash_head); - } - // longest_match() sets match_start - } - if(match_length>=MIN_MATCH){ - // check_match(strstart, match_start, match_length); - - bflush=_tr_tally(strstart-match_start, match_length-MIN_MATCH); - - lookahead -= match_length; - - // Insert new strings in the hash table only if the match length - // is not too large. This saves time but degrades compression. - if(match_length <= max_lazy_match && - lookahead >= MIN_MATCH) { - match_length--; // string at strstart already in hash table - do{ - strstart++; - - ins_h=((ins_h<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask; -// prev[strstart&w_mask]=hash_head=head[ins_h]; - hash_head=(head[ins_h]&0xffff); - prev[strstart&w_mask]=head[ins_h]; - head[ins_h]=(short)strstart; - - // strstart never exceeds WSIZE-MAX_MATCH, so there are - // always MIN_MATCH bytes ahead. - } - while (--match_length != 0); - strstart++; - } - else{ - strstart += match_length; - match_length = 0; - ins_h = window[strstart]&0xff; - - ins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask; - // If lookahead < MIN_MATCH, ins_h is garbage, but it does not - // matter since it will be recomputed at next deflate call. - } - } - else { - // No match, output a literal byte - - bflush=_tr_tally(0, window[strstart]&0xff); - lookahead--; - strstart++; - } - if (bflush){ - - flush_block_only(false); - if(strm.avail_out==0) return NeedMore; - } - } - - flush_block_only(flush == Z_FINISH); - if(strm.avail_out==0){ - if(flush == Z_FINISH) return FinishStarted; - else return NeedMore; - } - return flush==Z_FINISH ? FinishDone : BlockDone; - } - - // Same as above, but achieves better compression. We use a lazy - // evaluation for matches: a match is finally adopted only if there is - // no better match at the next window position. - int deflate_slow(int flush){ -// short hash_head = 0; // head of hash chain - int hash_head = 0; // head of hash chain - boolean bflush; // set if current block must be flushed - - // Process the input block. - while(true){ - // Make sure that we always have enough lookahead, except - // at the end of the input file. We need MAX_MATCH bytes - // for the next match, plus MIN_MATCH bytes to insert the - // string following the next match. - - if (lookahead < MIN_LOOKAHEAD) { - fill_window(); - if(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return NeedMore; - } - if(lookahead == 0) break; // flush the current block - } - - // Insert the string window[strstart .. strstart+2] in the - // dictionary, and set hash_head to the head of the hash chain: - - if(lookahead >= MIN_MATCH) { - ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff)) & hash_mask; -// prev[strstart&w_mask]=hash_head=head[ins_h]; - hash_head=(head[ins_h]&0xffff); - prev[strstart&w_mask]=head[ins_h]; - head[ins_h]=(short)strstart; - } - - // Find the longest match, discarding those <= prev_length. - prev_length = match_length; prev_match = match_start; - match_length = MIN_MATCH-1; - - if (hash_head != 0 && prev_length < max_lazy_match && - ((strstart-hash_head)&0xffff) <= w_size-MIN_LOOKAHEAD - ){ - // To simplify the code, we prevent matches with the string - // of window index 0 (in particular we have to avoid a match - // of the string with itself at the start of the input file). - - if(strategy != Z_HUFFMAN_ONLY) { - match_length = longest_match(hash_head); - } - // longest_match() sets match_start - - if (match_length <= 5 && (strategy == Z_FILTERED || - (match_length == MIN_MATCH && - strstart - match_start > 4096))) { - - // If prev_match is also MIN_MATCH, match_start is garbage - // but we will ignore the current match anyway. - match_length = MIN_MATCH-1; - } - } - - // If there was a match at the previous step and the current - // match is not better, output the previous match: - if(prev_length >= MIN_MATCH && match_length <= prev_length) { - int max_insert = strstart + lookahead - MIN_MATCH; - // Do not insert strings in hash table beyond this. - - // check_match(strstart-1, prev_match, prev_length); - - bflush=_tr_tally(strstart-1-prev_match, prev_length - MIN_MATCH); - - // Insert in hash table all strings up to the end of the match. - // strstart-1 and strstart are already inserted. If there is not - // enough lookahead, the last two strings are not inserted in - // the hash table. - lookahead -= prev_length-1; - prev_length -= 2; - do{ - if(++strstart <= max_insert) { - ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask; - //prev[strstart&w_mask]=hash_head=head[ins_h]; - hash_head=(head[ins_h]&0xffff); - prev[strstart&w_mask]=head[ins_h]; - head[ins_h]=(short)strstart; - } - } - while(--prev_length != 0); - match_available = 0; - match_length = MIN_MATCH-1; - strstart++; - - if (bflush){ - flush_block_only(false); - if(strm.avail_out==0) return NeedMore; - } - } else if (match_available!=0) { - - // If there was no match at the previous position, output a - // single literal. If there was a match but the current match - // is longer, truncate the previous match to a single literal. - - bflush=_tr_tally(0, window[strstart-1]&0xff); - - if (bflush) { - flush_block_only(false); - } - strstart++; - lookahead--; - if(strm.avail_out == 0) return NeedMore; - } else { - // There is no previous match to compare with, wait for - // the next step to decide. - - match_available = 1; - strstart++; - lookahead--; - } - } - - if(match_available!=0) { - bflush=_tr_tally(0, window[strstart-1]&0xff); - match_available = 0; - } - flush_block_only(flush == Z_FINISH); - - if(strm.avail_out==0){ - if(flush == Z_FINISH) return FinishStarted; - else return NeedMore; - } - - return flush == Z_FINISH ? FinishDone : BlockDone; - } - - int longest_match(int cur_match){ - int chain_length = max_chain_length; // max hash chain length - int scan = strstart; // current string - int match; // matched string - int len; // length of current match - int best_len = prev_length; // best match length so far - int limit = strstart>(w_size-MIN_LOOKAHEAD) ? - strstart-(w_size-MIN_LOOKAHEAD) : 0; - int nice_match=this.nice_match; - - // Stop when cur_match becomes <= limit. To simplify the code, - // we prevent matches with the string of window index 0. - - int wmask = w_mask; - - int strend = strstart + MAX_MATCH; - byte scan_end1 = window[scan+best_len-1]; - byte scan_end = window[scan+best_len]; - - // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - // It is easy to get rid of this optimization if necessary. - - // Do not waste too much time if we already have a good match: - if (prev_length >= good_match) { - chain_length >>= 2; - } - - // Do not look for matches beyond the end of the input. This is necessary - // to make deflate deterministic. - if (nice_match > lookahead) nice_match = lookahead; - - do { - match = cur_match; - - // Skip to next match if the match length cannot increase - // or if the match length is less than 2: - if (window[match+best_len] != scan_end || - window[match+best_len-1] != scan_end1 || - window[match] != window[scan] || - window[++match] != window[scan+1]) continue; - - // The check at best_len-1 can be removed because it will be made - // again later. (This heuristic is not always a win.) - // It is not necessary to compare scan[2] and match[2] since they - // are always equal when the other bytes match, given that - // the hash keys are equal and that HASH_BITS >= 8. - scan += 2; match++; - - // We check for insufficient lookahead only every 8th comparison; - // the 256th check will be made at strstart+258. - do { - } while (window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - scan < strend); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - - if(len>best_len) { - match_start = cur_match; - best_len = len; - if (len >= nice_match) break; - scan_end1 = window[scan+best_len-1]; - scan_end = window[scan+best_len]; - } - - } while ((cur_match = (prev[cur_match & wmask]&0xffff)) > limit - && --chain_length != 0); - - if (best_len <= lookahead) return best_len; - return lookahead; - } - - int deflateInit(int level, int bits, int memlevel){ - return deflateInit(level, Z_DEFLATED, bits, memlevel, - Z_DEFAULT_STRATEGY); - } - - int deflateInit(int level, int bits){ - return deflateInit(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY); - } - int deflateInit(int level){ - return deflateInit(level, MAX_WBITS); - } - private int deflateInit(int level, int method, int windowBits, - int memLevel, int strategy){ - int wrap = 1; - // byte[] my_version=ZLIB_VERSION; - - // - // if (version == null || version[0] != my_version[0] - // || stream_size != sizeof(z_stream)) { - // return Z_VERSION_ERROR; - // } - - strm.msg = null; - - if (level == Z_DEFAULT_COMPRESSION) level = 6; - - if (windowBits < 0) { // undocumented feature: suppress zlib header - wrap = 0; - windowBits = -windowBits; - } - else if(windowBits > 15){ - wrap = 2; - windowBits -= 16; - strm.adler=new CRC32(); - } - - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || - method != Z_DEFLATED || - windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_HUFFMAN_ONLY) { - return Z_STREAM_ERROR; - } - - strm.dstate = (Deflate)this; - - this.wrap = wrap; - w_bits = windowBits; - w_size = 1 << w_bits; - w_mask = w_size - 1; - - hash_bits = memLevel + 7; - hash_size = 1 << hash_bits; - hash_mask = hash_size - 1; - hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH); - - window = new byte[w_size*2]; - prev = new short[w_size]; - head = new short[hash_size]; - - lit_bufsize = 1 << (memLevel + 6); // 16K elements by default - - // We overlay pending_buf and d_buf+l_buf. This works since the average - // output size for (length,distance) codes is <= 24 bits. - pending_buf = new byte[lit_bufsize*3]; - pending_buf_size = lit_bufsize*3; - - d_buf = lit_bufsize; - l_buf = new byte[lit_bufsize]; - - this.level = level; - - this.strategy = strategy; - this.method = (byte)method; - - return deflateReset(); - } - - int deflateReset(){ - strm.total_in = strm.total_out = 0; - strm.msg = null; // - strm.data_type = Z_UNKNOWN; - - pending = 0; - pending_out = 0; - - if(wrap < 0){ - wrap = -wrap; - } - status = (wrap==0) ? BUSY_STATE : INIT_STATE; - strm.adler.reset(); - - last_flush = Z_NO_FLUSH; - - tr_init(); - lm_init(); - return Z_OK; - } - - int deflateEnd(){ - if(status!=INIT_STATE && status!=BUSY_STATE && status!=FINISH_STATE){ - return Z_STREAM_ERROR; - } - // Deallocate in reverse order of allocations: - pending_buf=null; - l_buf=null; - head=null; - prev=null; - window=null; - // free - // dstate=null; - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; - } - - int deflateParams(int _level, int _strategy){ - int err=Z_OK; - - if(_level == Z_DEFAULT_COMPRESSION){ - _level = 6; - } - if(_level < 0 || _level > 9 || - _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { - return Z_STREAM_ERROR; - } - - if(config_table[level].func!=config_table[_level].func && - strm.total_in != 0) { - // Flush the last buffer: - err = strm.deflate(Z_PARTIAL_FLUSH); - } - - if(level != _level) { - level = _level; - max_lazy_match = config_table[level].max_lazy; - good_match = config_table[level].good_length; - nice_match = config_table[level].nice_length; - max_chain_length = config_table[level].max_chain; - } - strategy = _strategy; - return err; - } - - int deflateSetDictionary (byte[] dictionary, int dictLength){ - int length = dictLength; - int index=0; - - if(dictionary == null || status != INIT_STATE) - return Z_STREAM_ERROR; - - strm.adler.update(dictionary, 0, dictLength); - - if(length < MIN_MATCH) return Z_OK; - if(length > w_size-MIN_LOOKAHEAD){ - length = w_size-MIN_LOOKAHEAD; - index=dictLength-length; // use the tail of the dictionary - } - System.arraycopy(dictionary, index, window, 0, length); - strstart = length; - block_start = length; - - // Insert all strings in the hash table (except for the last two bytes). - // s->lookahead stays null, so s->ins_h will be recomputed at the next - // call of fill_window. - - ins_h = window[0]&0xff; - ins_h=(((ins_h)<<hash_shift)^(window[1]&0xff))&hash_mask; - - for(int n=0; n<=length-MIN_MATCH; n++){ - ins_h=(((ins_h)<<hash_shift)^(window[(n)+(MIN_MATCH-1)]&0xff))&hash_mask; - prev[n&w_mask]=head[ins_h]; - head[ins_h]=(short)n; - } - return Z_OK; - } - - int deflate(int flush){ - int old_flush; - - if(flush>Z_FINISH || flush<0){ - return Z_STREAM_ERROR; - } - - if(strm.next_out == null || - (strm.next_in == null && strm.avail_in != 0) || - (status == FINISH_STATE && flush != Z_FINISH)) { - strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)]; - return Z_STREAM_ERROR; - } - if(strm.avail_out == 0){ - strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; - return Z_BUF_ERROR; - } - - old_flush = last_flush; - last_flush = flush; - - // Write the zlib header - if(status == INIT_STATE) { - if(wrap == 2){ - getGZIPHeader().put(this); - status=BUSY_STATE; - strm.adler.reset(); - } - else{ - int header = (Z_DEFLATED+((w_bits-8)<<4))<<8; - int level_flags=((level-1)&0xff)>>1; - - if(level_flags>3) level_flags=3; - header |= (level_flags<<6); - if(strstart!=0) header |= PRESET_DICT; - header+=31-(header % 31); - - status=BUSY_STATE; - putShortMSB(header); - - - // Save the adler32 of the preset dictionary: - if(strstart!=0){ - long adler=strm.adler.getValue(); - putShortMSB((int)(adler>>>16)); - putShortMSB((int)(adler&0xffff)); - } - strm.adler.reset(); - } - } - - // Flush as much pending output as possible - if(pending != 0) { - strm.flush_pending(); - if(strm.avail_out == 0) { - // Since avail_out is 0, deflate will be called again with - // more output space, but possibly with both pending and - // avail_in equal to zero. There won't be anything to do, - // but this is not an error situation so make sure we - // return OK instead of BUF_ERROR at next call of deflate: - last_flush = -1; - return Z_OK; - } - - // Make sure there is something to do and avoid duplicate consecutive - // flushes. For repeated and useless calls with Z_FINISH, we keep - // returning Z_STREAM_END instead of Z_BUFF_ERROR. - } - else if(strm.avail_in==0 && flush <= old_flush && - flush != Z_FINISH) { - strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; - return Z_BUF_ERROR; - } - - // User must not provide more input after the first FINISH: - if(status == FINISH_STATE && strm.avail_in != 0) { - strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; - return Z_BUF_ERROR; - } - - // Start a new block or continue the current one. - if(strm.avail_in!=0 || lookahead!=0 || - (flush != Z_NO_FLUSH && status != FINISH_STATE)) { - int bstate=-1; - switch(config_table[level].func){ - case STORED: - bstate = deflate_stored(flush); - break; - case FAST: - bstate = deflate_fast(flush); - break; - case SLOW: - bstate = deflate_slow(flush); - break; - default: - } - - if (bstate==FinishStarted || bstate==FinishDone) { - status = FINISH_STATE; - } - if (bstate==NeedMore || bstate==FinishStarted) { - if(strm.avail_out == 0) { - last_flush = -1; // avoid BUF_ERROR next call, see above - } - return Z_OK; - // If flush != Z_NO_FLUSH && avail_out == 0, the next call - // of deflate should use the same flush parameter to make sure - // that the flush is complete. So we don't have to output an - // empty block here, this will be done at next call. This also - // ensures that for a very small output buffer, we emit at most - // one empty block. - } - - if (bstate==BlockDone) { - if(flush == Z_PARTIAL_FLUSH) { - _tr_align(); - } - else { // FULL_FLUSH or SYNC_FLUSH - _tr_stored_block(0, 0, false); - // For a full flush, this empty block will be recognized - // as a special marker by inflate_sync(). - if(flush == Z_FULL_FLUSH) { - //state.head[s.hash_size-1]=0; - for(int i=0; i<hash_size/*-1*/; i++) // forget history - head[i]=0; - } - } - strm.flush_pending(); - if(strm.avail_out == 0) { - last_flush = -1; // avoid BUF_ERROR at next call, see above - return Z_OK; - } - } - } - - if(flush!=Z_FINISH) return Z_OK; - if(wrap<=0) return Z_STREAM_END; - - if(wrap==2){ - long adler=strm.adler.getValue(); - put_byte((byte)(adler&0xff)); - put_byte((byte)((adler>>8)&0xff)); - put_byte((byte)((adler>>16)&0xff)); - put_byte((byte)((adler>>24)&0xff)); - put_byte((byte)(strm.total_in&0xff)); - put_byte((byte)((strm.total_in>>8)&0xff)); - put_byte((byte)((strm.total_in>>16)&0xff)); - put_byte((byte)((strm.total_in>>24)&0xff)); - - getGZIPHeader().setCRC(adler); - } - else{ - // Write the zlib trailer (adler32) - long adler=strm.adler.getValue(); - putShortMSB((int)(adler>>>16)); - putShortMSB((int)(adler&0xffff)); - } - - strm.flush_pending(); - - // If avail_out is zero, the application will call deflate again - // to flush the rest. - - if(wrap > 0) wrap = -wrap; // write the trailer only once! - return pending != 0 ? Z_OK : Z_STREAM_END; - } - - static int deflateCopy(ZStream dest, ZStream src){ - - if(src.dstate == null){ - return Z_STREAM_ERROR; - } - - if(src.next_in!=null){ - dest.next_in = new byte[src.next_in.length]; - System.arraycopy(src.next_in, 0, dest.next_in, 0, src.next_in.length); - } - dest.next_in_index = src.next_in_index; - dest.avail_in = src.avail_in; - dest.total_in = src.total_in; - - if(src.next_out!=null){ - dest.next_out = new byte[src.next_out.length]; - System.arraycopy(src.next_out, 0, dest.next_out ,0 , src.next_out.length); - } - - dest.next_out_index = src.next_out_index; - dest.avail_out = src.avail_out; - dest.total_out = src.total_out; - - dest.msg = src.msg; - dest.data_type = src.data_type; - dest.adler = src.adler.copy(); - - try{ - dest.dstate = (Deflate)src.dstate.clone(); - dest.dstate.strm = dest; - } - catch(CloneNotSupportedException e){ - // - } - return Z_OK; - } - - public Object clone() throws CloneNotSupportedException { - Deflate dest = (Deflate)super.clone(); - - dest.pending_buf = dup(dest.pending_buf); - dest.d_buf = dest.d_buf; - dest.l_buf = dup(dest.l_buf); - dest.window = dup(dest.window); - - dest.prev = dup(dest.prev); - dest.head = dup(dest.head); - dest.dyn_ltree = dup(dest.dyn_ltree); - dest.dyn_dtree = dup(dest.dyn_dtree); - dest.bl_tree = dup(dest.bl_tree); - - dest.bl_count = dup(dest.bl_count); - dest.next_code = dup(dest.next_code); - dest.heap = dup(dest.heap); - dest.depth = dup(dest.depth); - - dest.l_desc.dyn_tree = dest.dyn_ltree; - dest.d_desc.dyn_tree = dest.dyn_dtree; - dest.bl_desc.dyn_tree = dest.bl_tree; - - /* - dest.l_desc.stat_desc = StaticTree.static_l_desc; - dest.d_desc.stat_desc = StaticTree.static_d_desc; - dest.bl_desc.stat_desc = StaticTree.static_bl_desc; - */ - - if(dest.gheader!=null){ - dest.gheader = (GZIPHeader)dest.gheader.clone(); - } - - return dest; - } - - private byte[] dup(byte[] buf){ - byte[] foo = new byte[buf.length]; - System.arraycopy(buf, 0, foo, 0, foo.length); - return foo; - } - private short[] dup(short[] buf){ - short[] foo = new short[buf.length]; - System.arraycopy(buf, 0, foo, 0, foo.length); - return foo; - } - private int[] dup(int[] buf){ - int[] foo = new int[buf.length]; - System.arraycopy(buf, 0, foo, 0, foo.length); - return foo; - } - - synchronized GZIPHeader getGZIPHeader(){ - if(gheader==null){ - gheader = new GZIPHeader(); - } - return gheader; - } -}
--- a/src/com/jcraft/jzlib/Deflater.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final public class Deflater extends ZStream{ - - static final private int MAX_WBITS=15; // 32K LZ77 window - static final private int DEF_WBITS=MAX_WBITS; - - static final private int Z_NO_FLUSH=0; - static final private int Z_PARTIAL_FLUSH=1; - static final private int Z_SYNC_FLUSH=2; - static final private int Z_FULL_FLUSH=3; - static final private int Z_FINISH=4; - - static final private int MAX_MEM_LEVEL=9; - - static final private int Z_OK=0; - static final private int Z_STREAM_END=1; - static final private int Z_NEED_DICT=2; - static final private int Z_ERRNO=-1; - static final private int Z_STREAM_ERROR=-2; - static final private int Z_DATA_ERROR=-3; - static final private int Z_MEM_ERROR=-4; - static final private int Z_BUF_ERROR=-5; - static final private int Z_VERSION_ERROR=-6; - - private boolean finished = false; - - public Deflater(){ - super(); - } - - public Deflater(int level) throws GZIPException { - this(level, MAX_WBITS); - } - - public Deflater(int level, boolean nowrap) throws GZIPException { - this(level, MAX_WBITS, nowrap); - } - - public Deflater(int level, int bits) throws GZIPException { - this(level, bits, false); - } - - public Deflater(int level, int bits, boolean nowrap) throws GZIPException { - super(); - int ret = init(level, bits, nowrap); - if(ret!=Z_OK) - throw new GZIPException(ret+": "+msg); - } - - public Deflater(int level, int bits, int memlevel, JZlib.WrapperType wrapperType) throws GZIPException { - super(); - int ret = init(level, bits, memlevel, wrapperType); - if(ret!=Z_OK) - throw new GZIPException(ret+": "+msg); - } - - public Deflater(int level, int bits, int memlevel) throws GZIPException { - super(); - int ret = init(level, bits, memlevel); - if(ret!=Z_OK) - throw new GZIPException(ret+": "+msg); - } - - public int init(int level){ - return init(level, MAX_WBITS); - } - public int init(int level, boolean nowrap){ - return init(level, MAX_WBITS, nowrap); - } - public int init(int level, int bits){ - return init(level, bits, false); - } - public int init(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){ - if(bits < 9 || bits > 15){ - return Z_STREAM_ERROR; - } - if(wrapperType == JZlib.W_NONE) { - bits *= -1; - } - else if(wrapperType == JZlib.W_GZIP) { - bits += 16; - } - else if(wrapperType == JZlib.W_ANY) { - return Z_STREAM_ERROR; - } - else if(wrapperType == JZlib.W_ZLIB) { - } - return init(level, bits, memlevel); - } - public int init(int level, int bits, int memlevel){ - finished = false; - dstate=new Deflate(this); - return dstate.deflateInit(level, bits, memlevel); - } - public int init(int level, int bits, boolean nowrap){ - finished = false; - dstate=new Deflate(this); - return dstate.deflateInit(level, nowrap?-bits:bits); - } - - public int deflate(int flush){ - if(dstate==null){ - return Z_STREAM_ERROR; - } - int ret = dstate.deflate(flush); - if(ret == Z_STREAM_END) - finished = true; - return ret; - } - public int end(){ - finished = true; - if(dstate==null) return Z_STREAM_ERROR; - int ret=dstate.deflateEnd(); - dstate=null; - free(); - return ret; - } - public int params(int level, int strategy){ - if(dstate==null) return Z_STREAM_ERROR; - return dstate.deflateParams(level, strategy); - } - public int setDictionary (byte[] dictionary, int dictLength){ - if(dstate == null) - return Z_STREAM_ERROR; - return dstate.deflateSetDictionary(dictionary, dictLength); - } - - public boolean finished(){ - return finished; - } - - public int copy(Deflater src){ - this.finished = src.finished; - return Deflate.deflateCopy(this, src); - } -}
--- a/src/com/jcraft/jzlib/DeflaterOutputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jcraft.jzlib; -import java.io.*; - -public class DeflaterOutputStream extends FilterOutputStream { - - protected final Deflater deflater; - - protected byte[] buffer; - - private boolean closed = false; - - private boolean syncFlush = false; - - private final byte[] buf1 = new byte[1]; - - protected boolean mydeflater = false; - - private boolean close_out = true; - - protected static final int DEFAULT_BUFSIZE = 512; - - public DeflaterOutputStream(OutputStream out) throws IOException { - this(out, - new Deflater(JZlib.Z_DEFAULT_COMPRESSION), - DEFAULT_BUFSIZE, true); - mydeflater = true; - } - - public DeflaterOutputStream(OutputStream out, Deflater def) throws IOException { - this(out, def, DEFAULT_BUFSIZE, true); - } - - public DeflaterOutputStream(OutputStream out, - Deflater deflater, - int size) throws IOException { - this(out, deflater, size, true); - } - public DeflaterOutputStream(OutputStream out, - Deflater deflater, - int size, - boolean close_out) throws IOException { - super(out); - if (out == null || deflater == null) { - throw new NullPointerException(); - } - else if (size <= 0) { - throw new IllegalArgumentException("buffer size must be greater than 0"); - } - this.deflater = deflater; - buffer = new byte[size]; - this.close_out = close_out; - } - - public void write(int b) throws IOException { - buf1[0] = (byte)(b & 0xff); - write(buf1, 0, 1); - } - - public void write(byte[] b, int off, int len) throws IOException { - if (deflater.finished()) { - throw new IOException("finished"); - } - else if (off<0 | len<0 | off+len>b.length) { - throw new IndexOutOfBoundsException(); - } - else if (len == 0) { - return; - } - else { - int flush = syncFlush ? JZlib.Z_SYNC_FLUSH : JZlib.Z_NO_FLUSH; - deflater.setInput(b, off, len, true); - while (deflater.avail_in>0) { - int err = deflate(flush); - if (err == JZlib.Z_STREAM_END) - break; - } - } - } - - public void finish() throws IOException { - while (!deflater.finished()) { - deflate(JZlib.Z_FINISH); - } - } - - public void close() throws IOException { - if (!closed) { - finish(); - if (mydeflater){ - deflater.end(); - } - if(close_out) - out.close(); - closed = true; - } - } - - protected int deflate(int flush) throws IOException { - deflater.setOutput(buffer, 0, buffer.length); - int err = deflater.deflate(flush); - switch(err) { - case JZlib.Z_OK: - case JZlib.Z_STREAM_END: - break; - case JZlib.Z_BUF_ERROR: - if(deflater.avail_in<=0 && flush!=JZlib.Z_FINISH){ - // flush() without any data - break; - } - default: - throw new IOException("failed to deflate: error="+err+" avail_out="+deflater.avail_out); - } - int len = deflater.next_out_index; - if (len > 0) { - out.write(buffer, 0, len); - } - return err; - } - - public void flush() throws IOException { - if (syncFlush && !deflater.finished()) { - while (true) { - int err = deflate(JZlib.Z_SYNC_FLUSH); - if (deflater.next_out_index < buffer.length) - break; - if (err == JZlib.Z_STREAM_END) - break; - } - } - out.flush(); - } - - public long getTotalIn() { - return deflater.getTotalIn(); - } - - public long getTotalOut() { - return deflater.getTotalOut(); - } - - public void setSyncFlush(boolean syncFlush){ - this.syncFlush = syncFlush; - } - - public boolean getSyncFlush(){ - return this.syncFlush; - } - - public Deflater getDeflater(){ - return deflater; - } -}
--- a/src/com/jcraft/jzlib/GZIPException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -public class GZIPException extends java.io.IOException { - public GZIPException() { - super(); - } - public GZIPException(String s) { - super(s); - } -}
--- a/src/com/jcraft/jzlib/GZIPHeader.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,214 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -import java.io.UnsupportedEncodingException; - -/** - * @see "http://www.ietf.org/rfc/rfc1952.txt" - */ -public class GZIPHeader implements Cloneable { - - public static final byte OS_MSDOS = (byte) 0x00; - public static final byte OS_AMIGA = (byte) 0x01; - public static final byte OS_VMS = (byte) 0x02; - public static final byte OS_UNIX = (byte) 0x03; - public static final byte OS_ATARI = (byte) 0x05; - public static final byte OS_OS2 = (byte) 0x06; - public static final byte OS_MACOS = (byte) 0x07; - public static final byte OS_TOPS20 = (byte) 0x0a; - public static final byte OS_WIN32 = (byte) 0x0b; - public static final byte OS_VMCMS = (byte) 0x04; - public static final byte OS_ZSYSTEM = (byte) 0x08; - public static final byte OS_CPM = (byte) 0x09; - public static final byte OS_QDOS = (byte) 0x0c; - public static final byte OS_RISCOS = (byte) 0x0d; - public static final byte OS_UNKNOWN = (byte) 0xff; - - boolean text = false; - private boolean fhcrc = false; - long time; - int xflags; - int os = 255; - byte[] extra; - byte[] name; - byte[] comment; - int hcrc; - long crc; - boolean done = false; - long mtime = 0; - - public void setModifiedTime(long mtime) { - this.mtime = mtime; - } - - public long getModifiedTime() { - return mtime; - } - - public void setOS(int os) { - if((0<=os && os <=13) || os==255) - this.os=os; - else - throw new IllegalArgumentException("os: "+os); - } - - public int getOS(){ - return os; - } - - public void setName(String name) { - try{ - this.name=name.getBytes("ISO-8859-1"); - } - catch(UnsupportedEncodingException e){ - throw new IllegalArgumentException("name must be in ISO-8859-1 "+name); - } - } - - public String getName(){ - if(name==null) return ""; - try { - return new String(name, "ISO-8859-1"); - } - catch (UnsupportedEncodingException e) { - throw new InternalError(e.toString()); - } - } - - public void setComment(String comment) { - try{ - this.comment=comment.getBytes("ISO-8859-1"); - } - catch(UnsupportedEncodingException e){ - throw new IllegalArgumentException("comment must be in ISO-8859-1 "+name); - } - } - - public String getComment(){ - if(comment==null) return ""; - try { - return new String(comment, "ISO-8859-1"); - } - catch (UnsupportedEncodingException e) { - throw new InternalError(e.toString()); - } - } - - public void setCRC(long crc){ - this.crc = crc; - } - - public long getCRC(){ - return crc; - } - - void put(Deflate d){ - int flag = 0; - if(text){ - flag |= 1; // FTEXT - } - if(fhcrc){ - flag |= 2; // FHCRC - } - if(extra!=null){ - flag |= 4; // FEXTRA - } - if(name!=null){ - flag |= 8; // FNAME - } - if(comment!=null){ - flag |= 16; // FCOMMENT - } - int xfl = 0; - if(d.level == JZlib.Z_BEST_SPEED){ - xfl |= 4; - } - else if (d.level == JZlib.Z_BEST_COMPRESSION){ - xfl |= 2; - } - - d.put_short((short)0x8b1f); // ID1 ID2 - d.put_byte((byte)8); // CM(Compression Method) - d.put_byte((byte)flag); - d.put_byte((byte)mtime); - d.put_byte((byte)(mtime>>8)); - d.put_byte((byte)(mtime>>16)); - d.put_byte((byte)(mtime>>24)); - d.put_byte((byte)xfl); - d.put_byte((byte)os); - - if(extra!=null){ - d.put_byte((byte)extra.length); - d.put_byte((byte)(extra.length>>8)); - d.put_byte(extra, 0, extra.length); - } - - if(name!=null){ - d.put_byte(name, 0, name.length); - d.put_byte((byte)0); - } - - if(comment!=null){ - d.put_byte(comment, 0, comment.length); - d.put_byte((byte)0); - } - } - - @Override - public Object clone() throws CloneNotSupportedException { - GZIPHeader gheader = (GZIPHeader)super.clone(); - byte[] tmp; - if(gheader.extra!=null){ - tmp=new byte[gheader.extra.length]; - System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length); - gheader.extra = tmp; - } - - if(gheader.name!=null){ - tmp=new byte[gheader.name.length]; - System.arraycopy(gheader.name, 0, tmp, 0, tmp.length); - gheader.name = tmp; - } - - if(gheader.comment!=null){ - tmp=new byte[gheader.comment.length]; - System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length); - gheader.comment = tmp; - } - - return gheader; - } -}
--- a/src/com/jcraft/jzlib/GZIPInputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jcraft.jzlib; -import java.io.*; - -public class GZIPInputStream extends InflaterInputStream { - - public GZIPInputStream(InputStream in) throws IOException { - this(in, DEFAULT_BUFSIZE, true); - } - - public GZIPInputStream(InputStream in, - int size, - boolean close_in) throws IOException { - this(in, new Inflater(15+16), size, close_in); - myinflater = true; - } - - public GZIPInputStream(InputStream in, - Inflater inflater, - int size, - boolean close_in) throws IOException { - super(in, inflater, size, close_in); - } - - public long getModifiedtime() { - return inflater.istate.getGZIPHeader().getModifiedTime(); - } - - public int getOS() { - return inflater.istate.getGZIPHeader().getOS(); - } - - public String getName() { - return inflater.istate.getGZIPHeader().getName(); - } - - public String getComment() { - return inflater.istate.getGZIPHeader().getComment(); - } - - public long getCRC() throws GZIPException { - if(inflater.istate.mode != 12 /*DONE*/) - throw new GZIPException("checksum is not calculated yet."); - return inflater.istate.getGZIPHeader().getCRC(); - } - - public void readHeader() throws IOException { - - byte[] empty = "".getBytes(); - inflater.setOutput(empty, 0, 0); - inflater.setInput(empty, 0, 0, false); - - byte[] b = new byte[10]; - - int n = fill(b); - if(n!=10){ - if(n>0){ - inflater.setInput(b, 0, n, false); - //inflater.next_in_index = n; - inflater.next_in_index = 0; - inflater.avail_in = n; - } - throw new IOException("no input"); - } - - inflater.setInput(b, 0, n, false); - - byte[] b1 = new byte[1]; - do{ - if(inflater.avail_in<=0){ - int i = in.read(b1); - if(i<=0) - throw new IOException("no input"); - inflater.setInput(b1, 0, 1, true); - } - - int err = inflater.inflate(JZlib.Z_NO_FLUSH); - - if(err!=0/*Z_OK*/){ - int len = 2048-inflater.next_in.length; - if(len>0){ - byte[] tmp = new byte[len]; - n = fill(tmp); - if(n>0){ - inflater.avail_in += inflater.next_in_index; - inflater.next_in_index = 0; - inflater.setInput(tmp, 0, n, true); - } - } - //inflater.next_in_index = inflater.next_in.length; - inflater.avail_in += inflater.next_in_index; - inflater.next_in_index = 0; - throw new IOException(inflater.msg); - } - } - while(inflater.istate.inParsingHeader()); - } - - private int fill(byte[] buf) { - int len = buf.length; - int n = 0; - do{ - int i = -1; - try { - i = in.read(buf, n, buf.length - n); - } - catch(IOException e){ - } - if(i == -1){ - break; - } - n+=i; - } - while(n<len); - return n; - } -} \ No newline at end of file
--- a/src/com/jcraft/jzlib/GZIPOutputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jcraft.jzlib; -import java.io.*; - -public class GZIPOutputStream extends DeflaterOutputStream { - - public GZIPOutputStream(OutputStream out) throws IOException { - this(out, DEFAULT_BUFSIZE); - } - - public GZIPOutputStream(OutputStream out, int size) throws IOException { - this(out, size, true); - } - - public GZIPOutputStream(OutputStream out, - int size, - boolean close_out) throws IOException { - this(out, - new Deflater(JZlib.Z_DEFAULT_COMPRESSION, 15+16), - size, close_out); - mydeflater=true; - } - - public GZIPOutputStream(OutputStream out, - Deflater deflater, - int size, - boolean close_out) throws IOException{ - super(out, deflater, size, close_out); - } - - - private void check() throws GZIPException { - if(deflater.dstate.status != 42 /*INIT_STATUS*/) - throw new GZIPException("header is already written."); - } - - public void setModifiedTime(long mtime) throws GZIPException { - check(); - deflater.dstate.getGZIPHeader().setModifiedTime(mtime); - } - - public void setOS(int os) throws GZIPException { - check(); - deflater.dstate.getGZIPHeader().setOS(os); - } - - public void setName(String name) throws GZIPException { - check(); - deflater.dstate.getGZIPHeader().setName(name); - } - - public void setComment(String comment) throws GZIPException { - check(); - deflater.dstate.getGZIPHeader().setComment(comment); - } - - public long getCRC() throws GZIPException { - if(deflater.dstate.status != 666 /*FINISH_STATE*/) - throw new GZIPException("checksum is not calculated yet."); - return deflater.dstate.getGZIPHeader().getCRC(); - } -}
--- a/src/com/jcraft/jzlib/InfBlocks.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,614 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final class InfBlocks{ - static final private int MANY=1440; - - // And'ing with mask[n] masks the lower n bits - static final private int[] inflate_mask = { - 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, - 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, - 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, - 0x00007fff, 0x0000ffff - }; - - // Table for deflate from PKZIP's appnote.txt. - static final int[] border = { // Order of the bit length code lengths - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - }; - - static final private int Z_OK=0; - static final private int Z_STREAM_END=1; - static final private int Z_NEED_DICT=2; - static final private int Z_ERRNO=-1; - static final private int Z_STREAM_ERROR=-2; - static final private int Z_DATA_ERROR=-3; - static final private int Z_MEM_ERROR=-4; - static final private int Z_BUF_ERROR=-5; - static final private int Z_VERSION_ERROR=-6; - - static final private int TYPE=0; // get type bits (3, including end bit) - static final private int LENS=1; // get lengths for stored - static final private int STORED=2;// processing stored block - static final private int TABLE=3; // get table lengths - static final private int BTREE=4; // get bit lengths tree for a dynamic block - static final private int DTREE=5; // get length, distance trees for a dynamic block - static final private int CODES=6; // processing fixed or dynamic block - static final private int DRY=7; // output remaining window bytes - static final private int DONE=8; // finished last block, done - static final private int BAD=9; // ot a data error--stuck here - - int mode; // current inflate_block mode - - int left; // if STORED, bytes left to copy - - int table; // table lengths (14 bits) - int index; // index into blens (or border) - int[] blens; // bit lengths of codes - int[] bb=new int[1]; // bit length tree depth - int[] tb=new int[1]; // bit length decoding tree - - int[] bl=new int[1]; - int[] bd=new int[1]; - - int[][] tl=new int[1][]; - int[][] td=new int[1][]; - int[] tli=new int[1]; // tl_index - int[] tdi=new int[1]; // td_index - - private final InfCodes codes; // if CODES, current state - - int last; // true if this block is the last block - - // mode independent information - int bitk; // bits in bit buffer - int bitb; // bit buffer - int[] hufts; // single malloc for tree space - byte[] window; // sliding window - int end; // one byte after sliding window - int read; // window read pointer - int write; // window write pointer - private boolean check; - - private final InfTree inftree=new InfTree(); - - private final ZStream z; - - InfBlocks(ZStream z, int w){ - this.z=z; - this.codes=new InfCodes(this.z, this); - hufts=new int[MANY*3]; - window=new byte[w]; - end=w; - this.check = (z.istate.wrap==0) ? false : true; - mode = TYPE; - reset(); - } - - void reset(){ - if(mode==BTREE || mode==DTREE){ - } - if(mode==CODES){ - codes.free(z); - } - mode=TYPE; - bitk=0; - bitb=0; - read=write=0; - if(check){ - z.adler.reset(); - } - } - - int proc(int r){ - int t; // temporary storage - int b; // bit buffer - int k; // bits in bit buffer - int p; // input data pointer - int n; // bytes available there - int q; // output window write pointer - int m; // bytes to end of window or read pointer - - // copy input/output information to locals (UPDATE macro restores) - {p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;} - {q=write;m=(int)(q<read?read-q-1:end-q);} - - // process input based on current state - while(true){ - switch (mode){ - case TYPE: - - while(k<(3)){ - if(n!=0){ - r=Z_OK; - } - else{ - bitb=b; bitk=k; - z.avail_in=n; - z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - }; - n--; - b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - t = (int)(b & 7); - last = t & 1; - - switch (t >>> 1){ - case 0: // stored - {b>>>=(3);k-=(3);} - t = k & 7; // go to byte boundary - - {b>>>=(t);k-=(t);} - mode = LENS; // get length of stored block - break; - case 1: // fixed - InfTree.inflate_trees_fixed(bl, bd, tl, td, z); - codes.init(bl[0], bd[0], tl[0], 0, td[0], 0); - - {b>>>=(3);k-=(3);} - - mode = CODES; - break; - case 2: // dynamic - - {b>>>=(3);k-=(3);} - - mode = TABLE; - break; - case 3: // illegal - - {b>>>=(3);k-=(3);} - mode = BAD; - z.msg = "invalid block type"; - r = Z_DATA_ERROR; - - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - break; - case LENS: - - while(k<(32)){ - if(n!=0){ - r=Z_OK; - } - else{ - bitb=b; bitk=k; - z.avail_in=n; - z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - }; - n--; - b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - - if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){ - mode = BAD; - z.msg = "invalid stored block lengths"; - r = Z_DATA_ERROR; - - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - left = (b & 0xffff); - b = k = 0; // dump bits - mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE); - break; - case STORED: - if (n == 0){ - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - - if(m==0){ - if(q==end&&read!=0){ - q=0; m=(int)(q<read?read-q-1:end-q); - } - if(m==0){ - write=q; - r=inflate_flush(r); - q=write;m=(int)(q<read?read-q-1:end-q); - if(q==end&&read!=0){ - q=0; m=(int)(q<read?read-q-1:end-q); - } - if(m==0){ - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - } - } - r=Z_OK; - - t = left; - if(t>n) t = n; - if(t>m) t = m; - System.arraycopy(z.next_in, p, window, q, t); - p += t; n -= t; - q += t; m -= t; - if ((left -= t) != 0) - break; - mode = last!=0 ? DRY : TYPE; - break; - case TABLE: - - while(k<(14)){ - if(n!=0){ - r=Z_OK; - } - else{ - bitb=b; bitk=k; - z.avail_in=n; - z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - }; - n--; - b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - - table = t = (b & 0x3fff); - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - mode = BAD; - z.msg = "too many length or distance symbols"; - r = Z_DATA_ERROR; - - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if(blens==null || blens.length<t){ - blens=new int[t]; - } - else{ - for(int i=0; i<t; i++){blens[i]=0;} - } - - {b>>>=(14);k-=(14);} - - index = 0; - mode = BTREE; - case BTREE: - while (index < 4 + (table >>> 10)){ - while(k<(3)){ - if(n!=0){ - r=Z_OK; - } - else{ - bitb=b; bitk=k; - z.avail_in=n; - z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - }; - n--; - b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - - blens[border[index++]] = b&7; - - {b>>>=(3);k-=(3);} - } - - while(index < 19){ - blens[border[index++]] = 0; - } - - bb[0] = 7; - t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z); - if (t != Z_OK){ - r = t; - if (r == Z_DATA_ERROR){ - blens=null; - mode = BAD; - } - - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - - index = 0; - mode = DTREE; - case DTREE: - while (true){ - t = table; - if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){ - break; - } - - int[] h; - int i, j, c; - - t = bb[0]; - - while(k<(t)){ - if(n!=0){ - r=Z_OK; - } - else{ - bitb=b; bitk=k; - z.avail_in=n; - z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - }; - n--; - b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - - if(tb[0]==-1){ - //System.err.println("null..."); - } - - t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1]; - c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2]; - - if (c < 16){ - b>>>=(t);k-=(t); - blens[index++] = c; - } - else { // c == 16..18 - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - - while(k<(t+i)){ - if(n!=0){ - r=Z_OK; - } - else{ - bitb=b; bitk=k; - z.avail_in=n; - z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - }; - n--; - b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - - b>>>=(t);k-=(t); - - j += (b & inflate_mask[i]); - - b>>>=(i);k-=(i); - - i = index; - t = table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)){ - blens=null; - mode = BAD; - z.msg = "invalid bit length repeat"; - r = Z_DATA_ERROR; - - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - - c = c == 16 ? blens[i-1] : 0; - do{ - blens[i++] = c; - } - while (--j!=0); - index = i; - } - } - - tb[0]=-1; - { - bl[0] = 9; // must be <= 9 for lookahead assumptions - bd[0] = 6; // must be <= 9 for lookahead assumptions - t = table; - t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), - 1 + ((t >> 5) & 0x1f), - blens, bl, bd, tli, tdi, hufts, z); - - if (t != Z_OK){ - if (t == Z_DATA_ERROR){ - blens=null; - mode = BAD; - } - r = t; - - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]); - } - mode = CODES; - case CODES: - bitb=b; bitk=k; - z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - - if ((r = codes.proc(r)) != Z_STREAM_END){ - return inflate_flush(r); - } - r = Z_OK; - codes.free(z); - - p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk; - q=write;m=(int)(q<read?read-q-1:end-q); - - if (last==0){ - mode = TYPE; - break; - } - mode = DRY; - case DRY: - write=q; - r=inflate_flush(r); - q=write; m=(int)(q<read?read-q-1:end-q); - if (read != write){ - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - mode = DONE; - case DONE: - r = Z_STREAM_END; - - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - case BAD: - r = Z_DATA_ERROR; - - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - - default: - r = Z_STREAM_ERROR; - - bitb=b; bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - write=q; - return inflate_flush(r); - } - } - } - - void free(){ - reset(); - window=null; - hufts=null; - //ZFREE(z, s); - } - - void set_dictionary(byte[] d, int start, int n){ - System.arraycopy(d, start, window, 0, n); - read = write = n; - } - - // Returns true if inflate is currently at the end of a block generated - // by Z_SYNC_FLUSH or Z_FULL_FLUSH. - int sync_point(){ - return mode == LENS ? 1 : 0; - } - - // copy as much as possible from the sliding window to the output area - int inflate_flush(int r){ - int n; - int p; - int q; - - // local copies of source and destination pointers - p = z.next_out_index; - q = read; - - // compute number of bytes to copy as far as end of window - n = (int)((q <= write ? write : end) - q); - if(n > z.avail_out) n = z.avail_out; - if(n!=0 && r == Z_BUF_ERROR) r = Z_OK; - - // update counters - z.avail_out -= n; - z.total_out += n; - - // update check information - if(check && n>0){ - z.adler.update(window, q, n); - } - - // copy as far as end of window - System.arraycopy(window, q, z.next_out, p, n); - p += n; - q += n; - - // see if more to copy at beginning of window - if (q == end){ - // wrap pointers - q = 0; - if (write == end) - write = 0; - - // compute bytes to copy - n = write - q; - if (n > z.avail_out) n = z.avail_out; - if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; - - // update counters - z.avail_out -= n; - z.total_out += n; - - // update check information - if(check && n>0){ - z.adler.update(window, q, n); - } - - // copy - System.arraycopy(window, q, z.next_out, p, n); - p += n; - q += n; - } - - // update pointers - z.next_out_index = p; - read = q; - - // done - return r; - } -}
--- a/src/com/jcraft/jzlib/InfCodes.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,610 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final class InfCodes{ - - static final private int[] inflate_mask = { - 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, - 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, - 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, - 0x00007fff, 0x0000ffff - }; - - static final private int Z_OK=0; - static final private int Z_STREAM_END=1; - static final private int Z_NEED_DICT=2; - static final private int Z_ERRNO=-1; - static final private int Z_STREAM_ERROR=-2; - static final private int Z_DATA_ERROR=-3; - static final private int Z_MEM_ERROR=-4; - static final private int Z_BUF_ERROR=-5; - static final private int Z_VERSION_ERROR=-6; - - // waiting for "i:"=input, - // "o:"=output, - // "x:"=nothing - static final private int START=0; // x: set up for LEN - static final private int LEN=1; // i: get length/literal/eob next - static final private int LENEXT=2; // i: getting length extra (have base) - static final private int DIST=3; // i: get distance next - static final private int DISTEXT=4;// i: getting distance extra - static final private int COPY=5; // o: copying bytes in window, waiting for space - static final private int LIT=6; // o: got literal, waiting for output space - static final private int WASH=7; // o: got eob, possibly still output waiting - static final private int END=8; // x: got eob and all data flushed - static final private int BADCODE=9;// x: got error - - int mode; // current inflate_codes mode - - // mode dependent information - int len; - - int[] tree; // pointer into tree - int tree_index=0; - int need; // bits needed - - int lit; - - // if EXT or COPY, where and how much - int get; // bits to get for extra - int dist; // distance back to copy from - - byte lbits; // ltree bits decoded per branch - byte dbits; // dtree bits decoder per branch - int[] ltree; // literal/length/eob tree - int ltree_index; // literal/length/eob tree - int[] dtree; // distance tree - int dtree_index; // distance tree - - private final ZStream z; - private final InfBlocks s; - InfCodes(ZStream z, InfBlocks s){ - this.z=z; - this.s=s; - } - - void init(int bl, int bd, - int[] tl, int tl_index, - int[] td, int td_index){ - mode=START; - lbits=(byte)bl; - dbits=(byte)bd; - ltree=tl; - ltree_index=tl_index; - dtree = td; - dtree_index=td_index; - tree=null; - } - - int proc(int r){ - int j; // temporary storage - int[] t; // temporary pointer - int tindex; // temporary pointer - int e; // extra bits or operation - int b=0; // bit buffer - int k=0; // bits in bit buffer - int p=0; // input data pointer - int n; // bytes available there - int q; // output window write pointer - int m; // bytes to end of window or read pointer - int f; // pointer to copy strings from - - // copy input/output information to locals (UPDATE macro restores) - p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; - q=s.write;m=q<s.read?s.read-q-1:s.end-q; - - // process input and output based on current state - while (true){ - switch (mode){ - // waiting for "i:"=input, "o:"=output, "x:"=nothing - case START: // x: set up for LEN - if (m >= 258 && n >= 10){ - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - r = inflate_fast(lbits, dbits, - ltree, ltree_index, - dtree, dtree_index, - s, z); - - p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; - q=s.write;m=q<s.read?s.read-q-1:s.end-q; - - if (r != Z_OK){ - mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } - need = lbits; - tree = ltree; - tree_index=ltree_index; - - mode = LEN; - case LEN: // i: get length/literal/eob next - j = need; - - while(k<(j)){ - if(n!=0)r=Z_OK; - else{ - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - } - n--; - b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - - tindex=(tree_index+(b&inflate_mask[j]))*3; - - b>>>=(tree[tindex+1]); - k-=(tree[tindex+1]); - - e=tree[tindex]; - - if(e == 0){ // literal - lit = tree[tindex+2]; - mode = LIT; - break; - } - if((e & 16)!=0 ){ // length - get = e & 15; - len = tree[tindex+2]; - mode = LENEXT; - break; - } - if ((e & 64) == 0){ // next table - need = e; - tree_index = tindex/3+tree[tindex+2]; - break; - } - if ((e & 32)!=0){ // end of block - mode = WASH; - break; - } - mode = BADCODE; // invalid code - z.msg = "invalid literal/length code"; - r = Z_DATA_ERROR; - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - - case LENEXT: // i: getting length extra (have base) - j = get; - - while(k<(j)){ - if(n!=0)r=Z_OK; - else{ - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - } - n--; b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - - len += (b & inflate_mask[j]); - - b>>=j; - k-=j; - - need = dbits; - tree = dtree; - tree_index=dtree_index; - mode = DIST; - case DIST: // i: get distance next - j = need; - - while(k<(j)){ - if(n!=0)r=Z_OK; - else{ - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - } - n--; b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - - tindex=(tree_index+(b & inflate_mask[j]))*3; - - b>>=tree[tindex+1]; - k-=tree[tindex+1]; - - e = (tree[tindex]); - if((e & 16)!=0){ // distance - get = e & 15; - dist = tree[tindex+2]; - mode = DISTEXT; - break; - } - if ((e & 64) == 0){ // next table - need = e; - tree_index = tindex/3 + tree[tindex+2]; - break; - } - mode = BADCODE; // invalid code - z.msg = "invalid distance code"; - r = Z_DATA_ERROR; - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - - case DISTEXT: // i: getting distance extra - j = get; - - while(k<(j)){ - if(n!=0)r=Z_OK; - else{ - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - } - n--; b|=(z.next_in[p++]&0xff)<<k; - k+=8; - } - - dist += (b & inflate_mask[j]); - - b>>=j; - k-=j; - - mode = COPY; - case COPY: // o: copying bytes in window, waiting for space - f = q - dist; - while(f < 0){ // modulo window size-"while" instead - f += s.end; // of "if" handles invalid distances - } - while (len!=0){ - - if(m==0){ - if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;} - if(m==0){ - s.write=q; r=s.inflate_flush(r); - q=s.write;m=q<s.read?s.read-q-1:s.end-q; - - if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;} - - if(m==0){ - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - } - } - } - - s.window[q++]=s.window[f++]; m--; - - if (f == s.end) - f = 0; - len--; - } - mode = START; - break; - case LIT: // o: got literal, waiting for output space - if(m==0){ - if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;} - if(m==0){ - s.write=q; r=s.inflate_flush(r); - q=s.write;m=q<s.read?s.read-q-1:s.end-q; - - if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;} - if(m==0){ - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - } - } - } - r=Z_OK; - - s.window[q++]=(byte)lit; m--; - - mode = START; - break; - case WASH: // o: got eob, possibly more output - if (k > 7){ // return unused byte, if any - k -= 8; - n++; - p--; // can always return one - } - - s.write=q; r=s.inflate_flush(r); - q=s.write;m=q<s.read?s.read-q-1:s.end-q; - - if (s.read != s.write){ - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - } - mode = END; - case END: - r = Z_STREAM_END; - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - - case BADCODE: // x: got error - - r = Z_DATA_ERROR; - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - - default: - r = Z_STREAM_ERROR; - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - return s.inflate_flush(r); - } - } - } - - void free(ZStream z){ - // ZFREE(z, c); - } - - // Called with number of bytes left to write in window at least 258 - // (the maximum string length) and number of input bytes available - // at least ten. The ten bytes are six bytes for the longest length/ - // distance pair plus four bytes for overloading the bit buffer. - - int inflate_fast(int bl, int bd, - int[] tl, int tl_index, - int[] td, int td_index, - InfBlocks s, ZStream z){ - int t; // temporary pointer - int[] tp; // temporary pointer - int tp_index; // temporary pointer - int e; // extra bits or operation - int b; // bit buffer - int k; // bits in bit buffer - int p; // input data pointer - int n; // bytes available there - int q; // output window write pointer - int m; // bytes to end of window or read pointer - int ml; // mask for literal/length tree - int md; // mask for distance tree - int c; // bytes to copy - int d; // distance back to copy from - int r; // copy source pointer - - int tp_index_t_3; // (tp_index+t)*3 - - // load input, output, bit values - p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; - q=s.write;m=q<s.read?s.read-q-1:s.end-q; - - // initialize masks - ml = inflate_mask[bl]; - md = inflate_mask[bd]; - - // do until not enough input or output space for fast loop - do { // assume called with m >= 258 && n >= 10 - // get literal/length code - while(k<(20)){ // max bits for literal/length code - n--; - b|=(z.next_in[p++]&0xff)<<k;k+=8; - } - - t= b&ml; - tp=tl; - tp_index=tl_index; - tp_index_t_3=(tp_index+t)*3; - if ((e = tp[tp_index_t_3]) == 0){ - b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); - - s.window[q++] = (byte)tp[tp_index_t_3+2]; - m--; - continue; - } - do { - - b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); - - if((e&16)!=0){ - e &= 15; - c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]); - - b>>=e; k-=e; - - // decode distance base of block to copy - while(k<(15)){ // max bits for distance code - n--; - b|=(z.next_in[p++]&0xff)<<k;k+=8; - } - - t= b&md; - tp=td; - tp_index=td_index; - tp_index_t_3=(tp_index+t)*3; - e = tp[tp_index_t_3]; - - do { - - b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); - - if((e&16)!=0){ - // get extra bits to add to distance base - e &= 15; - while(k<(e)){ // get extra bits (up to 13) - n--; - b|=(z.next_in[p++]&0xff)<<k;k+=8; - } - - d = tp[tp_index_t_3+2] + (b&inflate_mask[e]); - - b>>=(e); k-=(e); - - // do the copy - m -= c; - if (q >= d){ // offset before dest - // just copy - r=q-d; - if(q-r>0 && 2>(q-r)){ - s.window[q++]=s.window[r++]; // minimum count is three, - s.window[q++]=s.window[r++]; // so unroll loop a little - c-=2; - } - else{ - System.arraycopy(s.window, r, s.window, q, 2); - q+=2; r+=2; c-=2; - } - } - else{ // else offset after destination - r=q-d; - do{ - r+=s.end; // force pointer in window - }while(r<0); // covers invalid distances - e=s.end-r; - if(c>e){ // if source crosses, - c-=e; // wrapped copy - if(q-r>0 && e>(q-r)){ - do{s.window[q++] = s.window[r++];} - while(--e!=0); - } - else{ - System.arraycopy(s.window, r, s.window, q, e); - q+=e; r+=e; e=0; - } - r = 0; // copy rest from start of window - } - - } - - // copy all or what's left - if(q-r>0 && c>(q-r)){ - do{s.window[q++] = s.window[r++];} - while(--c!=0); - } - else{ - System.arraycopy(s.window, r, s.window, q, c); - q+=c; r+=c; c=0; - } - break; - } - else if((e&64)==0){ - t+=tp[tp_index_t_3+2]; - t+=(b&inflate_mask[e]); - tp_index_t_3=(tp_index+t)*3; - e=tp[tp_index_t_3]; - } - else{ - z.msg = "invalid distance code"; - - c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3; - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - - return Z_DATA_ERROR; - } - } - while(true); - break; - } - - if((e&64)==0){ - t+=tp[tp_index_t_3+2]; - t+=(b&inflate_mask[e]); - tp_index_t_3=(tp_index+t)*3; - if((e=tp[tp_index_t_3])==0){ - - b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); - - s.window[q++]=(byte)tp[tp_index_t_3+2]; - m--; - break; - } - } - else if((e&32)!=0){ - - c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3; - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - - return Z_STREAM_END; - } - else{ - z.msg="invalid literal/length code"; - - c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3; - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - - return Z_DATA_ERROR; - } - } - while(true); - } - while(m>=258 && n>= 10); - - // not enough input or output--restore pointers and return - c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3; - - s.bitb=b;s.bitk=k; - z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; - s.write=q; - - return Z_OK; - } -}
--- a/src/com/jcraft/jzlib/InfTree.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,518 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final class InfTree{ - - static final private int MANY=1440; - - static final private int Z_OK=0; - static final private int Z_STREAM_END=1; - static final private int Z_NEED_DICT=2; - static final private int Z_ERRNO=-1; - static final private int Z_STREAM_ERROR=-2; - static final private int Z_DATA_ERROR=-3; - static final private int Z_MEM_ERROR=-4; - static final private int Z_BUF_ERROR=-5; - static final private int Z_VERSION_ERROR=-6; - - static final int fixed_bl = 9; - static final int fixed_bd = 5; - - static final int[] fixed_tl = { - 96,7,256, 0,8,80, 0,8,16, 84,8,115, - 82,7,31, 0,8,112, 0,8,48, 0,9,192, - 80,7,10, 0,8,96, 0,8,32, 0,9,160, - 0,8,0, 0,8,128, 0,8,64, 0,9,224, - 80,7,6, 0,8,88, 0,8,24, 0,9,144, - 83,7,59, 0,8,120, 0,8,56, 0,9,208, - 81,7,17, 0,8,104, 0,8,40, 0,9,176, - 0,8,8, 0,8,136, 0,8,72, 0,9,240, - 80,7,4, 0,8,84, 0,8,20, 85,8,227, - 83,7,43, 0,8,116, 0,8,52, 0,9,200, - 81,7,13, 0,8,100, 0,8,36, 0,9,168, - 0,8,4, 0,8,132, 0,8,68, 0,9,232, - 80,7,8, 0,8,92, 0,8,28, 0,9,152, - 84,7,83, 0,8,124, 0,8,60, 0,9,216, - 82,7,23, 0,8,108, 0,8,44, 0,9,184, - 0,8,12, 0,8,140, 0,8,76, 0,9,248, - 80,7,3, 0,8,82, 0,8,18, 85,8,163, - 83,7,35, 0,8,114, 0,8,50, 0,9,196, - 81,7,11, 0,8,98, 0,8,34, 0,9,164, - 0,8,2, 0,8,130, 0,8,66, 0,9,228, - 80,7,7, 0,8,90, 0,8,26, 0,9,148, - 84,7,67, 0,8,122, 0,8,58, 0,9,212, - 82,7,19, 0,8,106, 0,8,42, 0,9,180, - 0,8,10, 0,8,138, 0,8,74, 0,9,244, - 80,7,5, 0,8,86, 0,8,22, 192,8,0, - 83,7,51, 0,8,118, 0,8,54, 0,9,204, - 81,7,15, 0,8,102, 0,8,38, 0,9,172, - 0,8,6, 0,8,134, 0,8,70, 0,9,236, - 80,7,9, 0,8,94, 0,8,30, 0,9,156, - 84,7,99, 0,8,126, 0,8,62, 0,9,220, - 82,7,27, 0,8,110, 0,8,46, 0,9,188, - 0,8,14, 0,8,142, 0,8,78, 0,9,252, - 96,7,256, 0,8,81, 0,8,17, 85,8,131, - 82,7,31, 0,8,113, 0,8,49, 0,9,194, - 80,7,10, 0,8,97, 0,8,33, 0,9,162, - 0,8,1, 0,8,129, 0,8,65, 0,9,226, - 80,7,6, 0,8,89, 0,8,25, 0,9,146, - 83,7,59, 0,8,121, 0,8,57, 0,9,210, - 81,7,17, 0,8,105, 0,8,41, 0,9,178, - 0,8,9, 0,8,137, 0,8,73, 0,9,242, - 80,7,4, 0,8,85, 0,8,21, 80,8,258, - 83,7,43, 0,8,117, 0,8,53, 0,9,202, - 81,7,13, 0,8,101, 0,8,37, 0,9,170, - 0,8,5, 0,8,133, 0,8,69, 0,9,234, - 80,7,8, 0,8,93, 0,8,29, 0,9,154, - 84,7,83, 0,8,125, 0,8,61, 0,9,218, - 82,7,23, 0,8,109, 0,8,45, 0,9,186, - 0,8,13, 0,8,141, 0,8,77, 0,9,250, - 80,7,3, 0,8,83, 0,8,19, 85,8,195, - 83,7,35, 0,8,115, 0,8,51, 0,9,198, - 81,7,11, 0,8,99, 0,8,35, 0,9,166, - 0,8,3, 0,8,131, 0,8,67, 0,9,230, - 80,7,7, 0,8,91, 0,8,27, 0,9,150, - 84,7,67, 0,8,123, 0,8,59, 0,9,214, - 82,7,19, 0,8,107, 0,8,43, 0,9,182, - 0,8,11, 0,8,139, 0,8,75, 0,9,246, - 80,7,5, 0,8,87, 0,8,23, 192,8,0, - 83,7,51, 0,8,119, 0,8,55, 0,9,206, - 81,7,15, 0,8,103, 0,8,39, 0,9,174, - 0,8,7, 0,8,135, 0,8,71, 0,9,238, - 80,7,9, 0,8,95, 0,8,31, 0,9,158, - 84,7,99, 0,8,127, 0,8,63, 0,9,222, - 82,7,27, 0,8,111, 0,8,47, 0,9,190, - 0,8,15, 0,8,143, 0,8,79, 0,9,254, - 96,7,256, 0,8,80, 0,8,16, 84,8,115, - 82,7,31, 0,8,112, 0,8,48, 0,9,193, - - 80,7,10, 0,8,96, 0,8,32, 0,9,161, - 0,8,0, 0,8,128, 0,8,64, 0,9,225, - 80,7,6, 0,8,88, 0,8,24, 0,9,145, - 83,7,59, 0,8,120, 0,8,56, 0,9,209, - 81,7,17, 0,8,104, 0,8,40, 0,9,177, - 0,8,8, 0,8,136, 0,8,72, 0,9,241, - 80,7,4, 0,8,84, 0,8,20, 85,8,227, - 83,7,43, 0,8,116, 0,8,52, 0,9,201, - 81,7,13, 0,8,100, 0,8,36, 0,9,169, - 0,8,4, 0,8,132, 0,8,68, 0,9,233, - 80,7,8, 0,8,92, 0,8,28, 0,9,153, - 84,7,83, 0,8,124, 0,8,60, 0,9,217, - 82,7,23, 0,8,108, 0,8,44, 0,9,185, - 0,8,12, 0,8,140, 0,8,76, 0,9,249, - 80,7,3, 0,8,82, 0,8,18, 85,8,163, - 83,7,35, 0,8,114, 0,8,50, 0,9,197, - 81,7,11, 0,8,98, 0,8,34, 0,9,165, - 0,8,2, 0,8,130, 0,8,66, 0,9,229, - 80,7,7, 0,8,90, 0,8,26, 0,9,149, - 84,7,67, 0,8,122, 0,8,58, 0,9,213, - 82,7,19, 0,8,106, 0,8,42, 0,9,181, - 0,8,10, 0,8,138, 0,8,74, 0,9,245, - 80,7,5, 0,8,86, 0,8,22, 192,8,0, - 83,7,51, 0,8,118, 0,8,54, 0,9,205, - 81,7,15, 0,8,102, 0,8,38, 0,9,173, - 0,8,6, 0,8,134, 0,8,70, 0,9,237, - 80,7,9, 0,8,94, 0,8,30, 0,9,157, - 84,7,99, 0,8,126, 0,8,62, 0,9,221, - 82,7,27, 0,8,110, 0,8,46, 0,9,189, - 0,8,14, 0,8,142, 0,8,78, 0,9,253, - 96,7,256, 0,8,81, 0,8,17, 85,8,131, - 82,7,31, 0,8,113, 0,8,49, 0,9,195, - 80,7,10, 0,8,97, 0,8,33, 0,9,163, - 0,8,1, 0,8,129, 0,8,65, 0,9,227, - 80,7,6, 0,8,89, 0,8,25, 0,9,147, - 83,7,59, 0,8,121, 0,8,57, 0,9,211, - 81,7,17, 0,8,105, 0,8,41, 0,9,179, - 0,8,9, 0,8,137, 0,8,73, 0,9,243, - 80,7,4, 0,8,85, 0,8,21, 80,8,258, - 83,7,43, 0,8,117, 0,8,53, 0,9,203, - 81,7,13, 0,8,101, 0,8,37, 0,9,171, - 0,8,5, 0,8,133, 0,8,69, 0,9,235, - 80,7,8, 0,8,93, 0,8,29, 0,9,155, - 84,7,83, 0,8,125, 0,8,61, 0,9,219, - 82,7,23, 0,8,109, 0,8,45, 0,9,187, - 0,8,13, 0,8,141, 0,8,77, 0,9,251, - 80,7,3, 0,8,83, 0,8,19, 85,8,195, - 83,7,35, 0,8,115, 0,8,51, 0,9,199, - 81,7,11, 0,8,99, 0,8,35, 0,9,167, - 0,8,3, 0,8,131, 0,8,67, 0,9,231, - 80,7,7, 0,8,91, 0,8,27, 0,9,151, - 84,7,67, 0,8,123, 0,8,59, 0,9,215, - 82,7,19, 0,8,107, 0,8,43, 0,9,183, - 0,8,11, 0,8,139, 0,8,75, 0,9,247, - 80,7,5, 0,8,87, 0,8,23, 192,8,0, - 83,7,51, 0,8,119, 0,8,55, 0,9,207, - 81,7,15, 0,8,103, 0,8,39, 0,9,175, - 0,8,7, 0,8,135, 0,8,71, 0,9,239, - 80,7,9, 0,8,95, 0,8,31, 0,9,159, - 84,7,99, 0,8,127, 0,8,63, 0,9,223, - 82,7,27, 0,8,111, 0,8,47, 0,9,191, - 0,8,15, 0,8,143, 0,8,79, 0,9,255 - }; - static final int[] fixed_td = { - 80,5,1, 87,5,257, 83,5,17, 91,5,4097, - 81,5,5, 89,5,1025, 85,5,65, 93,5,16385, - 80,5,3, 88,5,513, 84,5,33, 92,5,8193, - 82,5,9, 90,5,2049, 86,5,129, 192,5,24577, - 80,5,2, 87,5,385, 83,5,25, 91,5,6145, - 81,5,7, 89,5,1537, 85,5,97, 93,5,24577, - 80,5,4, 88,5,769, 84,5,49, 92,5,12289, - 82,5,13, 90,5,3073, 86,5,193, 192,5,24577 - }; - - // Tables for deflate from PKZIP's appnote.txt. - static final int[] cplens = { // Copy lengths for literal codes 257..285 - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 - }; - - // see note #13 above about 258 - static final int[] cplext = { // Extra bits for literal codes 257..285 - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid - }; - - static final int[] cpdist = { // Copy offsets for distance codes 0..29 - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577 - }; - - static final int[] cpdext = { // Extra bits for distance codes - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - - // If BMAX needs to be larger than 16, then h and x[] should be uLong. - static final int BMAX=15; // maximum bit length of any code - - int[] hn = null; // hufts used in space - int[] v = null; // work area for huft_build - int[] c = null; // bit length count table - int[] r = null; // table entry for structure assignment - int[] u = null; // table stack - int[] x = null; // bit offsets, then code stack - - private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX) - int bindex, - int n, // number of codes (assumed <= 288) - int s, // number of simple-valued codes (0..s-1) - int[] d, // list of base values for non-simple codes - int[] e, // list of extra bits for non-simple codes - int[] t, // result: starting table - int[] m, // maximum lookup bits, returns actual - int[] hp,// space for trees - int[] hn,// hufts used in space - int[] v // working area: values in order of bit length - ){ - // Given a list of code lengths and a maximum table size, make a set of - // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - // if the given code set is incomplete (the tables are still built in this - // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of - // lengths), or Z_MEM_ERROR if not enough memory. - - int a; // counter for codes of length k - int f; // i repeats in table every f entries - int g; // maximum code length - int h; // table level - int i; // counter, current code - int j; // counter - int k; // number of bits in current code - int l; // bits per table (returned in m) - int mask; // (1 << w) - 1, to avoid cc -O bug on HP - int p; // pointer into c[], b[], or v[] - int q; // points to current table - int w; // bits before this table == (l * h) - int xp; // pointer into x - int y; // number of dummy codes added - int z; // number of entries in current table - - // Generate counts for each bit length - - p = 0; i = n; - do { - c[b[bindex+p]]++; p++; i--; // assume all entries <= BMAX - }while(i!=0); - - if(c[0] == n){ // null input--all zero length codes - t[0] = -1; - m[0] = 0; - return Z_OK; - } - - // Find minimum and maximum length, bound *m by those - l = m[0]; - for (j = 1; j <= BMAX; j++) - if(c[j]!=0) break; - k = j; // minimum code length - if(l < j){ - l = j; - } - for (i = BMAX; i!=0; i--){ - if(c[i]!=0) break; - } - g = i; // maximum code length - if(l > i){ - l = i; - } - m[0] = l; - - // Adjust last length count to fill out codes, if needed - for (y = 1 << j; j < i; j++, y <<= 1){ - if ((y -= c[j]) < 0){ - return Z_DATA_ERROR; - } - } - if ((y -= c[i]) < 0){ - return Z_DATA_ERROR; - } - c[i] += y; - - // Generate starting offsets into the value table for each length - x[1] = j = 0; - p = 1; xp = 2; - while (--i!=0) { // note that i == g from above - x[xp] = (j += c[p]); - xp++; - p++; - } - - // Make a table of values in order of bit lengths - i = 0; p = 0; - do { - if ((j = b[bindex+p]) != 0){ - v[x[j]++] = i; - } - p++; - } - while (++i < n); - n = x[g]; // set n to length of v - - // Generate the Huffman codes and for each, make the table entries - x[0] = i = 0; // first Huffman code is zero - p = 0; // grab values in bit order - h = -1; // no tables yet--level -1 - w = -l; // bits decoded == (l * h) - u[0] = 0; // just to keep compilers happy - q = 0; // ditto - z = 0; // ditto - - // go through the bit lengths (k already is bits in shortest code) - for (; k <= g; k++){ - a = c[k]; - while (a--!=0){ - // here i is the Huffman code of length k bits for value *p - // make tables up to required level - while (k > w + l){ - h++; - w += l; // previous table always l bits - // compute minimum size table less than or equal to l bits - z = g - w; - z = (z > l) ? l : z; // table size upper limit - if((f=1<<(j=k-w))>a+1){ // try a k-w bit table - // too few codes for k-w bit table - f -= a + 1; // deduct codes from patterns left - xp = k; - if(j < z){ - while (++j < z){ // try smaller tables up to z bits - if((f <<= 1) <= c[++xp]) - break; // enough codes to use up j bits - f -= c[xp]; // else deduct codes from patterns - } - } - } - z = 1 << j; // table entries for j-bit table - - // allocate new table - if (hn[0] + z > MANY){ // (note: doesn't matter for fixed) - return Z_DATA_ERROR; // overflow of MANY - } - u[h] = q = /*hp+*/ hn[0]; // DEBUG - hn[0] += z; - - // connect to last table, if there is one - if(h!=0){ - x[h]=i; // save pattern for backing up - r[0]=(byte)j; // bits in this table - r[1]=(byte)l; // bits to dump before this table - j=i>>>(w - l); - r[2] = (int)(q - u[h-1] - j); // offset to this table - System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table - } - else{ - t[0] = q; // first table is returned result - } - } - - // set up table entry in r - r[1] = (byte)(k - w); - if (p >= n){ - r[0] = 128 + 64; // out of values--invalid code - } - else if (v[p] < s){ - r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block - r[2] = v[p++]; // simple code is just the value - } - else{ - r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists - r[2]=d[v[p++] - s]; - } - - // fill code-like entries with r - f=1<<(k-w); - for (j=i>>>w;j<z;j+=f){ - System.arraycopy(r, 0, hp, (q+j)*3, 3); - } - - // backwards increment the k-bit code i - for (j = 1 << (k - 1); (i & j)!=0; j >>>= 1){ - i ^= j; - } - i ^= j; - - // backup over finished tables - mask = (1 << w) - 1; // needed on HP, cc -O bug - while ((i & mask) != x[h]){ - h--; // don't need to update q - w -= l; - mask = (1 << w) - 1; - } - } - } - // Return Z_BUF_ERROR if we were given an incomplete table - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; - } - - int inflate_trees_bits(int[] c, // 19 code lengths - int[] bb, // bits tree desired/actual depth - int[] tb, // bits tree result - int[] hp, // space for trees - ZStream z // for messages - ){ - int result; - initWorkArea(19); - hn[0]=0; - result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); - - if(result == Z_DATA_ERROR){ - z.msg = "oversubscribed dynamic bit lengths tree"; - } - else if(result == Z_BUF_ERROR || bb[0] == 0){ - z.msg = "incomplete dynamic bit lengths tree"; - result = Z_DATA_ERROR; - } - return result; - } - - int inflate_trees_dynamic(int nl, // number of literal/length codes - int nd, // number of distance codes - int[] c, // that many (total) code lengths - int[] bl, // literal desired/actual bit depth - int[] bd, // distance desired/actual bit depth - int[] tl, // literal/length tree result - int[] td, // distance tree result - int[] hp, // space for trees - ZStream z // for messages - ){ - int result; - - // build literal/length tree - initWorkArea(288); - hn[0]=0; - result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); - if (result != Z_OK || bl[0] == 0){ - if(result == Z_DATA_ERROR){ - z.msg = "oversubscribed literal/length tree"; - } - else if (result != Z_MEM_ERROR){ - z.msg = "incomplete literal/length tree"; - result = Z_DATA_ERROR; - } - return result; - } - - // build distance tree - initWorkArea(288); - result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); - - if (result != Z_OK || (bd[0] == 0 && nl > 257)){ - if (result == Z_DATA_ERROR){ - z.msg = "oversubscribed distance tree"; - } - else if (result == Z_BUF_ERROR) { - z.msg = "incomplete distance tree"; - result = Z_DATA_ERROR; - } - else if (result != Z_MEM_ERROR){ - z.msg = "empty distance tree with lengths"; - result = Z_DATA_ERROR; - } - return result; - } - - return Z_OK; - } - - static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth - int[] bd, //distance desired/actual bit depth - int[][] tl,//literal/length tree result - int[][] td,//distance tree result - ZStream z //for memory allocation - ){ - bl[0]=fixed_bl; - bd[0]=fixed_bd; - tl[0]=fixed_tl; - td[0]=fixed_td; - return Z_OK; - } - - private void initWorkArea(int vsize){ - if(hn==null){ - hn=new int[1]; - v=new int[vsize]; - c=new int[BMAX+1]; - r=new int[3]; - u=new int[BMAX]; - x=new int[BMAX+1]; - } - if(v.length<vsize){ v=new int[vsize]; } - for(int i=0; i<vsize; i++){v[i]=0;} - for(int i=0; i<BMAX+1; i++){c[i]=0;} - for(int i=0; i<3; i++){r[i]=0;} - System.arraycopy(c, 0, u, 0, BMAX); - System.arraycopy(c, 0, x, 0, BMAX+1); - } -}
--- a/src/com/jcraft/jzlib/Inflate.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,751 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final class Inflate{ - - static final private int MAX_WBITS=15; // 32K LZ77 window - - // preset dictionary flag in zlib header - static final private int PRESET_DICT=0x20; - - static final int Z_NO_FLUSH=0; - static final int Z_PARTIAL_FLUSH=1; - static final int Z_SYNC_FLUSH=2; - static final int Z_FULL_FLUSH=3; - static final int Z_FINISH=4; - - static final private int Z_DEFLATED=8; - - static final private int Z_OK=0; - static final private int Z_STREAM_END=1; - static final private int Z_NEED_DICT=2; - static final private int Z_ERRNO=-1; - static final private int Z_STREAM_ERROR=-2; - static final private int Z_DATA_ERROR=-3; - static final private int Z_MEM_ERROR=-4; - static final private int Z_BUF_ERROR=-5; - static final private int Z_VERSION_ERROR=-6; - - static final private int METHOD=0; // waiting for method byte - static final private int FLAG=1; // waiting for flag byte - static final private int DICT4=2; // four dictionary check bytes to go - static final private int DICT3=3; // three dictionary check bytes to go - static final private int DICT2=4; // two dictionary check bytes to go - static final private int DICT1=5; // one dictionary check byte to go - static final private int DICT0=6; // waiting for inflateSetDictionary - static final private int BLOCKS=7; // decompressing blocks - static final private int CHECK4=8; // four check bytes to go - static final private int CHECK3=9; // three check bytes to go - static final private int CHECK2=10; // two check bytes to go - static final private int CHECK1=11; // one check byte to go - static final private int DONE=12; // finished check, done - static final private int BAD=13; // got an error--stay here - - static final private int HEAD=14; - static final private int LENGTH=15; - static final private int TIME=16; - static final private int OS=17; - static final private int EXLEN=18; - static final private int EXTRA=19; - static final private int NAME=20; - static final private int COMMENT=21; - static final private int HCRC=22; - static final private int FLAGS=23; - - static final int INFLATE_ANY=0x40000000; - - int mode; // current inflate mode - - // mode dependent information - int method; // if FLAGS, method byte - - // if CHECK, check values to compare - long was = -1; // computed check value - long need; // stream check value - - // if BAD, inflateSync's marker bytes count - int marker; - - // mode independent information - int wrap; // flag for no wrapper - // 0: no wrapper - // 1: zlib header - // 2: gzip header - // 4: auto detection - - int wbits; // log2(window size) (8..15, defaults to 15) - - InfBlocks blocks; // current inflate_blocks state - - private final ZStream z; - - private int flags; - - private int need_bytes = -1; - private byte[] crcbuf=new byte[4]; - - GZIPHeader gheader = null; - - int inflateReset(){ - if(z == null) return Z_STREAM_ERROR; - - z.total_in = z.total_out = 0; - z.msg = null; - this.mode = HEAD; - this.need_bytes = -1; - this.blocks.reset(); - return Z_OK; - } - - int inflateEnd(){ - if(blocks != null){ - blocks.free(); - } - return Z_OK; - } - - Inflate(ZStream z){ - this.z=z; - } - - int inflateInit(int w){ - z.msg = null; - blocks = null; - - // handle undocumented wrap option (no zlib header or check) - wrap = 0; - if(w < 0){ - w = - w; - } - else if((w&INFLATE_ANY) != 0){ - wrap = 4; - w &= ~INFLATE_ANY; - if(w < 48) - w &= 15; - } - else if((w & ~31) != 0) { // for example, DEF_WBITS + 32 - wrap = 4; // zlib and gzip wrapped data should be accepted. - w &= 15; - } - else { - wrap = (w >> 4) + 1; - if(w < 48) - w &= 15; - } - - if(w<8 ||w>15){ - inflateEnd(); - return Z_STREAM_ERROR; - } - if(blocks != null && wbits != w){ - blocks.free(); - blocks=null; - } - - // set window size - wbits=w; - - this.blocks=new InfBlocks(z, 1<<w); - - // reset state - inflateReset(); - - return Z_OK; - } - - int inflate(int f){ - int hold = 0; - - int r; - int b; - - if(z == null || z.next_in == null){ - if(f == Z_FINISH && this.mode==HEAD) - return Z_OK; - return Z_STREAM_ERROR; - } - - f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; - r = Z_BUF_ERROR; - while (true){ - - switch (this.mode){ - case HEAD: - if(wrap==0){ - this.mode = BLOCKS; - break; - } - - try { r=readBytes(2, r, f); } - catch(Return e){ return e.r; } - - if((wrap == 4 || (wrap&2)!=0) && - this.need == 0x8b1fL) { // gzip header - if(wrap == 4){ - wrap = 2; - } - z.adler=new CRC32(); - checksum(2, this.need); - - if(gheader==null) - gheader=new GZIPHeader(); - - this.mode = FLAGS; - break; - } - - if((wrap&2) != 0){ - this.mode = BAD; - z.msg = "incorrect header check"; - break; - } - - flags = 0; - - this.method = ((int)this.need)&0xff; - b=((int)(this.need>>8))&0xff; - - if(((wrap&1)==0 || // check if zlib header allowed - (((this.method << 8)+b) % 31)!=0) && - (this.method&0xf)!=Z_DEFLATED){ - if(wrap == 4){ - z.next_in_index -= 2; - z.avail_in += 2; - z.total_in -= 2; - wrap = 0; - this.mode = BLOCKS; - break; - } - this.mode = BAD; - z.msg = "incorrect header check"; - // since zlib 1.2, it is allowted to inflateSync for this case. - /* - this.marker = 5; // can't try inflateSync - */ - break; - } - - if((this.method&0xf)!=Z_DEFLATED){ - this.mode = BAD; - z.msg="unknown compression method"; - // since zlib 1.2, it is allowted to inflateSync for this case. - /* - this.marker = 5; // can't try inflateSync - */ - break; - } - - if(wrap == 4){ - wrap = 1; - } - - if((this.method>>4)+8>this.wbits){ - this.mode = BAD; - z.msg="invalid window size"; - // since zlib 1.2, it is allowted to inflateSync for this case. - /* - this.marker = 5; // can't try inflateSync - */ - break; - } - - z.adler=new Adler32(); - - if((b&PRESET_DICT)==0){ - this.mode = BLOCKS; - break; - } - this.mode = DICT4; - case DICT4: - - if(z.avail_in==0)return r;r=f; - - z.avail_in--; z.total_in++; - this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; - this.mode=DICT3; - case DICT3: - - if(z.avail_in==0)return r;r=f; - - z.avail_in--; z.total_in++; - this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; - this.mode=DICT2; - case DICT2: - - if(z.avail_in==0)return r;r=f; - - z.avail_in--; z.total_in++; - this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; - this.mode=DICT1; - case DICT1: - - if(z.avail_in==0)return r;r=f; - - z.avail_in--; z.total_in++; - this.need += (z.next_in[z.next_in_index++]&0xffL); - z.adler.reset(this.need); - this.mode = DICT0; - return Z_NEED_DICT; - case DICT0: - this.mode = BAD; - z.msg = "need dictionary"; - this.marker = 0; // can try inflateSync - return Z_STREAM_ERROR; - case BLOCKS: - r = this.blocks.proc(r); - if(r == Z_DATA_ERROR){ - this.mode = BAD; - this.marker = 0; // can try inflateSync - break; - } - if(r == Z_OK){ - r = f; - } - if(r != Z_STREAM_END){ - return r; - } - r = f; - this.was=z.adler.getValue(); - this.blocks.reset(); - if(this.wrap==0){ - this.mode=DONE; - break; - } - this.mode=CHECK4; - case CHECK4: - - if(z.avail_in==0)return r;r=f; - - z.avail_in--; z.total_in++; - this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; - this.mode=CHECK3; - case CHECK3: - - if(z.avail_in==0)return r;r=f; - - z.avail_in--; z.total_in++; - this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; - this.mode = CHECK2; - case CHECK2: - - if(z.avail_in==0)return r;r=f; - - z.avail_in--; z.total_in++; - this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; - this.mode = CHECK1; - case CHECK1: - - if(z.avail_in==0)return r;r=f; - - z.avail_in--; z.total_in++; - this.need+=(z.next_in[z.next_in_index++]&0xffL); - - if(flags!=0){ // gzip - this.need = ((this.need&0xff000000)>>24 | - (this.need&0x00ff0000)>>8 | - (this.need&0x0000ff00)<<8 | - (this.need&0x0000ffff)<<24)&0xffffffffL; - } - - if(((int)(this.was)) != ((int)(this.need))){ - z.msg = "incorrect data check"; - // chack is delayed - /* - this.mode = BAD; - this.marker = 5; // can't try inflateSync - break; - */ - } - else if(flags!=0 && gheader!=null){ - gheader.crc = this.need; - } - - this.mode = LENGTH; - case LENGTH: - if (wrap!=0 && flags!=0) { - - try { r=readBytes(4, r, f); } - catch(Return e){ return e.r; } - - if(z.msg!=null && z.msg.equals("incorrect data check")){ - this.mode = BAD; - this.marker = 5; // can't try inflateSync - break; - } - - if (this.need != (z.total_out & 0xffffffffL)) { - z.msg = "incorrect length check"; - this.mode = BAD; - break; - } - z.msg = null; - } - else { - if(z.msg!=null && z.msg.equals("incorrect data check")){ - this.mode = BAD; - this.marker = 5; // can't try inflateSync - break; - } - } - - this.mode = DONE; - case DONE: - return Z_STREAM_END; - case BAD: - return Z_DATA_ERROR; - - case FLAGS: - - try { r=readBytes(2, r, f); } - catch(Return e){ return e.r; } - - flags = ((int)this.need)&0xffff; - - if ((flags & 0xff) != Z_DEFLATED) { - z.msg = "unknown compression method"; - this.mode = BAD; - break; - } - if ((flags & 0xe000)!=0) { - z.msg = "unknown header flags set"; - this.mode = BAD; - break; - } - - if ((flags & 0x0200)!=0){ - checksum(2, this.need); - } - - this.mode = TIME; - - case TIME: - try { r=readBytes(4, r, f); } - catch(Return e){ return e.r; } - if(gheader!=null) - gheader.time = this.need; - if ((flags & 0x0200)!=0){ - checksum(4, this.need); - } - this.mode = OS; - case OS: - try { r=readBytes(2, r, f); } - catch(Return e){ return e.r; } - if(gheader!=null){ - gheader.xflags = ((int)this.need)&0xff; - gheader.os = (((int)this.need)>>8)&0xff; - } - if ((flags & 0x0200)!=0){ - checksum(2, this.need); - } - this.mode = EXLEN; - case EXLEN: - if ((flags & 0x0400)!=0) { - try { r=readBytes(2, r, f); } - catch(Return e){ return e.r; } - if(gheader!=null){ - gheader.extra = new byte[((int)this.need)&0xffff]; - } - if ((flags & 0x0200)!=0){ - checksum(2, this.need); - } - } - else if(gheader!=null){ - gheader.extra=null; - } - this.mode = EXTRA; - - case EXTRA: - if ((flags & 0x0400)!=0) { - try { - r=readBytes(r, f); - if(gheader!=null){ - byte[] foo = tmp_string.toByteArray(); - tmp_string=null; - if(foo.length == gheader.extra.length){ - System.arraycopy(foo, 0, gheader.extra, 0, foo.length); - } - else{ - z.msg = "bad extra field length"; - this.mode = BAD; - break; - } - } - } - catch(Return e){ return e.r; } - } - else if(gheader!=null){ - gheader.extra=null; - } - this.mode = NAME; - case NAME: - if ((flags & 0x0800)!=0) { - try { - r=readString(r, f); - if(gheader!=null){ - gheader.name=tmp_string.toByteArray(); - } - tmp_string=null; - } - catch(Return e){ return e.r; } - } - else if(gheader!=null){ - gheader.name=null; - } - this.mode = COMMENT; - case COMMENT: - if ((flags & 0x1000)!=0) { - try { - r=readString(r, f); - if(gheader!=null){ - gheader.comment=tmp_string.toByteArray(); - } - tmp_string=null; - } - catch(Return e){ return e.r; } - } - else if(gheader!=null){ - gheader.comment=null; - } - this.mode = HCRC; - case HCRC: - if ((flags & 0x0200)!=0) { - try { r=readBytes(2, r, f); } - catch(Return e){ return e.r; } - if(gheader!=null){ - gheader.hcrc=(int)(this.need&0xffff); - } - if(this.need != (z.adler.getValue()&0xffffL)){ - this.mode = BAD; - z.msg = "header crc mismatch"; - this.marker = 5; // can't try inflateSync - break; - } - } - z.adler = new CRC32(); - - this.mode = BLOCKS; - break; - default: - return Z_STREAM_ERROR; - } - } - } - - int inflateSetDictionary(byte[] dictionary, int dictLength){ - if(z==null || (this.mode != DICT0 && this.wrap != 0)){ - return Z_STREAM_ERROR; - } - - int index=0; - int length = dictLength; - - if(this.mode==DICT0){ - long adler_need=z.adler.getValue(); - z.adler.reset(); - z.adler.update(dictionary, 0, dictLength); - if(z.adler.getValue()!=adler_need){ - return Z_DATA_ERROR; - } - } - - z.adler.reset(); - - if(length >= (1<<this.wbits)){ - length = (1<<this.wbits)-1; - index=dictLength - length; - } - this.blocks.set_dictionary(dictionary, index, length); - this.mode = BLOCKS; - return Z_OK; - } - - static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff}; - - int inflateSync(){ - int n; // number of bytes to look at - int p; // pointer to bytes - int m; // number of marker bytes found in a row - long r, w; // temporaries to save total_in and total_out - - // set up - if(z == null) - return Z_STREAM_ERROR; - if(this.mode != BAD){ - this.mode = BAD; - this.marker = 0; - } - if((n=z.avail_in)==0) - return Z_BUF_ERROR; - - p=z.next_in_index; - m=this.marker; - // search - while (n!=0 && m < 4){ - if(z.next_in[p] == mark[m]){ - m++; - } - else if(z.next_in[p]!=0){ - m = 0; - } - else{ - m = 4 - m; - } - p++; n--; - } - - // restore - z.total_in += p-z.next_in_index; - z.next_in_index = p; - z.avail_in = n; - this.marker = m; - - // return no joy or set up to restart on a new block - if(m != 4){ - return Z_DATA_ERROR; - } - r=z.total_in; w=z.total_out; - inflateReset(); - z.total_in=r; z.total_out = w; - this.mode = BLOCKS; - - return Z_OK; - } - - // Returns true if inflate is currently at the end of a block generated - // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH - // but removes the length bytes of the resulting empty stored block. When - // decompressing, PPP checks that at the end of input packet, inflate is - // waiting for these length bytes. - int inflateSyncPoint(){ - if(z == null || this.blocks == null) - return Z_STREAM_ERROR; - return this.blocks.sync_point(); - } - - private int readBytes(int n, int r, int f) throws Return{ - if(need_bytes == -1){ - need_bytes=n; - this.need=0; - } - while(need_bytes>0){ - if(z.avail_in==0){ throw new Return(r); }; r=f; - z.avail_in--; z.total_in++; - this.need = this.need | - ((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8)); - need_bytes--; - } - if(n==2){ - this.need&=0xffffL; - } - else if(n==4) { - this.need&=0xffffffffL; - } - need_bytes=-1; - return r; - } - class Return extends Exception{ - int r; - Return(int r){this.r=r; } - } - - private java.io.ByteArrayOutputStream tmp_string = null; - private int readString(int r, int f) throws Return{ - if(tmp_string == null){ - tmp_string=new java.io.ByteArrayOutputStream(); - } - int b=0; - do { - if(z.avail_in==0){ throw new Return(r); }; r=f; - z.avail_in--; z.total_in++; - b = z.next_in[z.next_in_index]; - if(b!=0) tmp_string.write(z.next_in, z.next_in_index, 1); - z.adler.update(z.next_in, z.next_in_index, 1); - z.next_in_index++; - }while(b!=0); - return r; - } - - private int readBytes(int r, int f) throws Return{ - if(tmp_string == null){ - tmp_string=new java.io.ByteArrayOutputStream(); - } - int b=0; - while(this.need>0){ - if(z.avail_in==0){ throw new Return(r); }; r=f; - z.avail_in--; z.total_in++; - b = z.next_in[z.next_in_index]; - tmp_string.write(z.next_in, z.next_in_index, 1); - z.adler.update(z.next_in, z.next_in_index, 1); - z.next_in_index++; - this.need--; - } - return r; - } - - private void checksum(int n, long v){ - for(int i=0; i<n; i++){ - crcbuf[i]=(byte)(v&0xff); - v>>=8; - } - z.adler.update(crcbuf, 0, n); - } - - public GZIPHeader getGZIPHeader(){ - return gheader; - } - - boolean inParsingHeader(){ - switch(mode){ - case HEAD: - case DICT4: - case DICT3: - case DICT2: - case DICT1: - case FLAGS: - case TIME: - case OS: - case EXLEN: - case EXTRA: - case NAME: - case COMMENT: - case HCRC: - return true; - default: - return false; - } - } -}
--- a/src/com/jcraft/jzlib/Inflater.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final public class Inflater extends ZStream{ - - static final private int MAX_WBITS=15; // 32K LZ77 window - static final private int DEF_WBITS=MAX_WBITS; - - static final private int Z_NO_FLUSH=0; - static final private int Z_PARTIAL_FLUSH=1; - static final private int Z_SYNC_FLUSH=2; - static final private int Z_FULL_FLUSH=3; - static final private int Z_FINISH=4; - - static final private int MAX_MEM_LEVEL=9; - - static final private int Z_OK=0; - static final private int Z_STREAM_END=1; - static final private int Z_NEED_DICT=2; - static final private int Z_ERRNO=-1; - static final private int Z_STREAM_ERROR=-2; - static final private int Z_DATA_ERROR=-3; - static final private int Z_MEM_ERROR=-4; - static final private int Z_BUF_ERROR=-5; - static final private int Z_VERSION_ERROR=-6; - - public Inflater() { - super(); - init(); - } - - public Inflater(JZlib.WrapperType wrapperType) throws GZIPException { - this(DEF_WBITS, wrapperType); - } - - public Inflater(int w, JZlib.WrapperType wrapperType) throws GZIPException { - super(); - int ret = init(w, wrapperType); - if(ret!=Z_OK) - throw new GZIPException(ret+": "+msg); - } - - public Inflater(int w) throws GZIPException { - this(w, false); - } - - public Inflater(boolean nowrap) throws GZIPException { - this(DEF_WBITS, nowrap); - } - - public Inflater(int w, boolean nowrap) throws GZIPException { - super(); - int ret = init(w, nowrap); - if(ret!=Z_OK) - throw new GZIPException(ret+": "+msg); - } - - private boolean finished = false; - - public int init(){ - return init(DEF_WBITS); - } - - public int init(JZlib.WrapperType wrapperType){ - return init(DEF_WBITS, wrapperType); - } - - public int init(int w, JZlib.WrapperType wrapperType) { - boolean nowrap = false; - if(wrapperType == JZlib.W_NONE){ - nowrap = true; - } - else if(wrapperType == JZlib.W_GZIP) { - w += 16; - } - else if(wrapperType == JZlib.W_ANY) { - w |= Inflate.INFLATE_ANY; - } - else if(wrapperType == JZlib.W_ZLIB) { - } - return init(w, nowrap); - } - - public int init(boolean nowrap){ - return init(DEF_WBITS, nowrap); - } - - public int init(int w){ - return init(w, false); - } - - public int init(int w, boolean nowrap){ - finished = false; - istate=new Inflate(this); - return istate.inflateInit(nowrap?-w:w); - } - - public int inflate(int f){ - if(istate==null) return Z_STREAM_ERROR; - int ret = istate.inflate(f); - if(ret == Z_STREAM_END) - finished = true; - return ret; - } - - public int end(){ - finished = true; - if(istate==null) return Z_STREAM_ERROR; - int ret=istate.inflateEnd(); -// istate = null; - return ret; - } - - public int sync(){ - if(istate == null) - return Z_STREAM_ERROR; - return istate.inflateSync(); - } - - public int syncPoint(){ - if(istate == null) - return Z_STREAM_ERROR; - return istate.inflateSyncPoint(); - } - - public int setDictionary(byte[] dictionary, int dictLength){ - if(istate == null) - return Z_STREAM_ERROR; - return istate.inflateSetDictionary(dictionary, dictLength); - } - - public boolean finished(){ - return istate.mode==12 /*DONE*/; - } -}
--- a/src/com/jcraft/jzlib/InflaterInputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,247 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jcraft.jzlib; -import java.io.*; - -public class InflaterInputStream extends FilterInputStream { - protected final Inflater inflater; - protected byte[] buf; - - private boolean closed = false; - - private boolean eof = false; - - private boolean close_in = true; - - protected static final int DEFAULT_BUFSIZE = 512; - - public InflaterInputStream(InputStream in) throws IOException { - this(in, false); - } - - public InflaterInputStream(InputStream in, boolean nowrap) throws IOException { - this(in, new Inflater(nowrap)); - myinflater = true; - } - - public InflaterInputStream(InputStream in, Inflater inflater) throws IOException { - this(in, inflater, DEFAULT_BUFSIZE); - } - - public InflaterInputStream(InputStream in, - Inflater inflater, int size) throws IOException { - this(in, inflater, size, true); - } - - public InflaterInputStream(InputStream in, - Inflater inflater, - int size, boolean close_in) throws IOException { - super(in); - if (in == null || inflater == null) { - throw new NullPointerException(); - } - else if (size <= 0) { - throw new IllegalArgumentException("buffer size must be greater than 0"); - } - this.inflater = inflater; - buf = new byte[size]; - this.close_in = close_in; - } - - protected boolean myinflater = false; - - private byte[] byte1 = new byte[1]; - - public int read() throws IOException { - if (closed) { throw new IOException("Stream closed"); } - return read(byte1, 0, 1) == -1 ? -1 : byte1[0] & 0xff; - } - - public int read(byte[] b, int off, int len) throws IOException { - if (closed) { throw new IOException("Stream closed"); } - if (b == null) { - throw new NullPointerException(); - } - else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } - else if (len == 0) { - return 0; - } - else if (eof) { - return -1; - } - - int n = 0; - inflater.setOutput(b, off, len); - while(!eof) { - if(inflater.avail_in==0) - fill(); - int err = inflater.inflate(JZlib.Z_NO_FLUSH); - n += inflater.next_out_index - off; - off = inflater.next_out_index; - switch(err) { - case JZlib.Z_DATA_ERROR: - throw new IOException(inflater.msg); - case JZlib.Z_STREAM_END: - case JZlib.Z_NEED_DICT: - eof = true; - if(err == JZlib.Z_NEED_DICT) - return -1; - break; - default: - } - if(inflater.avail_out==0) - break; - } - return n; - } - - public int available() throws IOException { - if (closed) { throw new IOException("Stream closed"); } - if (eof) { - return 0; - } - else { - return 1; - } - } - - private byte[] b = new byte[512]; - - public long skip(long n) throws IOException { - if (n < 0) { - throw new IllegalArgumentException("negative skip length"); - } - - if (closed) { throw new IOException("Stream closed"); } - - int max = (int)Math.min(n, Integer.MAX_VALUE); - int total = 0; - while (total < max) { - int len = max - total; - if (len > b.length) { - len = b.length; - } - len = read(b, 0, len); - if (len == -1) { - eof = true; - break; - } - total += len; - } - return total; - } - - public void close() throws IOException { - if (!closed) { - if (myinflater) - inflater.end(); - if(close_in) - in.close(); - closed = true; - } - } - - protected void fill() throws IOException { - if (closed) { throw new IOException("Stream closed"); } - int len = in.read(buf, 0, buf.length); - if (len == -1) { - if(inflater.istate.wrap == 0 && - !inflater.finished()){ - buf[0]=0; - len=1; - } - else if(inflater.istate.was != -1){ // in reading trailer - throw new IOException("footer is not found"); - } - else{ - throw new EOFException("Unexpected end of ZLIB input stream"); - } - } - inflater.setInput(buf, 0, len, true); - } - - public boolean markSupported() { - return false; - } - - public synchronized void mark(int readlimit) { - } - - public synchronized void reset() throws IOException { - throw new IOException("mark/reset not supported"); - } - - public long getTotalIn() { - return inflater.getTotalIn(); - } - - public long getTotalOut() { - return inflater.getTotalOut(); - } - - public byte[] getAvailIn() { - if(inflater.avail_in<=0) - return null; - byte[] tmp = new byte[inflater.avail_in]; - System.arraycopy(inflater.next_in, inflater.next_in_index, - tmp, 0, inflater.avail_in); - return tmp; - } - - public void readHeader() throws IOException { - - byte[] empty = "".getBytes(); - inflater.setInput(empty, 0, 0, false); - inflater.setOutput(empty, 0, 0); - - int err = inflater.inflate(JZlib.Z_NO_FLUSH); - if(!inflater.istate.inParsingHeader()){ - return; - } - - byte[] b1 = new byte[1]; - do{ - int i = in.read(b1); - if(i<=0) - throw new IOException("no input"); - inflater.setInput(b1); - err = inflater.inflate(JZlib.Z_NO_FLUSH); - if(err!=0/*Z_OK*/) - throw new IOException(inflater.msg); - } - while(inflater.istate.inParsingHeader()); - } - - public Inflater getInflater(){ - return inflater; - } -} \ No newline at end of file
--- a/src/com/jcraft/jzlib/JZlib.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final public class JZlib{ - private static final String version="1.1.0"; - public static String version(){return version;} - - static final public int MAX_WBITS=15; // 32K LZ77 window - static final public int DEF_WBITS=MAX_WBITS; - - public enum WrapperType { - NONE, ZLIB, GZIP, ANY - } - - public static final WrapperType W_NONE = WrapperType.NONE; - public static final WrapperType W_ZLIB = WrapperType.ZLIB; - public static final WrapperType W_GZIP = WrapperType.GZIP; - public static final WrapperType W_ANY = WrapperType.ANY; - - // compression levels - static final public int Z_NO_COMPRESSION=0; - static final public int Z_BEST_SPEED=1; - static final public int Z_BEST_COMPRESSION=9; - static final public int Z_DEFAULT_COMPRESSION=(-1); - - // compression strategy - static final public int Z_FILTERED=1; - static final public int Z_HUFFMAN_ONLY=2; - static final public int Z_DEFAULT_STRATEGY=0; - - static final public int Z_NO_FLUSH=0; - static final public int Z_PARTIAL_FLUSH=1; - static final public int Z_SYNC_FLUSH=2; - static final public int Z_FULL_FLUSH=3; - static final public int Z_FINISH=4; - - static final public int Z_OK=0; - static final public int Z_STREAM_END=1; - static final public int Z_NEED_DICT=2; - static final public int Z_ERRNO=-1; - static final public int Z_STREAM_ERROR=-2; - static final public int Z_DATA_ERROR=-3; - static final public int Z_MEM_ERROR=-4; - static final public int Z_BUF_ERROR=-5; - static final public int Z_VERSION_ERROR=-6; - - // The three kinds of block type - static final public byte Z_BINARY = 0; - static final public byte Z_ASCII = 1; - static final public byte Z_UNKNOWN = 2; - - public static long adler32_combine(long adler1, long adler2, long len2){ - return Adler32.combine(adler1, adler2, len2); - } - - public static long crc32_combine(long crc1, long crc2, long len2){ - return CRC32.combine(crc1, crc2, len2); - } -}
--- a/src/com/jcraft/jzlib/StaticTree.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final class StaticTree{ - static final private int MAX_BITS=15; - - static final private int BL_CODES=19; - static final private int D_CODES=30; - static final private int LITERALS=256; - static final private int LENGTH_CODES=29; - static final private int L_CODES=(LITERALS+1+LENGTH_CODES); - - // Bit length codes must not exceed MAX_BL_BITS bits - static final int MAX_BL_BITS=7; - - static final short[] static_ltree = { - 12, 8, 140, 8, 76, 8, 204, 8, 44, 8, - 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, - 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, - 252, 8, 2, 8, 130, 8, 66, 8, 194, 8, - 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, - 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, - 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, - 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, - 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, - 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, - 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, - 230, 8, 22, 8, 150, 8, 86, 8, 214, 8, - 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, - 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, - 110, 8, 238, 8, 30, 8, 158, 8, 94, 8, - 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, - 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, - 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, - 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, - 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, - 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, - 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, - 121, 8, 249, 8, 5, 8, 133, 8, 69, 8, - 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, - 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, - 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, - 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, - 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, - 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, - 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, - 211, 9, 467, 9, 51, 9, 307, 9, 179, 9, - 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, - 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, - 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, - 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, - 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, - 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, - 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, - 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, - 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, - 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, - 359, 9, 231, 9, 487, 9, 23, 9, 279, 9, - 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, - 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, - 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, - 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, - 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, - 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, - 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, - 351, 9, 223, 9, 479, 9, 63, 9, 319, 9, - 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, - 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, - 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, - 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, - 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, - 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, - 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, - 163, 8, 99, 8, 227, 8 - }; - - static final short[] static_dtree = { - 0, 5, 16, 5, 8, 5, 24, 5, 4, 5, - 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, - 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, - 30, 5, 1, 5, 17, 5, 9, 5, 25, 5, - 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, - 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 - }; - - static StaticTree static_l_desc = - new StaticTree(static_ltree, Tree.extra_lbits, - LITERALS+1, L_CODES, MAX_BITS); - - static StaticTree static_d_desc = - new StaticTree(static_dtree, Tree.extra_dbits, - 0, D_CODES, MAX_BITS); - - static StaticTree static_bl_desc = - new StaticTree(null, Tree.extra_blbits, - 0, BL_CODES, MAX_BL_BITS); - - short[] static_tree; // static tree or null - int[] extra_bits; // extra bits for each code or null - int extra_base; // base index for extra_bits - int elems; // max number of elements in the tree - int max_length; // max bit length for the codes - - private StaticTree(short[] static_tree, - int[] extra_bits, - int extra_base, - int elems, - int max_length){ - this.static_tree=static_tree; - this.extra_bits=extra_bits; - this.extra_base=extra_base; - this.elems=elems; - this.max_length=max_length; - } -}
--- a/src/com/jcraft/jzlib/Tree.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,367 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -final class Tree{ - static final private int MAX_BITS=15; - static final private int BL_CODES=19; - static final private int D_CODES=30; - static final private int LITERALS=256; - static final private int LENGTH_CODES=29; - static final private int L_CODES=(LITERALS+1+LENGTH_CODES); - static final private int HEAP_SIZE=(2*L_CODES+1); - - // Bit length codes must not exceed MAX_BL_BITS bits - static final int MAX_BL_BITS=7; - - // end of block literal code - static final int END_BLOCK=256; - - // repeat previous bit length 3-6 times (2 bits of repeat count) - static final int REP_3_6=16; - - // repeat a zero length 3-10 times (3 bits of repeat count) - static final int REPZ_3_10=17; - - // repeat a zero length 11-138 times (7 bits of repeat count) - static final int REPZ_11_138=18; - - // extra bits for each length code - static final int[] extra_lbits={ - 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0 - }; - - // extra bits for each distance code - static final int[] extra_dbits={ - 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 - }; - - // extra bits for each bit length code - static final int[] extra_blbits={ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7 - }; - - static final byte[] bl_order={ - 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; - - - // The lengths of the bit length codes are sent in order of decreasing - // probability, to avoid transmitting the lengths for unused bit - // length codes. - - static final int Buf_size=8*2; - - // see definition of array dist_code below - static final int DIST_CODE_LEN=512; - - static final byte[] _dist_code = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, - 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, - 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 - }; - - static final byte[] _length_code={ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, - 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, - 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, - 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 - }; - - static final int[] base_length = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, - 64, 80, 96, 112, 128, 160, 192, 224, 0 - }; - - static final int[] base_dist = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 - }; - - // Mapping from a distance to a distance code. dist is the distance - 1 and - // must not have side effects. _dist_code[256] and _dist_code[257] are never - // used. - static int d_code(int dist){ - return ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>>7)]); - } - - short[] dyn_tree; // the dynamic tree - int max_code; // largest code with non zero frequency - StaticTree stat_desc; // the corresponding static tree - - // Compute the optimal bit lengths for a tree and update the total bit length - // for the current block. - // IN assertion: the fields freq and dad are set, heap[heap_max] and - // above are the tree nodes sorted by increasing frequency. - // OUT assertions: the field len is set to the optimal bit length, the - // array bl_count contains the frequencies for each bit length. - // The length opt_len is updated; static_len is also updated if stree is - // not null. - void gen_bitlen(Deflate s){ - short[] tree = dyn_tree; - short[] stree = stat_desc.static_tree; - int[] extra = stat_desc.extra_bits; - int base = stat_desc.extra_base; - int max_length = stat_desc.max_length; - int h; // heap index - int n, m; // iterate over the tree elements - int bits; // bit length - int xbits; // extra bits - short f; // frequency - int overflow = 0; // number of elements with bit length too large - - for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0; - - // In a first pass, compute the optimal bit lengths (which may - // overflow in the case of the bit length tree). - tree[s.heap[s.heap_max]*2+1] = 0; // root of the heap - - for(h=s.heap_max+1; h<HEAP_SIZE; h++){ - n = s.heap[h]; - bits = tree[tree[n*2+1]*2+1] + 1; - if (bits > max_length){ bits = max_length; overflow++; } - tree[n*2+1] = (short)bits; - // We overwrite tree[n*2+1] which is no longer needed - - if (n > max_code) continue; // not a leaf node - - s.bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n*2]; - s.opt_len += f * (bits + xbits); - if (stree!=null) s.static_len += f * (stree[n*2+1] + xbits); - } - if (overflow == 0) return; - - // This happens for example on obj2 and pic of the Calgary corpus - // Find the first bit length which could increase: - do { - bits = max_length-1; - while(s.bl_count[bits]==0) bits--; - s.bl_count[bits]--; // move one leaf down the tree - s.bl_count[bits+1]+=2; // move one overflow item as its brother - s.bl_count[max_length]--; - // The brother of the overflow item also moves one step up, - // but this does not affect bl_count[max_length] - overflow -= 2; - } - while (overflow > 0); - - for (bits = max_length; bits != 0; bits--) { - n = s.bl_count[bits]; - while (n != 0) { - m = s.heap[--h]; - if (m > max_code) continue; - if (tree[m*2+1] != bits) { - s.opt_len += ((long)bits - (long)tree[m*2+1])*(long)tree[m*2]; - tree[m*2+1] = (short)bits; - } - n--; - } - } - } - - // Construct one Huffman tree and assigns the code bit strings and lengths. - // Update the total bit length for the current block. - // IN assertion: the field freq is set for all tree elements. - // OUT assertions: the fields len and code are set to the optimal bit length - // and corresponding code. The length opt_len is updated; static_len is - // also updated if stree is not null. The field max_code is set. - void build_tree(Deflate s){ - short[] tree=dyn_tree; - short[] stree=stat_desc.static_tree; - int elems=stat_desc.elems; - int n, m; // iterate over heap elements - int max_code=-1; // largest code with non zero frequency - int node; // new node being created - - // Construct the initial heap, with least frequent element in - // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - // heap[0] is not used. - s.heap_len = 0; - s.heap_max = HEAP_SIZE; - - for(n=0; n<elems; n++) { - if(tree[n*2] != 0) { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; - } - else{ - tree[n*2+1] = 0; - } - } - - // The pkzip format requires that at least one distance code exists, - // and that at least one bit should be sent even if there is only one - // possible code. So to avoid special checks later on we force at least - // two codes of non zero frequency. - while (s.heap_len < 2) { - node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); - tree[node*2] = 1; - s.depth[node] = 0; - s.opt_len--; if (stree!=null) s.static_len -= stree[node*2+1]; - // node is 0 or 1 so it does not have extra bits - } - this.max_code = max_code; - - // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - // establish sub-heaps of increasing lengths: - - for(n=s.heap_len/2;n>=1; n--) - s.pqdownheap(tree, n); - - // Construct the Huffman tree by repeatedly combining the least two - // frequent nodes. - - node=elems; // next internal node of the tree - do{ - // n = node of least frequency - n=s.heap[1]; - s.heap[1]=s.heap[s.heap_len--]; - s.pqdownheap(tree, 1); - m=s.heap[1]; // m = node of next least frequency - - s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency - s.heap[--s.heap_max] = m; - - // Create a new node father of n and m - tree[node*2] = (short)(tree[n*2] + tree[m*2]); - s.depth[node] = (byte)(Math.max(s.depth[n],s.depth[m])+1); - tree[n*2+1] = tree[m*2+1] = (short)node; - - // and insert the new node in the heap - s.heap[1] = node++; - s.pqdownheap(tree, 1); - } - while(s.heap_len>=2); - - s.heap[--s.heap_max] = s.heap[1]; - - // At this point, the fields freq and dad are set. We can now - // generate the bit lengths. - - gen_bitlen(s); - - // The field len is now set, we can generate the bit codes - gen_codes(tree, max_code, s.bl_count, s.next_code); - } - - // Generate the codes for a given tree and bit counts (which need not be - // optimal). - // IN assertion: the array bl_count contains the bit length statistics for - // the given tree and the field len is set for all tree elements. - // OUT assertion: the field code is set for all tree elements of non - // zero code length. - private final static void gen_codes( - short[] tree, // the tree to decorate - int max_code, // largest code with non zero frequency - short[] bl_count, // number of codes at each bit length - short[] next_code){ - short code = 0; // running code value - int bits; // bit index - int n; // code index - - // The distribution counts are first used to generate the code values - // without bit reversal. - next_code[0]=0; - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (short)((code + bl_count[bits-1]) << 1); - } - - // Check that the bit counts in bl_count are consistent. The last code - // must be all ones. - //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, - // "inconsistent bit counts"); - //Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); - - for (n = 0; n <= max_code; n++) { - int len = tree[n*2+1]; - if (len == 0) continue; - // Now reverse the bits - tree[n*2] = (short)(bi_reverse(next_code[len]++, len)); - } - } - - // Reverse the first len bits of a code, using straightforward code (a faster - // method would use a table) - // IN assertion: 1 <= len <= 15 - private final static int bi_reverse( - int code, // the value to invert - int len // its bit length - ){ - int res = 0; - do{ - res|=code&1; - code>>>=1; - res<<=1; - } - while(--len>0); - return res>>>1; - } -} -
--- a/src/com/jcraft/jzlib/ZInputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jcraft.jzlib; -import java.io.*; - -/** - * ZInputStream - * - * @deprecated use DeflaterOutputStream or InflaterInputStream - */ -@Deprecated -public class ZInputStream extends FilterInputStream { - - protected int flush=JZlib.Z_NO_FLUSH; - protected boolean compress; - protected InputStream in=null; - - protected Deflater deflater; - protected InflaterInputStream iis; - - public ZInputStream(InputStream in) throws IOException { - this(in, false); - } - public ZInputStream(InputStream in, boolean nowrap) throws IOException { - super(in); - iis = new InflaterInputStream(in, nowrap); - compress=false; - } - - public ZInputStream(InputStream in, int level) throws IOException { - super(in); - this.in=in; - deflater = new Deflater(); - deflater.init(level); - compress=true; - } - - private byte[] buf1 = new byte[1]; - public int read() throws IOException { - if(read(buf1, 0, 1)==-1) return -1; - return(buf1[0]&0xFF); - } - - private byte[] buf = new byte[512]; - - public int read(byte[] b, int off, int len) throws IOException { - if(compress){ - deflater.setOutput(b, off, len); - while(true){ - int datalen = in.read(buf, 0, buf.length); - if(datalen == -1) return -1; - deflater.setInput(buf, 0, datalen, true); - int err = deflater.deflate(flush); - if(deflater.next_out_index>0) - return deflater.next_out_index; - if(err == JZlib.Z_STREAM_END) - return 0; - if(err == JZlib.Z_STREAM_ERROR || - err == JZlib.Z_DATA_ERROR){ - throw new ZStreamException("deflating: "+deflater.msg); - } - } - } - else{ - return iis.read(b, off, len); - } - } - - public long skip(long n) throws IOException { - int len=512; - if(n<len) - len=(int)n; - byte[] tmp=new byte[len]; - return((long)read(tmp)); - } - - public int getFlushMode() { - return flush; - } - - public void setFlushMode(int flush) { - this.flush=flush; - } - - public long getTotalIn() { - if(compress) return deflater.total_in; - else return iis.getTotalIn(); - } - - public long getTotalOut() { - if(compress) return deflater.total_out; - else return iis.getTotalOut(); - } - - public void close() throws IOException{ - if(compress) deflater.end(); - else iis.close(); - } -}
--- a/src/com/jcraft/jzlib/ZOutputStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jcraft.jzlib; -import java.io.*; - -/** - * ZOutputStream - * - * @deprecated use DeflaterOutputStream or InflaterInputStream - */ -@Deprecated -public class ZOutputStream extends FilterOutputStream { - - protected int bufsize=512; - protected int flush=JZlib.Z_NO_FLUSH; - protected byte[] buf=new byte[bufsize]; - protected boolean compress; - - protected OutputStream out; - private boolean end=false; - - private DeflaterOutputStream dos; - private Inflater inflater; - - public ZOutputStream(OutputStream out) throws IOException { - super(out); - this.out=out; - inflater = new Inflater(); - inflater.init(); - compress=false; - } - - public ZOutputStream(OutputStream out, int level) throws IOException { - this(out, level, false); - } - - public ZOutputStream(OutputStream out, int level, boolean nowrap) throws IOException { - super(out); - this.out=out; - Deflater deflater = new Deflater(level, nowrap); - dos = new DeflaterOutputStream(out, deflater); - compress=true; - } - - private byte[] buf1 = new byte[1]; - public void write(int b) throws IOException { - buf1[0]=(byte)b; - write(buf1, 0, 1); - } - - public void write(byte b[], int off, int len) throws IOException { - if(len==0) return; - if(compress){ - dos.write(b, off, len); - } - else { - inflater.setInput(b, off, len, true); - int err = JZlib.Z_OK; - while(inflater.avail_in>0){ - inflater.setOutput(buf, 0, buf.length); - err = inflater.inflate(flush); - if(inflater.next_out_index>0) - out.write(buf, 0, inflater.next_out_index); - if(err != JZlib.Z_OK) - break; - } - if(err != JZlib.Z_OK) - throw new ZStreamException("inflating: "+inflater.msg); - return; - } - } - - public int getFlushMode() { - return flush; - } - - public void setFlushMode(int flush) { - this.flush=flush; - } - - public void finish() throws IOException { - int err; - if(compress){ - int tmp = flush; - int flush = JZlib.Z_FINISH; - try{ - write("".getBytes(), 0, 0); - } - finally { flush = tmp; } - } - else{ - dos.finish(); - } - flush(); - } - public synchronized void end() { - if(end) return; - if(compress){ - try { dos.finish(); } catch(Exception e){} - } - else{ - inflater.end(); - } - end=true; - } - public void close() throws IOException { - try{ - try{finish();} - catch (IOException ignored) {} - } - finally{ - end(); - out.close(); - out=null; - } - } - - public long getTotalIn() { - if(compress) return dos.getTotalIn(); - else return inflater.total_in; - } - - public long getTotalOut() { - if(compress) return dos.getTotalOut(); - else return inflater.total_out; - } - - public void flush() throws IOException { - out.flush(); - } - -}
--- a/src/com/jcraft/jzlib/ZStream.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,377 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ -/* -Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -/** - * ZStream - * - * @deprecated Not for public use in the future. - */ -@Deprecated -public class ZStream{ - - static final private int MAX_WBITS=15; // 32K LZ77 window - static final private int DEF_WBITS=MAX_WBITS; - - static final private int Z_NO_FLUSH=0; - static final private int Z_PARTIAL_FLUSH=1; - static final private int Z_SYNC_FLUSH=2; - static final private int Z_FULL_FLUSH=3; - static final private int Z_FINISH=4; - - static final private int MAX_MEM_LEVEL=9; - - static final private int Z_OK=0; - static final private int Z_STREAM_END=1; - static final private int Z_NEED_DICT=2; - static final private int Z_ERRNO=-1; - static final private int Z_STREAM_ERROR=-2; - static final private int Z_DATA_ERROR=-3; - static final private int Z_MEM_ERROR=-4; - static final private int Z_BUF_ERROR=-5; - static final private int Z_VERSION_ERROR=-6; - - public byte[] next_in; // next input byte - public int next_in_index; - public int avail_in; // number of bytes available at next_in - public long total_in; // total nb of input bytes read so far - - public byte[] next_out; // next output byte should be put there - public int next_out_index; - public int avail_out; // remaining free space at next_out - public long total_out; // total nb of bytes output so far - - public String msg; - - Deflate dstate; - Inflate istate; - - int data_type; // best guess about the data type: ascii or binary - - Checksum adler; - - public ZStream(){ - this(new Adler32()); - } - - public ZStream(Checksum adler){ - this.adler=adler; - } - - public int inflateInit(){ - return inflateInit(DEF_WBITS); - } - public int inflateInit(boolean nowrap){ - return inflateInit(DEF_WBITS, nowrap); - } - public int inflateInit(int w){ - return inflateInit(w, false); - } - public int inflateInit(JZlib.WrapperType wrapperType) { - return inflateInit(DEF_WBITS, wrapperType); - } - public int inflateInit(int w, JZlib.WrapperType wrapperType) { - boolean nowrap = false; - if(wrapperType == JZlib.W_NONE){ - nowrap = true; - } - else if(wrapperType == JZlib.W_GZIP) { - w += 16; - } - else if(wrapperType == JZlib.W_ANY) { - w |= Inflate.INFLATE_ANY; - } - else if(wrapperType == JZlib.W_ZLIB) { - } - return inflateInit(w, nowrap); - } - public int inflateInit(int w, boolean nowrap){ - istate=new Inflate(this); - return istate.inflateInit(nowrap?-w:w); - } - - public int inflate(int f){ - if(istate==null) return Z_STREAM_ERROR; - return istate.inflate(f); - } - public int inflateEnd(){ - if(istate==null) return Z_STREAM_ERROR; - int ret=istate.inflateEnd(); -// istate = null; - return ret; - } - public int inflateSync(){ - if(istate == null) - return Z_STREAM_ERROR; - return istate.inflateSync(); - } - public int inflateSyncPoint(){ - if(istate == null) - return Z_STREAM_ERROR; - return istate.inflateSyncPoint(); - } - public int inflateSetDictionary(byte[] dictionary, int dictLength){ - if(istate == null) - return Z_STREAM_ERROR; - return istate.inflateSetDictionary(dictionary, dictLength); - } - public boolean inflateFinished(){ - return istate.mode==12 /*DONE*/; - } - - public int deflateInit(int level){ - return deflateInit(level, MAX_WBITS); - } - public int deflateInit(int level, boolean nowrap){ - return deflateInit(level, MAX_WBITS, nowrap); - } - public int deflateInit(int level, int bits){ - return deflateInit(level, bits, false); - } - public int deflateInit(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){ - if(bits < 9 || bits > 15){ - return Z_STREAM_ERROR; - } - if(wrapperType == JZlib.W_NONE) { - bits *= -1; - } - else if(wrapperType == JZlib.W_GZIP) { - bits += 16; - } - else if(wrapperType == JZlib.W_ANY) { - return Z_STREAM_ERROR; - } - else if(wrapperType == JZlib.W_ZLIB) { - } - return this.deflateInit(level, bits, memlevel); - } - public int deflateInit(int level, int bits, int memlevel){ - dstate=new Deflate(this); - return dstate.deflateInit(level, bits, memlevel); - } - public int deflateInit(int level, int bits, boolean nowrap){ - dstate=new Deflate(this); - return dstate.deflateInit(level, nowrap?-bits:bits); - } - public int deflate(int flush){ - if(dstate==null){ - return Z_STREAM_ERROR; - } - return dstate.deflate(flush); - } - public int deflateEnd(){ - if(dstate==null) return Z_STREAM_ERROR; - int ret=dstate.deflateEnd(); - dstate=null; - return ret; - } - public int deflateParams(int level, int strategy){ - if(dstate==null) return Z_STREAM_ERROR; - return dstate.deflateParams(level, strategy); - } - public int deflateSetDictionary (byte[] dictionary, int dictLength){ - if(dstate == null) - return Z_STREAM_ERROR; - return dstate.deflateSetDictionary(dictionary, dictLength); - } - - // Flush as much pending output as possible. All deflate() output goes - // through this function so some applications may wish to modify it - // to avoid allocating a large strm->next_out buffer and copying into it. - // (See also read_buf()). - void flush_pending(){ - int len=dstate.pending; - - if(len>avail_out) len=avail_out; - if(len==0) return; - - if(dstate.pending_buf.length<=dstate.pending_out || - next_out.length<=next_out_index || - dstate.pending_buf.length<(dstate.pending_out+len) || - next_out.length<(next_out_index+len)){ - //System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+ - // ", "+next_out.length+", "+next_out_index+", "+len); - //System.out.println("avail_out="+avail_out); - } - - System.arraycopy(dstate.pending_buf, dstate.pending_out, - next_out, next_out_index, len); - - next_out_index+=len; - dstate.pending_out+=len; - total_out+=len; - avail_out-=len; - dstate.pending-=len; - if(dstate.pending==0){ - dstate.pending_out=0; - } - } - - // Read a new buffer from the current input stream, update the adler32 - // and total number of bytes read. All deflate() input goes through - // this function so some applications may wish to modify it to avoid - // allocating a large strm->next_in buffer and copying from it. - // (See also flush_pending()). - int read_buf(byte[] buf, int start, int size) { - int len=avail_in; - - if(len>size) len=size; - if(len==0) return 0; - - avail_in-=len; - - if(dstate.wrap!=0) { - adler.update(next_in, next_in_index, len); - } - System.arraycopy(next_in, next_in_index, buf, start, len); - next_in_index += len; - total_in += len; - return len; - } - - public long getAdler(){ - return adler.getValue(); - } - - public void free(){ - next_in=null; - next_out=null; - msg=null; - } - - public void setOutput(byte[] buf){ - setOutput(buf, 0, buf.length); - } - - public void setOutput(byte[] buf, int off, int len){ - next_out = buf; - next_out_index = off; - avail_out = len; - } - - public void setInput(byte[] buf){ - setInput(buf, 0, buf.length, false); - } - - public void setInput(byte[] buf, boolean append){ - setInput(buf, 0, buf.length, append); - } - - public void setInput(byte[] buf, int off, int len, boolean append){ - if(len<=0 && append && next_in!=null) return; - - if(avail_in>0 && append){ - byte[] tmp = new byte[avail_in+len]; - System.arraycopy(next_in, next_in_index, tmp, 0, avail_in); - System.arraycopy(buf, off, tmp, avail_in, len); - next_in=tmp; - next_in_index=0; - avail_in+=len; - } - else{ - next_in=buf; - next_in_index=off; - avail_in=len; - } - } - - public byte[] getNextIn(){ - return next_in; - } - - public void setNextIn(byte[] next_in){ - this.next_in = next_in; - } - - public int getNextInIndex(){ - return next_in_index; - } - - public void setNextInIndex(int next_in_index){ - this.next_in_index = next_in_index; - } - - public int getAvailIn(){ - return avail_in; - } - - public void setAvailIn(int avail_in){ - this.avail_in = avail_in; - } - - public byte[] getNextOut(){ - return next_out; - } - - public void setNextOut(byte[] next_out){ - this.next_out = next_out; - } - - public int getNextOutIndex(){ - return next_out_index; - } - - public void setNextOutIndex(int next_out_index){ - this.next_out_index = next_out_index; - } - - public int getAvailOut(){ - return avail_out; - - } - - public void setAvailOut(int avail_out){ - this.avail_out = avail_out; - } - - public long getTotalOut(){ - return total_out; - } - - public long getTotalIn(){ - return total_in; - } - - public String getMessage(){ - return msg; - } - - /** - * Those methods are expected to be override by Inflater and Deflater. - * In the future, they will become abstract methods. - */ - public int end(){ return Z_OK; } - public boolean finished(){ return false; } -}
--- a/src/com/jcraft/jzlib/ZStreamException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* -*-mode:java; c-basic-offset:2; -*- */ -/* -Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - - 3. The names of the authors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This program is based on zlib-1.1.3, so all credit should go authors - * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) - * and contributors of zlib. - */ - -package com.jcraft.jzlib; - -public class ZStreamException extends java.io.IOException { - public ZStreamException() { - super(); - } - public ZStreamException(String s) { - super(s); - } -}
--- a/src/com/lamerman/FileDialog.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,292 +0,0 @@ -package com.lamerman; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.TreeMap; - -import com.five_ten_sg.connectbot.R; -import android.app.AlertDialog; -import android.app.ListActivity; -import android.content.DialogInterface; -import android.net.Uri; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.inputmethod.InputMethodManager; -import android.widget.Button; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.SimpleAdapter; -import android.widget.TextView; - -public class FileDialog extends ListActivity { - - private static final String ITEM_KEY = "key"; - private static final String ITEM_IMAGE = "image"; - private static final String ROOT = "/"; - - public static final String START_PATH = "START_PATH"; - public static final String RESULT_PATH = "RESULT_PATH"; - public static final String SELECTION_MODE = "SELECTION_MODE"; - public static final String TITLE = "TITLE"; - - private List<String> path = null; - private TextView myPath; - private EditText mFileName; - private ArrayList<HashMap<String, Object>> mList; - - private Button selectButton; - - private LinearLayout layoutSelect; - private LinearLayout layoutCreate; - private InputMethodManager inputManager; - private String parentPath; - private String currentPath = ROOT; - - private int selectionMode = SelectionMode.MODE_CREATE; - - private File selectedFile; - private HashMap<String, Integer> lastPositions = new HashMap<String, Integer>(); - - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setResult(RESULT_CANCELED, getIntent()); - setContentView(R.layout.file_dialog_main); - this.setTitle(String.format("%s: %s", - getResources().getText(R.string.app_name), - getIntent().getStringExtra(TITLE))); - myPath = (TextView) findViewById(R.id.path); - mFileName = (EditText) findViewById(R.id.fdEditTextFile); - inputManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); - selectButton = (Button) findViewById(R.id.fdButtonSelect); - selectButton.setEnabled(false); - selectButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - if (selectedFile != null) { - getIntent().setData(Uri.fromFile(selectedFile)); - setResult(RESULT_OK, getIntent()); - finish(); - } - } - }); - final Button newButton = (Button) findViewById(R.id.fdButtonNew); - newButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - setCreateVisible(v); - mFileName.setText(""); - mFileName.requestFocus(); - } - }); - final Button cancelButton = (Button) findViewById(R.id.fdButtonCancel); - cancelButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - setResult(RESULT_CANCELED, getIntent()); - finish(); - } - }); - selectionMode = getIntent().getIntExtra(SELECTION_MODE, - SelectionMode.MODE_CREATE); - - if (selectionMode == SelectionMode.MODE_OPEN) { - newButton.setEnabled(false); - } - - layoutSelect = (LinearLayout) findViewById(R.id.fdLinearLayoutSelect); - layoutCreate = (LinearLayout) findViewById(R.id.fdLinearLayoutCreate); - layoutCreate.setVisibility(View.GONE); - final Button cancelCreateButton = (Button) findViewById(R.id.fdButtonCancelCreate); - cancelCreateButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - setSelectVisible(v); - } - }); - final Button createButton = (Button) findViewById(R.id.fdButtonCreate); - createButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - if (mFileName.getText().length() > 0) { - getIntent().putExtra(RESULT_PATH, - currentPath + "/" + mFileName.getText()); - setResult(RESULT_OK, getIntent()); - finish(); - } - } - }); - String startPath = getIntent().getStringExtra(START_PATH); - - if (startPath != null) { - getDir(startPath); - } - else { - getDir(ROOT); - } - } - - @Override - protected void onPause() { - String myPathStr = myPath.getText().toString(); - int idx = myPathStr.lastIndexOf(':'); - String currPath = myPathStr.substring(idx + 2); - getIntent().putExtra(START_PATH, currPath); - super.onPause(); - } - - private void getDir(String dirPath) { - boolean useAutoSelection = dirPath.length() < currentPath.length(); - Integer position = lastPositions.get(parentPath); - getDirImpl(dirPath); - - if (position != null && useAutoSelection) { - getListView().setSelection(position); - } - } - - private void getDirImpl(final String dirPath) { - currentPath = dirPath; - final List<String> item = new ArrayList<String>(); - path = new ArrayList<String>(); - mList = new ArrayList<HashMap<String, Object>>(); - File f = new File(currentPath); - File[] files = f.listFiles(); - - if (files == null) { - currentPath = ROOT; - f = new File(currentPath); - files = f.listFiles(); - } - - myPath.setText(getText(R.string.location) + ": " + currentPath); - - if (!currentPath.equals(ROOT)) { - item.add(ROOT); - addItem(ROOT, R.drawable.folder); - path.add(ROOT); - item.add("../"); - addItem("../", R.drawable.folder); - path.add(f.getParent()); - parentPath = f.getParent(); - } - - TreeMap<String, String> dirsMap = new TreeMap<String, String>(); - TreeMap<String, String> dirsPathMap = new TreeMap<String, String>(); - TreeMap<String, String> filesMap = new TreeMap<String, String>(); - TreeMap<String, String> filesPathMap = new TreeMap<String, String>(); - - for (File file : files) { - if (file.isDirectory()) { - String dirName = file.getName(); - dirsMap.put(dirName, dirName); - dirsPathMap.put(dirName, file.getPath()); - } - else { - filesMap.put(file.getName(), file.getName()); - filesPathMap.put(file.getName(), file.getPath()); - } - } - - item.addAll(dirsMap.tailMap("").values()); - item.addAll(filesMap.tailMap("").values()); - path.addAll(dirsPathMap.tailMap("").values()); - path.addAll(filesPathMap.tailMap("").values()); - SimpleAdapter fileList = new SimpleAdapter(this, mList, - R.layout.file_dialog_row, - new String[] { ITEM_KEY, ITEM_IMAGE }, new int[] { - R.id.fdrowtext, R.id.fdrowimage - }); - - for (String dir : dirsMap.tailMap("").values()) { - addItem(dir, R.drawable.folder); - } - - for (String file : filesMap.tailMap("").values()) { - addItem(file, R.drawable.file); - } - - fileList.notifyDataSetChanged(); - setListAdapter(fileList); - } - - private void addItem(String fileName, int imageId) { - HashMap<String, Object> item = new HashMap<String, Object>(); - item.put(ITEM_KEY, fileName); - item.put(ITEM_IMAGE, imageId); - mList.add(item); - } - - @Override - protected void onListItemClick(ListView l, View v, int position, long id) { - File file = new File(path.get(position)); - setSelectVisible(v); - - if (file.isDirectory()) { - selectButton.setEnabled(false); - - if (file.canRead()) { - lastPositions.put(currentPath, position); - getDir(path.get(position)); - } - else { - new AlertDialog.Builder(this) - .setIcon(R.drawable.icon) - .setTitle( - "[" + file.getName() + "] " - + getText(R.string.cant_read_folder)) - .setPositiveButton("OK", - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - } - }).show(); - } - } - else { - selectedFile = file; - v.setSelected(true); - selectButton.setEnabled(true); - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if ((keyCode == KeyEvent.KEYCODE_BACK)) { - selectButton.setEnabled(false); - - if (layoutCreate.getVisibility() == View.VISIBLE) { - layoutCreate.setVisibility(View.GONE); - layoutSelect.setVisibility(View.VISIBLE); - } - else { - if (!currentPath.equals(ROOT)) { - getDir(parentPath); - } - else { - return super.onKeyDown(keyCode, event); - } - } - - return true; - } - else { - return super.onKeyDown(keyCode, event); - } - } - - private void setCreateVisible(View v) { - layoutCreate.setVisibility(View.VISIBLE); - layoutSelect.setVisibility(View.GONE); - inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); - selectButton.setEnabled(false); - } - - private void setSelectVisible(View v) { - layoutCreate.setVisibility(View.GONE); - layoutSelect.setVisibility(View.VISIBLE); - inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); - selectButton.setEnabled(false); - } -} \ No newline at end of file
--- a/src/com/lamerman/SelectionMode.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -package com.lamerman; - -public class SelectionMode { - public static final int MODE_CREATE = 0; - - public static final int MODE_OPEN = 1; -}
--- a/src/com/madgag/ssh/android/authagent/AndroidAuthAgent.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/* - * This file is auto-generated. DO NOT MODIFY. - * Original file: /home/roberto/development/madgag-ssh/ssh-android/src/main/java/com/madgag/ssh/android/authagent/AndroidAuthAgent.aidl - */ -package com.madgag.ssh.android.authagent; -public interface AndroidAuthAgent extends android.os.IInterface { - /** Local-side IPC implementation stub class. */ - public static abstract class Stub extends android.os.Binder implements com.madgag.ssh.android.authagent.AndroidAuthAgent { - private static final java.lang.String DESCRIPTOR = "com.madgag.ssh.android.authagent.AndroidAuthAgent"; - /** Construct the stub at attach it to the interface. */ - public Stub() { - this.attachInterface(this, DESCRIPTOR); - } - /** - * Cast an IBinder object into an com.madgag.ssh.android.authagent.AndroidAuthAgent interface, - * generating a proxy if needed. - */ - public static com.madgag.ssh.android.authagent.AndroidAuthAgent asInterface(android.os.IBinder obj) { - if ((obj == null)) { - return null; - } - - android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR); - - if (((iin != null) && (iin instanceof com.madgag.ssh.android.authagent.AndroidAuthAgent))) { - return ((com.madgag.ssh.android.authagent.AndroidAuthAgent)iin); - } - - return new com.madgag.ssh.android.authagent.AndroidAuthAgent.Stub.Proxy(obj); - } - public android.os.IBinder asBinder() { - return this; - } - @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { - switch (code) { - case INTERFACE_TRANSACTION: { - reply.writeString(DESCRIPTOR); - return true; - } - - case TRANSACTION_getIdentities: { - data.enforceInterface(DESCRIPTOR); - java.util.Map _result = this.getIdentities(); - reply.writeNoException(); - reply.writeMap(_result); - return true; - } - - case TRANSACTION_sign: { - data.enforceInterface(DESCRIPTOR); - byte[] _arg0; - _arg0 = data.createByteArray(); - byte[] _arg1; - _arg1 = data.createByteArray(); - byte[] _result = this.sign(_arg0, _arg1); - reply.writeNoException(); - reply.writeByteArray(_result); - return true; - } - } - - return super.onTransact(code, data, reply, flags); - } - private static class Proxy implements com.madgag.ssh.android.authagent.AndroidAuthAgent { - private android.os.IBinder mRemote; - Proxy(android.os.IBinder remote) { - mRemote = remote; - } - public android.os.IBinder asBinder() { - return mRemote; - } - public java.lang.String getInterfaceDescriptor() { - return DESCRIPTOR; - } - public java.util.Map getIdentities() throws android.os.RemoteException { - android.os.Parcel _data = android.os.Parcel.obtain(); - android.os.Parcel _reply = android.os.Parcel.obtain(); - java.util.Map _result; - - try { - _data.writeInterfaceToken(DESCRIPTOR); - mRemote.transact(Stub.TRANSACTION_getIdentities, _data, _reply, 0); - _reply.readException(); - java.lang.ClassLoader cl = (java.lang.ClassLoader)this.getClass().getClassLoader(); - _result = _reply.readHashMap(cl); - } - finally { - _reply.recycle(); - _data.recycle(); - } - - return _result; - } - public byte[] sign(byte[] publicKey, byte[] data) throws android.os.RemoteException { - android.os.Parcel _data = android.os.Parcel.obtain(); - android.os.Parcel _reply = android.os.Parcel.obtain(); - byte[] _result; - - try { - _data.writeInterfaceToken(DESCRIPTOR); - _data.writeByteArray(publicKey); - _data.writeByteArray(data); - mRemote.transact(Stub.TRANSACTION_sign, _data, _reply, 0); - _reply.readException(); - _result = _reply.createByteArray(); - } - finally { - _reply.recycle(); - _data.recycle(); - } - - return _result; - } - } - static final int TRANSACTION_getIdentities = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); - static final int TRANSACTION_sign = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); - } - public java.util.Map getIdentities() throws android.os.RemoteException; - public byte[] sign(byte[] publicKey, byte[] data) throws android.os.RemoteException; -}
--- a/src/de/mud/telnet/TelnetProtocolHandler.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,789 +0,0 @@ -/* - * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". - * - * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved. - * - * Please visit http://javatelnet.org/ for updates and contact. - * - * --LICENSE NOTICE-- - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * --LICENSE NOTICE-- - * - */ - -package de.mud.telnet; - -import java.io.IOException; -/** - * This is a telnet protocol handler. The handler needs implementations - * for several methods to handle the telnet options and to be able to - * read and write the buffer. - * <P> - * <B>Maintainer:</B> Marcus Meissner - * - * @version $Id: TelnetProtocolHandler.java 503 2005-10-24 07:34:13Z marcus $ - * @author Matthias L. Jugel, Marcus Meissner - */ -public abstract class TelnetProtocolHandler { - /** contains the current revision id */ - public final static String ID = "$Id: TelnetProtocolHandler.java 503 2005-10-24 07:34:13Z marcus $"; - - /** debug level */ - private final static int debug = 0; - - /** temporary buffer for data-telnetstuff-data transformation */ - private byte[] tempbuf = new byte[0]; - - /** the data sent on pressing <RETURN> \n */ - private byte[] crlf = new byte[2]; - /** the data sent on pressing <LineFeed> \r */ - private byte[] cr = new byte[2]; - - /** - * Create a new telnet protocol handler. - */ - public TelnetProtocolHandler() { - reset(); - crlf[0] = 13; crlf[1] = 10; - cr[0] = 13; cr[1] = 0; - } - - /** - * Get the current terminal type for TTYPE telnet option. - * @return the string id of the terminal - */ - protected abstract String getTerminalType(); - - /** - * Get the current window size of the terminal for the - * NAWS telnet option. - * @return the size of the terminal as Dimension - */ - protected abstract int[] getWindowSize(); - - /** - * Set the local echo option of telnet. - * @param echo true for local echo, false for no local echo - */ - protected abstract void setLocalEcho(boolean echo); - - /** - * Generate an EOR (end of record) request. For use by prompt displaying. - */ - protected abstract void notifyEndOfRecord(); - - /** - * Send data to the remote host. - * @param b array of bytes to send - */ - protected abstract void write(byte[] b) throws IOException; - - /** - * Read the charset name from terminal. - */ - protected abstract String getCharsetName(); - - /** - * Send one byte to the remote host. - * @param b the byte to be sent - * @see #write(byte[] b) - */ - private static byte[] one = new byte[1]; - private void write(byte b) throws IOException { - one[0] = b; - write(one); - } - - /** - * Reset the protocol handler. This may be necessary after the - * connection was closed or some other problem occured. - */ - public void reset() { - neg_state = 0; - receivedDX = new byte[256]; - sentDX = new byte[256]; - receivedWX = new byte[256]; - sentWX = new byte[256]; - } - - // =================================================================== - // the actual negotiation handling for the telnet protocol follows: - // =================================================================== - - /** state variable for telnet negotiation reader */ - private byte neg_state = 0; - - /** constants for the negotiation state */ - private final static byte STATE_DATA = 0; - private final static byte STATE_IAC = 1; - private final static byte STATE_IACSB = 2; - private final static byte STATE_IACWILL = 3; - private final static byte STATE_IACDO = 4; - private final static byte STATE_IACWONT = 5; - private final static byte STATE_IACDONT = 6; - private final static byte STATE_IACSBIAC = 7; - private final static byte STATE_IACSBDATA = 8; - private final static byte STATE_IACSBDATAIAC = 9; - - /** What IAC SB <xx> we are handling right now */ - private byte current_sb; - - /** current SB negotiation buffer */ - private byte[] sbbuf; - - /** IAC - init sequence for telnet negotiation. */ - private final static byte IAC = (byte)255; - /** [IAC] End Of Record */ - private final static byte EOR = (byte)239; - /** [IAC] WILL */ - private final static byte WILL = (byte)251; - /** [IAC] WONT */ - private final static byte WONT = (byte)252; - /** [IAC] DO */ - private final static byte DO = (byte)253; - /** [IAC] DONT */ - private final static byte DONT = (byte)254; - /** [IAC] Sub Begin */ - private final static byte SB = (byte)250; - /** [IAC] Sub End */ - private final static byte SE = (byte)240; - /** Telnet option: binary mode */ - private final static byte TELOPT_BINARY = (byte)0; /* binary mode */ - /** Telnet option: echo text */ - private final static byte TELOPT_ECHO = (byte)1; /* echo on/off */ - /** Telnet option: sga */ - private final static byte TELOPT_SGA = (byte)3; /* supress go ahead */ - /** Telnet option: End Of Record */ - private final static byte TELOPT_EOR = (byte)25; /* end of record */ - /** Telnet option: Negotiate About Window Size */ - private final static byte TELOPT_NAWS = (byte)31; /* NA-WindowSize*/ - /** Telnet option: Terminal Type */ - private final static byte TELOPT_TTYPE = (byte)24; /* terminal type */ - /** Telnet option: CHARSET */ - private final static byte TELOPT_CHARSET = (byte)42; /* charset */ - - private final static byte[] IACWILL = { IAC, WILL }; - private final static byte[] IACWONT = { IAC, WONT }; - private final static byte[] IACDO = { IAC, DO }; - private final static byte[] IACDONT = { IAC, DONT }; - private final static byte[] IACSB = { IAC, SB }; - private final static byte[] IACSE = { IAC, SE }; - - private final static byte CHARSET_ACCEPTED = (byte)2; - private final static byte CHARSET_REJECTED = (byte)3; - - /** Telnet option qualifier 'IS' */ - private final static byte TELQUAL_IS = (byte)0; - /** Telnet option qualifier 'SEND' */ - private final static byte TELQUAL_SEND = (byte)1; - - /** What IAC DO(NT) request do we have received already ? */ - private byte[] receivedDX; - /** What IAC WILL/WONT request do we have received already ? */ - private byte[] receivedWX; - /** What IAC DO/DONT request do we have sent already ? */ - private byte[] sentDX; - /** What IAC WILL/WONT request do we have sent already ? */ - private byte[] sentWX; - - /** - * Send a Telnet Escape character (IAC <code>) - */ - public void sendTelnetControl(byte code) - throws IOException { - byte[] b = new byte[2]; - b[0] = IAC; - b[1] = code; - write(b); - } - - /** - * Send the new Window Size (via NAWS) - */ - public void setWindowSize(int columns, int rows) - throws IOException { - if (debug > 2) System.err.println("sending NAWS"); - - if (receivedDX[TELOPT_NAWS] != DO) { - System.err.println("not allowed to send NAWS? (DONT NAWS)"); - return; - } - - write(IAC); write(SB); write(TELOPT_NAWS); - write((byte)(columns >> 8)); - write((byte)(columns & 0xff)); - write((byte)(rows >> 8)); - write((byte)(rows & 0xff)); - write(IAC); write(SE); - } - - - /** - * Handle an incoming IAC SB <type> <bytes> IAC SE - * @param type type of SB - * @param sbata byte array as <bytes> - */ - private void handle_sb(byte type, byte[] sbdata) - throws IOException { - if (debug > 1) - System.err.println("TelnetIO.handle_sb(" + type + ")"); - - switch (type) { - case TELOPT_TTYPE: - if (sbdata.length > 0 && sbdata[0] == TELQUAL_SEND) { - write(IACSB); write(TELOPT_TTYPE); write(TELQUAL_IS); - /* FIXME: need more logic here if we use - * more than one terminal type - */ - String ttype = getTerminalType(); - - if (ttype == null) ttype = "dumb"; - - write(ttype.getBytes()); - write(IACSE); - } - - break; - - case TELOPT_CHARSET: - System.out.println("Got SB CHARSET"); - String charsetStr = new String(sbdata, "US-ASCII"); - - if (charsetStr.startsWith("TTABLE ")) { - charsetStr = charsetStr.substring(7); - } - - String[] charsets = charsetStr.split(charsetStr.substring(0, 0)); - String myCharset = getCharsetName(); - - for (String charset : charsets) { - if (charset.equals(myCharset)) { - write(IACSB); write(TELOPT_CHARSET); write(CHARSET_ACCEPTED); - write(charset.getBytes()); - write(IACSE); - System.out.println("Sent our charset!"); - return; - } - } - - write(IACSB); write(TELOPT_CHARSET); write(CHARSET_REJECTED); - write(IACSE); - break; - } - } - - /** - * Do not send any notifications at startup. We do not know, - * whether the remote client understands telnet protocol handling, - * so we are silent. - * (This used to send IAC WILL SGA, but this is false for a compliant - * client.) - */ - public void startup() throws IOException { - } - /** - * Transpose special telnet codes like 0xff or newlines to values - * that are compliant to the protocol. This method will also send - * the buffer immediately after transposing the data. - * @param buf the data buffer to be sent - */ - public void transpose(byte[] buf) throws IOException { - int i; - byte[] nbuf, xbuf; - int nbufptr = 0; - nbuf = new byte[buf.length * 2]; // FIXME: buffer overflows possible - - for (i = 0; i < buf.length ; i++) { - switch (buf[i]) { - // Escape IAC twice in stream ... to be telnet protocol compliant - // this is there in binary and non-binary mode. - case IAC: - nbuf[nbufptr++] = IAC; - nbuf[nbufptr++] = IAC; - break; - - // We need to heed RFC 854. LF (\n) is 10, CR (\r) is 13 - // we assume that the Terminal sends \n for lf+cr and \r for just cr - // linefeed+carriage return is CR LF */ - case 10: // \n - if (receivedDX[TELOPT_BINARY + 128 ] != DO) { - while (nbuf.length - nbufptr < crlf.length) { - xbuf = new byte[nbuf.length * 2]; - System.arraycopy(nbuf, 0, xbuf, 0, nbufptr); - nbuf = xbuf; - } - - for (int j = 0; j < crlf.length; j++) - nbuf[nbufptr++] = crlf[j]; - - break; - } - else { - // copy verbatim in binary mode. - nbuf[nbufptr++] = buf[i]; - } - - break; - - // carriage return is CR NUL */ - case 13: // \r - if (receivedDX[TELOPT_BINARY + 128 ] != DO) { - while (nbuf.length - nbufptr < cr.length) { - xbuf = new byte[nbuf.length * 2]; - System.arraycopy(nbuf, 0, xbuf, 0, nbufptr); - nbuf = xbuf; - } - - for (int j = 0; j < cr.length; j++) - nbuf[nbufptr++] = cr[j]; - } - else { - // copy verbatim in binary mode. - nbuf[nbufptr++] = buf[i]; - } - - break; - - // all other characters are just copied - default: - nbuf[nbufptr++] = buf[i]; - break; - } - } - - xbuf = new byte[nbufptr]; - System.arraycopy(nbuf, 0, xbuf, 0, nbufptr); - write(xbuf); - } - - public void setCRLF(String xcrlf) { crlf = xcrlf.getBytes(); } - public void setCR(String xcr) { cr = xcr.getBytes(); } - - /** - * Handle telnet protocol negotiation. The buffer will be parsed - * and necessary actions are taken according to the telnet protocol. - * See <A HREF="RFC-Telnet-URL">RFC-Telnet</A> - * @param nbuf the byte buffer put out after negotiation - * @return number of bytes processed, 0 for none, and -1 for end of buffer. - */ - public int negotiate(byte nbuf[], int offset) - throws IOException { - int count = tempbuf.length; - byte[] buf = tempbuf; - byte sendbuf[] = new byte[3]; - byte b, reply; - int boffset = 0, noffset = offset; - boolean dobreak = false; - - if (count == 0) // buffer is empty. - return -1; - - while (!dobreak && (boffset < count) && (noffset < nbuf.length)) { - b = buf[boffset++]; - - // of course, byte is a signed entity (-128 -> 127) - // but apparently the SGI Netscape 3.0 doesn't seem - // to care and provides happily values up to 255 - if (b >= 128) - b = (byte)(b - 256); - - if (debug > 2) { - Byte B = new Byte(b); - System.err.print("byte: " + B.intValue() + " "); - } - - switch (neg_state) { - case STATE_DATA: - if (b == IAC) { - neg_state = STATE_IAC; - dobreak = true; // leave the loop so we can sync. - } - else - nbuf[noffset++] = b; - - break; - - case STATE_IAC: - switch (b) { - case IAC: - if (debug > 2) System.err.print("IAC "); - - neg_state = STATE_DATA; - nbuf[noffset++] = IAC; - break; - - case WILL: - if (debug > 2) System.err.print("WILL "); - - neg_state = STATE_IACWILL; - break; - - case WONT: - if (debug > 2) System.err.print("WONT "); - - neg_state = STATE_IACWONT; - break; - - case DONT: - if (debug > 2) System.err.print("DONT "); - - neg_state = STATE_IACDONT; - break; - - case DO: - if (debug > 2) System.err.print("DO "); - - neg_state = STATE_IACDO; - break; - - case EOR: - if (debug > 1) System.err.print("EOR "); - - notifyEndOfRecord(); - dobreak = true; // leave the loop so we can sync. - neg_state = STATE_DATA; - break; - - case SB: - if (debug > 2) System.err.print("SB "); - - neg_state = STATE_IACSB; - break; - - default: - if (debug > 2) System.err.print("<UNKNOWN " + b + " > "); - - neg_state = STATE_DATA; - break; - } - - break; - - case STATE_IACWILL: - switch (b) { - case TELOPT_ECHO: - if (debug > 2) System.err.println("ECHO"); - - reply = DO; - setLocalEcho(false); - break; - - case TELOPT_SGA: - if (debug > 2) System.err.println("SGA"); - - reply = DO; - break; - - case TELOPT_EOR: - if (debug > 2) System.err.println("EOR"); - - reply = DO; - break; - - case TELOPT_BINARY: - if (debug > 2) System.err.println("BINARY"); - - reply = DO; - break; - - default: - if (debug > 2) System.err.println("<UNKNOWN," + b + ">"); - - reply = DONT; - break; - } - - if (debug > 1) System.err.println("<" + b + ", WILL =" + WILL + ">"); - - if (reply != sentDX[b + 128] || WILL != receivedWX[b + 128]) { - sendbuf[0] = IAC; - sendbuf[1] = reply; - sendbuf[2] = b; - write(sendbuf); - sentDX[b + 128] = reply; - receivedWX[b + 128] = WILL; - } - - neg_state = STATE_DATA; - break; - - case STATE_IACWONT: - switch (b) { - case TELOPT_ECHO: - if (debug > 2) System.err.println("ECHO"); - - setLocalEcho(true); - reply = DONT; - break; - - case TELOPT_SGA: - if (debug > 2) System.err.println("SGA"); - - reply = DONT; - break; - - case TELOPT_EOR: - if (debug > 2) System.err.println("EOR"); - - reply = DONT; - break; - - case TELOPT_BINARY: - if (debug > 2) System.err.println("BINARY"); - - reply = DONT; - break; - - default: - if (debug > 2) System.err.println("<UNKNOWN," + b + ">"); - - reply = DONT; - break; - } - - if (reply != sentDX[b + 128] || WONT != receivedWX[b + 128]) { - sendbuf[0] = IAC; - sendbuf[1] = reply; - sendbuf[2] = b; - write(sendbuf); - sentDX[b + 128] = reply; - receivedWX[b + 128] = WILL; - } - - neg_state = STATE_DATA; - break; - - case STATE_IACDO: - switch (b) { - case TELOPT_ECHO: - if (debug > 2) System.err.println("ECHO"); - - reply = WILL; - setLocalEcho(true); - break; - - case TELOPT_SGA: - if (debug > 2) System.err.println("SGA"); - - reply = WILL; - break; - - case TELOPT_TTYPE: - if (debug > 2) System.err.println("TTYPE"); - - reply = WILL; - break; - - case TELOPT_BINARY: - if (debug > 2) System.err.println("BINARY"); - - reply = WILL; - break; - - case TELOPT_NAWS: - if (debug > 2) System.err.println("NAWS"); - - int[] size = getWindowSize(); - receivedDX[b] = DO; - - if (size == null) { - // this shouldn't happen - write(IAC); - write(WONT); - write(TELOPT_NAWS); - reply = WONT; - sentWX[b] = WONT; - break; - } - - reply = WILL; - sentWX[b] = WILL; - sendbuf[0] = IAC; - sendbuf[1] = WILL; - sendbuf[2] = TELOPT_NAWS; - write(sendbuf); - write(IAC); write(SB); write(TELOPT_NAWS); - write((byte)(size[0] >> 8)); - write((byte)(size[0] & 0xff)); - write((byte)(size[1] >> 8)); - write((byte)(size[1] & 0xff)); - write(IAC); write(SE); - break; - - default: - if (debug > 2) System.err.println("<UNKNOWN," + b + ">"); - - reply = WONT; - break; - } - - if (reply != sentWX[128 + b] || DO != receivedDX[128 + b]) { - sendbuf[0] = IAC; - sendbuf[1] = reply; - sendbuf[2] = b; - write(sendbuf); - sentWX[b + 128] = reply; - receivedDX[b + 128] = DO; - } - - neg_state = STATE_DATA; - break; - - case STATE_IACDONT: - switch (b) { - case TELOPT_ECHO: - if (debug > 2) System.err.println("ECHO"); - - reply = WONT; - setLocalEcho(false); - break; - - case TELOPT_SGA: - if (debug > 2) System.err.println("SGA"); - - reply = WONT; - break; - - case TELOPT_NAWS: - if (debug > 2) System.err.println("NAWS"); - - reply = WONT; - break; - - case TELOPT_BINARY: - if (debug > 2) System.err.println("BINARY"); - - reply = WONT; - break; - - default: - if (debug > 2) System.err.println("<UNKNOWN," + b + ">"); - - reply = WONT; - break; - } - - if (reply != sentWX[b + 128] || DONT != receivedDX[b + 128]) { - write(IAC); write(reply); write(b); - sentWX[b + 128] = reply; - receivedDX[b + 128] = DONT; - } - - neg_state = STATE_DATA; - break; - - case STATE_IACSBIAC: - if (debug > 2) System.err.println("" + b + " "); - - if (b == IAC) { - sbbuf = new byte[0]; - current_sb = b; - neg_state = STATE_IACSBDATA; - } - else { - System.err.println("(bad) " + b + " "); - neg_state = STATE_DATA; - } - - break; - - case STATE_IACSB: - if (debug > 2) System.err.println("" + b + " "); - - switch (b) { - case IAC: - neg_state = STATE_IACSBIAC; - break; - - default: - current_sb = b; - sbbuf = new byte[0]; - neg_state = STATE_IACSBDATA; - break; - } - - break; - - case STATE_IACSBDATA: - if (debug > 2) System.err.println("" + b + " "); - - switch (b) { - case IAC: - neg_state = STATE_IACSBDATAIAC; - break; - - default: - byte[] xsb = new byte[sbbuf.length + 1]; - System.arraycopy(sbbuf, 0, xsb, 0, sbbuf.length); - sbbuf = xsb; - sbbuf[sbbuf.length - 1] = b; - break; - } - - break; - - case STATE_IACSBDATAIAC: - if (debug > 2) System.err.println("" + b + " "); - - switch (b) { - case IAC: - neg_state = STATE_IACSBDATA; - byte[] xsb = new byte[sbbuf.length + 1]; - System.arraycopy(sbbuf, 0, xsb, 0, sbbuf.length); - sbbuf = xsb; - sbbuf[sbbuf.length - 1] = IAC; - break; - - case SE: - handle_sb(current_sb, sbbuf); - current_sb = 0; - neg_state = STATE_DATA; - break; - - case SB: - handle_sb(current_sb, sbbuf); - neg_state = STATE_IACSB; - break; - - default: - neg_state = STATE_DATA; - break; - } - - break; - - default: - if (debug > 1) - System.err.println("This should not happen: " + neg_state + " "); - - neg_state = STATE_DATA; - break; - } - } - - // shrink tempbuf to new processed size. - byte[] xb = new byte[count - boffset]; - System.arraycopy(tempbuf, boffset, xb, 0, count - boffset); - tempbuf = xb; - return noffset - offset; - } - - public void inputfeed(byte[] b, int offset, int len) { - byte[] xb = new byte[tempbuf.length + len]; - System.arraycopy(tempbuf, 0, xb, 0, tempbuf.length); - System.arraycopy(b, offset, xb, tempbuf.length, len); - tempbuf = xb; - } -}
--- a/src/de/mud/terminal/Precomposer.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1052 +0,0 @@ -/* - * ConnectBot: simple, powerful, open-source SSH client for Android - * Copyright 2007 Kenny Root, Jeffrey Sharkey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package de.mud.terminal; - -/** - * @author Kenny Root - * This data was taken from xterm's precompose.c - */ -public class Precomposer { - public final static char precompositions[][] = { - { 0x226E, 0x003C, 0x0338}, - { 0x2260, 0x003D, 0x0338}, - { 0x226F, 0x003E, 0x0338}, - { 0x00C0, 0x0041, 0x0300}, - { 0x00C1, 0x0041, 0x0301}, - { 0x00C2, 0x0041, 0x0302}, - { 0x00C3, 0x0041, 0x0303}, - { 0x0100, 0x0041, 0x0304}, - { 0x0102, 0x0041, 0x0306}, - { 0x0226, 0x0041, 0x0307}, - { 0x00C4, 0x0041, 0x0308}, - { 0x1EA2, 0x0041, 0x0309}, - { 0x00C5, 0x0041, 0x030A}, - { 0x01CD, 0x0041, 0x030C}, - { 0x0200, 0x0041, 0x030F}, - { 0x0202, 0x0041, 0x0311}, - { 0x1EA0, 0x0041, 0x0323}, - { 0x1E00, 0x0041, 0x0325}, - { 0x0104, 0x0041, 0x0328}, - { 0x1E02, 0x0042, 0x0307}, - { 0x1E04, 0x0042, 0x0323}, - { 0x1E06, 0x0042, 0x0331}, - { 0x0106, 0x0043, 0x0301}, - { 0x0108, 0x0043, 0x0302}, - { 0x010A, 0x0043, 0x0307}, - { 0x010C, 0x0043, 0x030C}, - { 0x00C7, 0x0043, 0x0327}, - { 0x1E0A, 0x0044, 0x0307}, - { 0x010E, 0x0044, 0x030C}, - { 0x1E0C, 0x0044, 0x0323}, - { 0x1E10, 0x0044, 0x0327}, - { 0x1E12, 0x0044, 0x032D}, - { 0x1E0E, 0x0044, 0x0331}, - { 0x00C8, 0x0045, 0x0300}, - { 0x00C9, 0x0045, 0x0301}, - { 0x00CA, 0x0045, 0x0302}, - { 0x1EBC, 0x0045, 0x0303}, - { 0x0112, 0x0045, 0x0304}, - { 0x0114, 0x0045, 0x0306}, - { 0x0116, 0x0045, 0x0307}, - { 0x00CB, 0x0045, 0x0308}, - { 0x1EBA, 0x0045, 0x0309}, - { 0x011A, 0x0045, 0x030C}, - { 0x0204, 0x0045, 0x030F}, - { 0x0206, 0x0045, 0x0311}, - { 0x1EB8, 0x0045, 0x0323}, - { 0x0228, 0x0045, 0x0327}, - { 0x0118, 0x0045, 0x0328}, - { 0x1E18, 0x0045, 0x032D}, - { 0x1E1A, 0x0045, 0x0330}, - { 0x1E1E, 0x0046, 0x0307}, - { 0x01F4, 0x0047, 0x0301}, - { 0x011C, 0x0047, 0x0302}, - { 0x1E20, 0x0047, 0x0304}, - { 0x011E, 0x0047, 0x0306}, - { 0x0120, 0x0047, 0x0307}, - { 0x01E6, 0x0047, 0x030C}, - { 0x0122, 0x0047, 0x0327}, - { 0x0124, 0x0048, 0x0302}, - { 0x1E22, 0x0048, 0x0307}, - { 0x1E26, 0x0048, 0x0308}, - { 0x021E, 0x0048, 0x030C}, - { 0x1E24, 0x0048, 0x0323}, - { 0x1E28, 0x0048, 0x0327}, - { 0x1E2A, 0x0048, 0x032E}, - { 0x00CC, 0x0049, 0x0300}, - { 0x00CD, 0x0049, 0x0301}, - { 0x00CE, 0x0049, 0x0302}, - { 0x0128, 0x0049, 0x0303}, - { 0x012A, 0x0049, 0x0304}, - { 0x012C, 0x0049, 0x0306}, - { 0x0130, 0x0049, 0x0307}, - { 0x00CF, 0x0049, 0x0308}, - { 0x1EC8, 0x0049, 0x0309}, - { 0x01CF, 0x0049, 0x030C}, - { 0x0208, 0x0049, 0x030F}, - { 0x020A, 0x0049, 0x0311}, - { 0x1ECA, 0x0049, 0x0323}, - { 0x012E, 0x0049, 0x0328}, - { 0x1E2C, 0x0049, 0x0330}, - { 0x0134, 0x004A, 0x0302}, - { 0x1E30, 0x004B, 0x0301}, - { 0x01E8, 0x004B, 0x030C}, - { 0x1E32, 0x004B, 0x0323}, - { 0x0136, 0x004B, 0x0327}, - { 0x1E34, 0x004B, 0x0331}, - { 0x0139, 0x004C, 0x0301}, - { 0x013D, 0x004C, 0x030C}, - { 0x1E36, 0x004C, 0x0323}, - { 0x013B, 0x004C, 0x0327}, - { 0x1E3C, 0x004C, 0x032D}, - { 0x1E3A, 0x004C, 0x0331}, - { 0x1E3E, 0x004D, 0x0301}, - { 0x1E40, 0x004D, 0x0307}, - { 0x1E42, 0x004D, 0x0323}, - { 0x01F8, 0x004E, 0x0300}, - { 0x0143, 0x004E, 0x0301}, - { 0x00D1, 0x004E, 0x0303}, - { 0x1E44, 0x004E, 0x0307}, - { 0x0147, 0x004E, 0x030C}, - { 0x1E46, 0x004E, 0x0323}, - { 0x0145, 0x004E, 0x0327}, - { 0x1E4A, 0x004E, 0x032D}, - { 0x1E48, 0x004E, 0x0331}, - { 0x00D2, 0x004F, 0x0300}, - { 0x00D3, 0x004F, 0x0301}, - { 0x00D4, 0x004F, 0x0302}, - { 0x00D5, 0x004F, 0x0303}, - { 0x014C, 0x004F, 0x0304}, - { 0x014E, 0x004F, 0x0306}, - { 0x022E, 0x004F, 0x0307}, - { 0x00D6, 0x004F, 0x0308}, - { 0x1ECE, 0x004F, 0x0309}, - { 0x0150, 0x004F, 0x030B}, - { 0x01D1, 0x004F, 0x030C}, - { 0x020C, 0x004F, 0x030F}, - { 0x020E, 0x004F, 0x0311}, - { 0x01A0, 0x004F, 0x031B}, - { 0x1ECC, 0x004F, 0x0323}, - { 0x01EA, 0x004F, 0x0328}, - { 0x1E54, 0x0050, 0x0301}, - { 0x1E56, 0x0050, 0x0307}, - { 0x0154, 0x0052, 0x0301}, - { 0x1E58, 0x0052, 0x0307}, - { 0x0158, 0x0052, 0x030C}, - { 0x0210, 0x0052, 0x030F}, - { 0x0212, 0x0052, 0x0311}, - { 0x1E5A, 0x0052, 0x0323}, - { 0x0156, 0x0052, 0x0327}, - { 0x1E5E, 0x0052, 0x0331}, - { 0x015A, 0x0053, 0x0301}, - { 0x015C, 0x0053, 0x0302}, - { 0x1E60, 0x0053, 0x0307}, - { 0x0160, 0x0053, 0x030C}, - { 0x1E62, 0x0053, 0x0323}, - { 0x0218, 0x0053, 0x0326}, - { 0x015E, 0x0053, 0x0327}, - { 0x1E6A, 0x0054, 0x0307}, - { 0x0164, 0x0054, 0x030C}, - { 0x1E6C, 0x0054, 0x0323}, - { 0x021A, 0x0054, 0x0326}, - { 0x0162, 0x0054, 0x0327}, - { 0x1E70, 0x0054, 0x032D}, - { 0x1E6E, 0x0054, 0x0331}, - { 0x00D9, 0x0055, 0x0300}, - { 0x00DA, 0x0055, 0x0301}, - { 0x00DB, 0x0055, 0x0302}, - { 0x0168, 0x0055, 0x0303}, - { 0x016A, 0x0055, 0x0304}, - { 0x016C, 0x0055, 0x0306}, - { 0x00DC, 0x0055, 0x0308}, - { 0x1EE6, 0x0055, 0x0309}, - { 0x016E, 0x0055, 0x030A}, - { 0x0170, 0x0055, 0x030B}, - { 0x01D3, 0x0055, 0x030C}, - { 0x0214, 0x0055, 0x030F}, - { 0x0216, 0x0055, 0x0311}, - { 0x01AF, 0x0055, 0x031B}, - { 0x1EE4, 0x0055, 0x0323}, - { 0x1E72, 0x0055, 0x0324}, - { 0x0172, 0x0055, 0x0328}, - { 0x1E76, 0x0055, 0x032D}, - { 0x1E74, 0x0055, 0x0330}, - { 0x1E7C, 0x0056, 0x0303}, - { 0x1E7E, 0x0056, 0x0323}, - { 0x1E80, 0x0057, 0x0300}, - { 0x1E82, 0x0057, 0x0301}, - { 0x0174, 0x0057, 0x0302}, - { 0x1E86, 0x0057, 0x0307}, - { 0x1E84, 0x0057, 0x0308}, - { 0x1E88, 0x0057, 0x0323}, - { 0x1E8A, 0x0058, 0x0307}, - { 0x1E8C, 0x0058, 0x0308}, - { 0x1EF2, 0x0059, 0x0300}, - { 0x00DD, 0x0059, 0x0301}, - { 0x0176, 0x0059, 0x0302}, - { 0x1EF8, 0x0059, 0x0303}, - { 0x0232, 0x0059, 0x0304}, - { 0x1E8E, 0x0059, 0x0307}, - { 0x0178, 0x0059, 0x0308}, - { 0x1EF6, 0x0059, 0x0309}, - { 0x1EF4, 0x0059, 0x0323}, - { 0x0179, 0x005A, 0x0301}, - { 0x1E90, 0x005A, 0x0302}, - { 0x017B, 0x005A, 0x0307}, - { 0x017D, 0x005A, 0x030C}, - { 0x1E92, 0x005A, 0x0323}, - { 0x1E94, 0x005A, 0x0331}, - { 0x00E0, 0x0061, 0x0300}, - { 0x00E1, 0x0061, 0x0301}, - { 0x00E2, 0x0061, 0x0302}, - { 0x00E3, 0x0061, 0x0303}, - { 0x0101, 0x0061, 0x0304}, - { 0x0103, 0x0061, 0x0306}, - { 0x0227, 0x0061, 0x0307}, - { 0x00E4, 0x0061, 0x0308}, - { 0x1EA3, 0x0061, 0x0309}, - { 0x00E5, 0x0061, 0x030A}, - { 0x01CE, 0x0061, 0x030C}, - { 0x0201, 0x0061, 0x030F}, - { 0x0203, 0x0061, 0x0311}, - { 0x1EA1, 0x0061, 0x0323}, - { 0x1E01, 0x0061, 0x0325}, - { 0x0105, 0x0061, 0x0328}, - { 0x1E03, 0x0062, 0x0307}, - { 0x1E05, 0x0062, 0x0323}, - { 0x1E07, 0x0062, 0x0331}, - { 0x0107, 0x0063, 0x0301}, - { 0x0109, 0x0063, 0x0302}, - { 0x010B, 0x0063, 0x0307}, - { 0x010D, 0x0063, 0x030C}, - { 0x00E7, 0x0063, 0x0327}, - { 0x1E0B, 0x0064, 0x0307}, - { 0x010F, 0x0064, 0x030C}, - { 0x1E0D, 0x0064, 0x0323}, - { 0x1E11, 0x0064, 0x0327}, - { 0x1E13, 0x0064, 0x032D}, - { 0x1E0F, 0x0064, 0x0331}, - { 0x00E8, 0x0065, 0x0300}, - { 0x00E9, 0x0065, 0x0301}, - { 0x00EA, 0x0065, 0x0302}, - { 0x1EBD, 0x0065, 0x0303}, - { 0x0113, 0x0065, 0x0304}, - { 0x0115, 0x0065, 0x0306}, - { 0x0117, 0x0065, 0x0307}, - { 0x00EB, 0x0065, 0x0308}, - { 0x1EBB, 0x0065, 0x0309}, - { 0x011B, 0x0065, 0x030C}, - { 0x0205, 0x0065, 0x030F}, - { 0x0207, 0x0065, 0x0311}, - { 0x1EB9, 0x0065, 0x0323}, - { 0x0229, 0x0065, 0x0327}, - { 0x0119, 0x0065, 0x0328}, - { 0x1E19, 0x0065, 0x032D}, - { 0x1E1B, 0x0065, 0x0330}, - { 0x1E1F, 0x0066, 0x0307}, - { 0x01F5, 0x0067, 0x0301}, - { 0x011D, 0x0067, 0x0302}, - { 0x1E21, 0x0067, 0x0304}, - { 0x011F, 0x0067, 0x0306}, - { 0x0121, 0x0067, 0x0307}, - { 0x01E7, 0x0067, 0x030C}, - { 0x0123, 0x0067, 0x0327}, - { 0x0125, 0x0068, 0x0302}, - { 0x1E23, 0x0068, 0x0307}, - { 0x1E27, 0x0068, 0x0308}, - { 0x021F, 0x0068, 0x030C}, - { 0x1E25, 0x0068, 0x0323}, - { 0x1E29, 0x0068, 0x0327}, - { 0x1E2B, 0x0068, 0x032E}, - { 0x1E96, 0x0068, 0x0331}, - { 0x00EC, 0x0069, 0x0300}, - { 0x00ED, 0x0069, 0x0301}, - { 0x00EE, 0x0069, 0x0302}, - { 0x0129, 0x0069, 0x0303}, - { 0x012B, 0x0069, 0x0304}, - { 0x012D, 0x0069, 0x0306}, - { 0x00EF, 0x0069, 0x0308}, - { 0x1EC9, 0x0069, 0x0309}, - { 0x01D0, 0x0069, 0x030C}, - { 0x0209, 0x0069, 0x030F}, - { 0x020B, 0x0069, 0x0311}, - { 0x1ECB, 0x0069, 0x0323}, - { 0x012F, 0x0069, 0x0328}, - { 0x1E2D, 0x0069, 0x0330}, - { 0x0135, 0x006A, 0x0302}, - { 0x01F0, 0x006A, 0x030C}, - { 0x1E31, 0x006B, 0x0301}, - { 0x01E9, 0x006B, 0x030C}, - { 0x1E33, 0x006B, 0x0323}, - { 0x0137, 0x006B, 0x0327}, - { 0x1E35, 0x006B, 0x0331}, - { 0x013A, 0x006C, 0x0301}, - { 0x013E, 0x006C, 0x030C}, - { 0x1E37, 0x006C, 0x0323}, - { 0x013C, 0x006C, 0x0327}, - { 0x1E3D, 0x006C, 0x032D}, - { 0x1E3B, 0x006C, 0x0331}, - { 0x1E3F, 0x006D, 0x0301}, - { 0x1E41, 0x006D, 0x0307}, - { 0x1E43, 0x006D, 0x0323}, - { 0x01F9, 0x006E, 0x0300}, - { 0x0144, 0x006E, 0x0301}, - { 0x00F1, 0x006E, 0x0303}, - { 0x1E45, 0x006E, 0x0307}, - { 0x0148, 0x006E, 0x030C}, - { 0x1E47, 0x006E, 0x0323}, - { 0x0146, 0x006E, 0x0327}, - { 0x1E4B, 0x006E, 0x032D}, - { 0x1E49, 0x006E, 0x0331}, - { 0x00F2, 0x006F, 0x0300}, - { 0x00F3, 0x006F, 0x0301}, - { 0x00F4, 0x006F, 0x0302}, - { 0x00F5, 0x006F, 0x0303}, - { 0x014D, 0x006F, 0x0304}, - { 0x014F, 0x006F, 0x0306}, - { 0x022F, 0x006F, 0x0307}, - { 0x00F6, 0x006F, 0x0308}, - { 0x1ECF, 0x006F, 0x0309}, - { 0x0151, 0x006F, 0x030B}, - { 0x01D2, 0x006F, 0x030C}, - { 0x020D, 0x006F, 0x030F}, - { 0x020F, 0x006F, 0x0311}, - { 0x01A1, 0x006F, 0x031B}, - { 0x1ECD, 0x006F, 0x0323}, - { 0x01EB, 0x006F, 0x0328}, - { 0x1E55, 0x0070, 0x0301}, - { 0x1E57, 0x0070, 0x0307}, - { 0x0155, 0x0072, 0x0301}, - { 0x1E59, 0x0072, 0x0307}, - { 0x0159, 0x0072, 0x030C}, - { 0x0211, 0x0072, 0x030F}, - { 0x0213, 0x0072, 0x0311}, - { 0x1E5B, 0x0072, 0x0323}, - { 0x0157, 0x0072, 0x0327}, - { 0x1E5F, 0x0072, 0x0331}, - { 0x015B, 0x0073, 0x0301}, - { 0x015D, 0x0073, 0x0302}, - { 0x1E61, 0x0073, 0x0307}, - { 0x0161, 0x0073, 0x030C}, - { 0x1E63, 0x0073, 0x0323}, - { 0x0219, 0x0073, 0x0326}, - { 0x015F, 0x0073, 0x0327}, - { 0x1E6B, 0x0074, 0x0307}, - { 0x1E97, 0x0074, 0x0308}, - { 0x0165, 0x0074, 0x030C}, - { 0x1E6D, 0x0074, 0x0323}, - { 0x021B, 0x0074, 0x0326}, - { 0x0163, 0x0074, 0x0327}, - { 0x1E71, 0x0074, 0x032D}, - { 0x1E6F, 0x0074, 0x0331}, - { 0x00F9, 0x0075, 0x0300}, - { 0x00FA, 0x0075, 0x0301}, - { 0x00FB, 0x0075, 0x0302}, - { 0x0169, 0x0075, 0x0303}, - { 0x016B, 0x0075, 0x0304}, - { 0x016D, 0x0075, 0x0306}, - { 0x00FC, 0x0075, 0x0308}, - { 0x1EE7, 0x0075, 0x0309}, - { 0x016F, 0x0075, 0x030A}, - { 0x0171, 0x0075, 0x030B}, - { 0x01D4, 0x0075, 0x030C}, - { 0x0215, 0x0075, 0x030F}, - { 0x0217, 0x0075, 0x0311}, - { 0x01B0, 0x0075, 0x031B}, - { 0x1EE5, 0x0075, 0x0323}, - { 0x1E73, 0x0075, 0x0324}, - { 0x0173, 0x0075, 0x0328}, - { 0x1E77, 0x0075, 0x032D}, - { 0x1E75, 0x0075, 0x0330}, - { 0x1E7D, 0x0076, 0x0303}, - { 0x1E7F, 0x0076, 0x0323}, - { 0x1E81, 0x0077, 0x0300}, - { 0x1E83, 0x0077, 0x0301}, - { 0x0175, 0x0077, 0x0302}, - { 0x1E87, 0x0077, 0x0307}, - { 0x1E85, 0x0077, 0x0308}, - { 0x1E98, 0x0077, 0x030A}, - { 0x1E89, 0x0077, 0x0323}, - { 0x1E8B, 0x0078, 0x0307}, - { 0x1E8D, 0x0078, 0x0308}, - { 0x1EF3, 0x0079, 0x0300}, - { 0x00FD, 0x0079, 0x0301}, - { 0x0177, 0x0079, 0x0302}, - { 0x1EF9, 0x0079, 0x0303}, - { 0x0233, 0x0079, 0x0304}, - { 0x1E8F, 0x0079, 0x0307}, - { 0x00FF, 0x0079, 0x0308}, - { 0x1EF7, 0x0079, 0x0309}, - { 0x1E99, 0x0079, 0x030A}, - { 0x1EF5, 0x0079, 0x0323}, - { 0x017A, 0x007A, 0x0301}, - { 0x1E91, 0x007A, 0x0302}, - { 0x017C, 0x007A, 0x0307}, - { 0x017E, 0x007A, 0x030C}, - { 0x1E93, 0x007A, 0x0323}, - { 0x1E95, 0x007A, 0x0331}, - { 0x1FED, 0x00A8, 0x0300}, - { 0x0385, 0x00A8, 0x0301}, - { 0x1FC1, 0x00A8, 0x0342}, - { 0x1EA6, 0x00C2, 0x0300}, - { 0x1EA4, 0x00C2, 0x0301}, - { 0x1EAA, 0x00C2, 0x0303}, - { 0x1EA8, 0x00C2, 0x0309}, - { 0x01DE, 0x00C4, 0x0304}, - { 0x01FA, 0x00C5, 0x0301}, - { 0x01FC, 0x00C6, 0x0301}, - { 0x01E2, 0x00C6, 0x0304}, - { 0x1E08, 0x00C7, 0x0301}, - { 0x1EC0, 0x00CA, 0x0300}, - { 0x1EBE, 0x00CA, 0x0301}, - { 0x1EC4, 0x00CA, 0x0303}, - { 0x1EC2, 0x00CA, 0x0309}, - { 0x1E2E, 0x00CF, 0x0301}, - { 0x1ED2, 0x00D4, 0x0300}, - { 0x1ED0, 0x00D4, 0x0301}, - { 0x1ED6, 0x00D4, 0x0303}, - { 0x1ED4, 0x00D4, 0x0309}, - { 0x1E4C, 0x00D5, 0x0301}, - { 0x022C, 0x00D5, 0x0304}, - { 0x1E4E, 0x00D5, 0x0308}, - { 0x022A, 0x00D6, 0x0304}, - { 0x01FE, 0x00D8, 0x0301}, - { 0x01DB, 0x00DC, 0x0300}, - { 0x01D7, 0x00DC, 0x0301}, - { 0x01D5, 0x00DC, 0x0304}, - { 0x01D9, 0x00DC, 0x030C}, - { 0x1EA7, 0x00E2, 0x0300}, - { 0x1EA5, 0x00E2, 0x0301}, - { 0x1EAB, 0x00E2, 0x0303}, - { 0x1EA9, 0x00E2, 0x0309}, - { 0x01DF, 0x00E4, 0x0304}, - { 0x01FB, 0x00E5, 0x0301}, - { 0x01FD, 0x00E6, 0x0301}, - { 0x01E3, 0x00E6, 0x0304}, - { 0x1E09, 0x00E7, 0x0301}, - { 0x1EC1, 0x00EA, 0x0300}, - { 0x1EBF, 0x00EA, 0x0301}, - { 0x1EC5, 0x00EA, 0x0303}, - { 0x1EC3, 0x00EA, 0x0309}, - { 0x1E2F, 0x00EF, 0x0301}, - { 0x1ED3, 0x00F4, 0x0300}, - { 0x1ED1, 0x00F4, 0x0301}, - { 0x1ED7, 0x00F4, 0x0303}, - { 0x1ED5, 0x00F4, 0x0309}, - { 0x1E4D, 0x00F5, 0x0301}, - { 0x022D, 0x00F5, 0x0304}, - { 0x1E4F, 0x00F5, 0x0308}, - { 0x022B, 0x00F6, 0x0304}, - { 0x01FF, 0x00F8, 0x0301}, - { 0x01DC, 0x00FC, 0x0300}, - { 0x01D8, 0x00FC, 0x0301}, - { 0x01D6, 0x00FC, 0x0304}, - { 0x01DA, 0x00FC, 0x030C}, - { 0x1EB0, 0x0102, 0x0300}, - { 0x1EAE, 0x0102, 0x0301}, - { 0x1EB4, 0x0102, 0x0303}, - { 0x1EB2, 0x0102, 0x0309}, - { 0x1EB1, 0x0103, 0x0300}, - { 0x1EAF, 0x0103, 0x0301}, - { 0x1EB5, 0x0103, 0x0303}, - { 0x1EB3, 0x0103, 0x0309}, - { 0x1E14, 0x0112, 0x0300}, - { 0x1E16, 0x0112, 0x0301}, - { 0x1E15, 0x0113, 0x0300}, - { 0x1E17, 0x0113, 0x0301}, - { 0x1E50, 0x014C, 0x0300}, - { 0x1E52, 0x014C, 0x0301}, - { 0x1E51, 0x014D, 0x0300}, - { 0x1E53, 0x014D, 0x0301}, - { 0x1E64, 0x015A, 0x0307}, - { 0x1E65, 0x015B, 0x0307}, - { 0x1E66, 0x0160, 0x0307}, - { 0x1E67, 0x0161, 0x0307}, - { 0x1E78, 0x0168, 0x0301}, - { 0x1E79, 0x0169, 0x0301}, - { 0x1E7A, 0x016A, 0x0308}, - { 0x1E7B, 0x016B, 0x0308}, - { 0x1E9B, 0x017F, 0x0307}, - { 0x1EDC, 0x01A0, 0x0300}, - { 0x1EDA, 0x01A0, 0x0301}, - { 0x1EE0, 0x01A0, 0x0303}, - { 0x1EDE, 0x01A0, 0x0309}, - { 0x1EE2, 0x01A0, 0x0323}, - { 0x1EDD, 0x01A1, 0x0300}, - { 0x1EDB, 0x01A1, 0x0301}, - { 0x1EE1, 0x01A1, 0x0303}, - { 0x1EDF, 0x01A1, 0x0309}, - { 0x1EE3, 0x01A1, 0x0323}, - { 0x1EEA, 0x01AF, 0x0300}, - { 0x1EE8, 0x01AF, 0x0301}, - { 0x1EEE, 0x01AF, 0x0303}, - { 0x1EEC, 0x01AF, 0x0309}, - { 0x1EF0, 0x01AF, 0x0323}, - { 0x1EEB, 0x01B0, 0x0300}, - { 0x1EE9, 0x01B0, 0x0301}, - { 0x1EEF, 0x01B0, 0x0303}, - { 0x1EED, 0x01B0, 0x0309}, - { 0x1EF1, 0x01B0, 0x0323}, - { 0x01EE, 0x01B7, 0x030C}, - { 0x01EC, 0x01EA, 0x0304}, - { 0x01ED, 0x01EB, 0x0304}, - { 0x01E0, 0x0226, 0x0304}, - { 0x01E1, 0x0227, 0x0304}, - { 0x1E1C, 0x0228, 0x0306}, - { 0x1E1D, 0x0229, 0x0306}, - { 0x0230, 0x022E, 0x0304}, - { 0x0231, 0x022F, 0x0304}, - { 0x01EF, 0x0292, 0x030C}, - { 0x0344, 0x0308, 0x0301}, - { 0x1FBA, 0x0391, 0x0300}, - { 0x0386, 0x0391, 0x0301}, - { 0x1FB9, 0x0391, 0x0304}, - { 0x1FB8, 0x0391, 0x0306}, - { 0x1F08, 0x0391, 0x0313}, - { 0x1F09, 0x0391, 0x0314}, - { 0x1FBC, 0x0391, 0x0345}, - { 0x1FC8, 0x0395, 0x0300}, - { 0x0388, 0x0395, 0x0301}, - { 0x1F18, 0x0395, 0x0313}, - { 0x1F19, 0x0395, 0x0314}, - { 0x1FCA, 0x0397, 0x0300}, - { 0x0389, 0x0397, 0x0301}, - { 0x1F28, 0x0397, 0x0313}, - { 0x1F29, 0x0397, 0x0314}, - { 0x1FCC, 0x0397, 0x0345}, - { 0x1FDA, 0x0399, 0x0300}, - { 0x038A, 0x0399, 0x0301}, - { 0x1FD9, 0x0399, 0x0304}, - { 0x1FD8, 0x0399, 0x0306}, - { 0x03AA, 0x0399, 0x0308}, - { 0x1F38, 0x0399, 0x0313}, - { 0x1F39, 0x0399, 0x0314}, - { 0x1FF8, 0x039F, 0x0300}, - { 0x038C, 0x039F, 0x0301}, - { 0x1F48, 0x039F, 0x0313}, - { 0x1F49, 0x039F, 0x0314}, - { 0x1FEC, 0x03A1, 0x0314}, - { 0x1FEA, 0x03A5, 0x0300}, - { 0x038E, 0x03A5, 0x0301}, - { 0x1FE9, 0x03A5, 0x0304}, - { 0x1FE8, 0x03A5, 0x0306}, - { 0x03AB, 0x03A5, 0x0308}, - { 0x1F59, 0x03A5, 0x0314}, - { 0x1FFA, 0x03A9, 0x0300}, - { 0x038F, 0x03A9, 0x0301}, - { 0x1F68, 0x03A9, 0x0313}, - { 0x1F69, 0x03A9, 0x0314}, - { 0x1FFC, 0x03A9, 0x0345}, - { 0x1FB4, 0x03AC, 0x0345}, - { 0x1FC4, 0x03AE, 0x0345}, - { 0x1F70, 0x03B1, 0x0300}, - { 0x03AC, 0x03B1, 0x0301}, - { 0x1FB1, 0x03B1, 0x0304}, - { 0x1FB0, 0x03B1, 0x0306}, - { 0x1F00, 0x03B1, 0x0313}, - { 0x1F01, 0x03B1, 0x0314}, - { 0x1FB6, 0x03B1, 0x0342}, - { 0x1FB3, 0x03B1, 0x0345}, - { 0x1F72, 0x03B5, 0x0300}, - { 0x03AD, 0x03B5, 0x0301}, - { 0x1F10, 0x03B5, 0x0313}, - { 0x1F11, 0x03B5, 0x0314}, - { 0x1F74, 0x03B7, 0x0300}, - { 0x03AE, 0x03B7, 0x0301}, - { 0x1F20, 0x03B7, 0x0313}, - { 0x1F21, 0x03B7, 0x0314}, - { 0x1FC6, 0x03B7, 0x0342}, - { 0x1FC3, 0x03B7, 0x0345}, - { 0x1F76, 0x03B9, 0x0300}, - { 0x03AF, 0x03B9, 0x0301}, - { 0x1FD1, 0x03B9, 0x0304}, - { 0x1FD0, 0x03B9, 0x0306}, - { 0x03CA, 0x03B9, 0x0308}, - { 0x1F30, 0x03B9, 0x0313}, - { 0x1F31, 0x03B9, 0x0314}, - { 0x1FD6, 0x03B9, 0x0342}, - { 0x1F78, 0x03BF, 0x0300}, - { 0x03CC, 0x03BF, 0x0301}, - { 0x1F40, 0x03BF, 0x0313}, - { 0x1F41, 0x03BF, 0x0314}, - { 0x1FE4, 0x03C1, 0x0313}, - { 0x1FE5, 0x03C1, 0x0314}, - { 0x1F7A, 0x03C5, 0x0300}, - { 0x03CD, 0x03C5, 0x0301}, - { 0x1FE1, 0x03C5, 0x0304}, - { 0x1FE0, 0x03C5, 0x0306}, - { 0x03CB, 0x03C5, 0x0308}, - { 0x1F50, 0x03C5, 0x0313}, - { 0x1F51, 0x03C5, 0x0314}, - { 0x1FE6, 0x03C5, 0x0342}, - { 0x1F7C, 0x03C9, 0x0300}, - { 0x03CE, 0x03C9, 0x0301}, - { 0x1F60, 0x03C9, 0x0313}, - { 0x1F61, 0x03C9, 0x0314}, - { 0x1FF6, 0x03C9, 0x0342}, - { 0x1FF3, 0x03C9, 0x0345}, - { 0x1FD2, 0x03CA, 0x0300}, - { 0x0390, 0x03CA, 0x0301}, - { 0x1FD7, 0x03CA, 0x0342}, - { 0x1FE2, 0x03CB, 0x0300}, - { 0x03B0, 0x03CB, 0x0301}, - { 0x1FE7, 0x03CB, 0x0342}, - { 0x1FF4, 0x03CE, 0x0345}, - { 0x03D3, 0x03D2, 0x0301}, - { 0x03D4, 0x03D2, 0x0308}, - { 0x0407, 0x0406, 0x0308}, - { 0x04D0, 0x0410, 0x0306}, - { 0x04D2, 0x0410, 0x0308}, - { 0x0403, 0x0413, 0x0301}, - { 0x0400, 0x0415, 0x0300}, - { 0x04D6, 0x0415, 0x0306}, - { 0x0401, 0x0415, 0x0308}, - { 0x04C1, 0x0416, 0x0306}, - { 0x04DC, 0x0416, 0x0308}, - { 0x04DE, 0x0417, 0x0308}, - { 0x040D, 0x0418, 0x0300}, - { 0x04E2, 0x0418, 0x0304}, - { 0x0419, 0x0418, 0x0306}, - { 0x04E4, 0x0418, 0x0308}, - { 0x040C, 0x041A, 0x0301}, - { 0x04E6, 0x041E, 0x0308}, - { 0x04EE, 0x0423, 0x0304}, - { 0x040E, 0x0423, 0x0306}, - { 0x04F0, 0x0423, 0x0308}, - { 0x04F2, 0x0423, 0x030B}, - { 0x04F4, 0x0427, 0x0308}, - { 0x04F8, 0x042B, 0x0308}, - { 0x04EC, 0x042D, 0x0308}, - { 0x04D1, 0x0430, 0x0306}, - { 0x04D3, 0x0430, 0x0308}, - { 0x0453, 0x0433, 0x0301}, - { 0x0450, 0x0435, 0x0300}, - { 0x04D7, 0x0435, 0x0306}, - { 0x0451, 0x0435, 0x0308}, - { 0x04C2, 0x0436, 0x0306}, - { 0x04DD, 0x0436, 0x0308}, - { 0x04DF, 0x0437, 0x0308}, - { 0x045D, 0x0438, 0x0300}, - { 0x04E3, 0x0438, 0x0304}, - { 0x0439, 0x0438, 0x0306}, - { 0x04E5, 0x0438, 0x0308}, - { 0x045C, 0x043A, 0x0301}, - { 0x04E7, 0x043E, 0x0308}, - { 0x04EF, 0x0443, 0x0304}, - { 0x045E, 0x0443, 0x0306}, - { 0x04F1, 0x0443, 0x0308}, - { 0x04F3, 0x0443, 0x030B}, - { 0x04F5, 0x0447, 0x0308}, - { 0x04F9, 0x044B, 0x0308}, - { 0x04ED, 0x044D, 0x0308}, - { 0x0457, 0x0456, 0x0308}, - { 0x0476, 0x0474, 0x030F}, - { 0x0477, 0x0475, 0x030F}, - { 0x04DA, 0x04D8, 0x0308}, - { 0x04DB, 0x04D9, 0x0308}, - { 0x04EA, 0x04E8, 0x0308}, - { 0x04EB, 0x04E9, 0x0308}, - { 0xFB2E, 0x05D0, 0x05B7}, - { 0xFB2F, 0x05D0, 0x05B8}, - { 0xFB30, 0x05D0, 0x05BC}, - { 0xFB31, 0x05D1, 0x05BC}, - { 0xFB4C, 0x05D1, 0x05BF}, - { 0xFB32, 0x05D2, 0x05BC}, - { 0xFB33, 0x05D3, 0x05BC}, - { 0xFB34, 0x05D4, 0x05BC}, - { 0xFB4B, 0x05D5, 0x05B9}, - { 0xFB35, 0x05D5, 0x05BC}, - { 0xFB36, 0x05D6, 0x05BC}, - { 0xFB38, 0x05D8, 0x05BC}, - { 0xFB1D, 0x05D9, 0x05B4}, - { 0xFB39, 0x05D9, 0x05BC}, - { 0xFB3A, 0x05DA, 0x05BC}, - { 0xFB3B, 0x05DB, 0x05BC}, - { 0xFB4D, 0x05DB, 0x05BF}, - { 0xFB3C, 0x05DC, 0x05BC}, - { 0xFB3E, 0x05DE, 0x05BC}, - { 0xFB40, 0x05E0, 0x05BC}, - { 0xFB41, 0x05E1, 0x05BC}, - { 0xFB43, 0x05E3, 0x05BC}, - { 0xFB44, 0x05E4, 0x05BC}, - { 0xFB4E, 0x05E4, 0x05BF}, - { 0xFB46, 0x05E6, 0x05BC}, - { 0xFB47, 0x05E7, 0x05BC}, - { 0xFB48, 0x05E8, 0x05BC}, - { 0xFB49, 0x05E9, 0x05BC}, - { 0xFB2A, 0x05E9, 0x05C1}, - { 0xFB2B, 0x05E9, 0x05C2}, - { 0xFB4A, 0x05EA, 0x05BC}, - { 0xFB1F, 0x05F2, 0x05B7}, - { 0x0622, 0x0627, 0x0653}, - { 0x0623, 0x0627, 0x0654}, - { 0x0625, 0x0627, 0x0655}, - { 0x0624, 0x0648, 0x0654}, - { 0x0626, 0x064A, 0x0654}, - { 0x06C2, 0x06C1, 0x0654}, - { 0x06D3, 0x06D2, 0x0654}, - { 0x06C0, 0x06D5, 0x0654}, - { 0x0958, 0x0915, 0x093C}, - { 0x0959, 0x0916, 0x093C}, - { 0x095A, 0x0917, 0x093C}, - { 0x095B, 0x091C, 0x093C}, - { 0x095C, 0x0921, 0x093C}, - { 0x095D, 0x0922, 0x093C}, - { 0x0929, 0x0928, 0x093C}, - { 0x095E, 0x092B, 0x093C}, - { 0x095F, 0x092F, 0x093C}, - { 0x0931, 0x0930, 0x093C}, - { 0x0934, 0x0933, 0x093C}, - { 0x09DC, 0x09A1, 0x09BC}, - { 0x09DD, 0x09A2, 0x09BC}, - { 0x09DF, 0x09AF, 0x09BC}, - { 0x09CB, 0x09C7, 0x09BE}, - { 0x09CC, 0x09C7, 0x09D7}, - { 0x0A59, 0x0A16, 0x0A3C}, - { 0x0A5A, 0x0A17, 0x0A3C}, - { 0x0A5B, 0x0A1C, 0x0A3C}, - { 0x0A5E, 0x0A2B, 0x0A3C}, - { 0x0A33, 0x0A32, 0x0A3C}, - { 0x0A36, 0x0A38, 0x0A3C}, - { 0x0B5C, 0x0B21, 0x0B3C}, - { 0x0B5D, 0x0B22, 0x0B3C}, - { 0x0B4B, 0x0B47, 0x0B3E}, - { 0x0B48, 0x0B47, 0x0B56}, - { 0x0B4C, 0x0B47, 0x0B57}, - { 0x0B94, 0x0B92, 0x0BD7}, - { 0x0BCA, 0x0BC6, 0x0BBE}, - { 0x0BCC, 0x0BC6, 0x0BD7}, - { 0x0BCB, 0x0BC7, 0x0BBE}, - { 0x0C48, 0x0C46, 0x0C56}, - { 0x0CC0, 0x0CBF, 0x0CD5}, - { 0x0CCA, 0x0CC6, 0x0CC2}, - { 0x0CC7, 0x0CC6, 0x0CD5}, - { 0x0CC8, 0x0CC6, 0x0CD6}, - { 0x0CCB, 0x0CCA, 0x0CD5}, - { 0x0D4A, 0x0D46, 0x0D3E}, - { 0x0D4C, 0x0D46, 0x0D57}, - { 0x0D4B, 0x0D47, 0x0D3E}, - { 0x0DDA, 0x0DD9, 0x0DCA}, - { 0x0DDC, 0x0DD9, 0x0DCF}, - { 0x0DDE, 0x0DD9, 0x0DDF}, - { 0x0DDD, 0x0DDC, 0x0DCA}, - { 0x0F69, 0x0F40, 0x0FB5}, - { 0x0F43, 0x0F42, 0x0FB7}, - { 0x0F4D, 0x0F4C, 0x0FB7}, - { 0x0F52, 0x0F51, 0x0FB7}, - { 0x0F57, 0x0F56, 0x0FB7}, - { 0x0F5C, 0x0F5B, 0x0FB7}, - { 0x0F73, 0x0F71, 0x0F72}, - { 0x0F75, 0x0F71, 0x0F74}, - { 0x0F81, 0x0F71, 0x0F80}, - { 0x0FB9, 0x0F90, 0x0FB5}, - { 0x0F93, 0x0F92, 0x0FB7}, - { 0x0F9D, 0x0F9C, 0x0FB7}, - { 0x0FA2, 0x0FA1, 0x0FB7}, - { 0x0FA7, 0x0FA6, 0x0FB7}, - { 0x0FAC, 0x0FAB, 0x0FB7}, - { 0x0F76, 0x0FB2, 0x0F80}, - { 0x0F78, 0x0FB3, 0x0F80}, - { 0x1026, 0x1025, 0x102E}, - { 0x1B06, 0x1B05, 0x1B35}, - { 0x1B08, 0x1B07, 0x1B35}, - { 0x1B0A, 0x1B09, 0x1B35}, - { 0x1B0C, 0x1B0B, 0x1B35}, - { 0x1B0E, 0x1B0D, 0x1B35}, - { 0x1B12, 0x1B11, 0x1B35}, - { 0x1B3B, 0x1B3A, 0x1B35}, - { 0x1B3D, 0x1B3C, 0x1B35}, - { 0x1B40, 0x1B3E, 0x1B35}, - { 0x1B41, 0x1B3F, 0x1B35}, - { 0x1B43, 0x1B42, 0x1B35}, - { 0x1E38, 0x1E36, 0x0304}, - { 0x1E39, 0x1E37, 0x0304}, - { 0x1E5C, 0x1E5A, 0x0304}, - { 0x1E5D, 0x1E5B, 0x0304}, - { 0x1E68, 0x1E62, 0x0307}, - { 0x1E69, 0x1E63, 0x0307}, - { 0x1EAC, 0x1EA0, 0x0302}, - { 0x1EB6, 0x1EA0, 0x0306}, - { 0x1EAD, 0x1EA1, 0x0302}, - { 0x1EB7, 0x1EA1, 0x0306}, - { 0x1EC6, 0x1EB8, 0x0302}, - { 0x1EC7, 0x1EB9, 0x0302}, - { 0x1ED8, 0x1ECC, 0x0302}, - { 0x1ED9, 0x1ECD, 0x0302}, - { 0x1F02, 0x1F00, 0x0300}, - { 0x1F04, 0x1F00, 0x0301}, - { 0x1F06, 0x1F00, 0x0342}, - { 0x1F80, 0x1F00, 0x0345}, - { 0x1F03, 0x1F01, 0x0300}, - { 0x1F05, 0x1F01, 0x0301}, - { 0x1F07, 0x1F01, 0x0342}, - { 0x1F81, 0x1F01, 0x0345}, - { 0x1F82, 0x1F02, 0x0345}, - { 0x1F83, 0x1F03, 0x0345}, - { 0x1F84, 0x1F04, 0x0345}, - { 0x1F85, 0x1F05, 0x0345}, - { 0x1F86, 0x1F06, 0x0345}, - { 0x1F87, 0x1F07, 0x0345}, - { 0x1F0A, 0x1F08, 0x0300}, - { 0x1F0C, 0x1F08, 0x0301}, - { 0x1F0E, 0x1F08, 0x0342}, - { 0x1F88, 0x1F08, 0x0345}, - { 0x1F0B, 0x1F09, 0x0300}, - { 0x1F0D, 0x1F09, 0x0301}, - { 0x1F0F, 0x1F09, 0x0342}, - { 0x1F89, 0x1F09, 0x0345}, - { 0x1F8A, 0x1F0A, 0x0345}, - { 0x1F8B, 0x1F0B, 0x0345}, - { 0x1F8C, 0x1F0C, 0x0345}, - { 0x1F8D, 0x1F0D, 0x0345}, - { 0x1F8E, 0x1F0E, 0x0345}, - { 0x1F8F, 0x1F0F, 0x0345}, - { 0x1F12, 0x1F10, 0x0300}, - { 0x1F14, 0x1F10, 0x0301}, - { 0x1F13, 0x1F11, 0x0300}, - { 0x1F15, 0x1F11, 0x0301}, - { 0x1F1A, 0x1F18, 0x0300}, - { 0x1F1C, 0x1F18, 0x0301}, - { 0x1F1B, 0x1F19, 0x0300}, - { 0x1F1D, 0x1F19, 0x0301}, - { 0x1F22, 0x1F20, 0x0300}, - { 0x1F24, 0x1F20, 0x0301}, - { 0x1F26, 0x1F20, 0x0342}, - { 0x1F90, 0x1F20, 0x0345}, - { 0x1F23, 0x1F21, 0x0300}, - { 0x1F25, 0x1F21, 0x0301}, - { 0x1F27, 0x1F21, 0x0342}, - { 0x1F91, 0x1F21, 0x0345}, - { 0x1F92, 0x1F22, 0x0345}, - { 0x1F93, 0x1F23, 0x0345}, - { 0x1F94, 0x1F24, 0x0345}, - { 0x1F95, 0x1F25, 0x0345}, - { 0x1F96, 0x1F26, 0x0345}, - { 0x1F97, 0x1F27, 0x0345}, - { 0x1F2A, 0x1F28, 0x0300}, - { 0x1F2C, 0x1F28, 0x0301}, - { 0x1F2E, 0x1F28, 0x0342}, - { 0x1F98, 0x1F28, 0x0345}, - { 0x1F2B, 0x1F29, 0x0300}, - { 0x1F2D, 0x1F29, 0x0301}, - { 0x1F2F, 0x1F29, 0x0342}, - { 0x1F99, 0x1F29, 0x0345}, - { 0x1F9A, 0x1F2A, 0x0345}, - { 0x1F9B, 0x1F2B, 0x0345}, - { 0x1F9C, 0x1F2C, 0x0345}, - { 0x1F9D, 0x1F2D, 0x0345}, - { 0x1F9E, 0x1F2E, 0x0345}, - { 0x1F9F, 0x1F2F, 0x0345}, - { 0x1F32, 0x1F30, 0x0300}, - { 0x1F34, 0x1F30, 0x0301}, - { 0x1F36, 0x1F30, 0x0342}, - { 0x1F33, 0x1F31, 0x0300}, - { 0x1F35, 0x1F31, 0x0301}, - { 0x1F37, 0x1F31, 0x0342}, - { 0x1F3A, 0x1F38, 0x0300}, - { 0x1F3C, 0x1F38, 0x0301}, - { 0x1F3E, 0x1F38, 0x0342}, - { 0x1F3B, 0x1F39, 0x0300}, - { 0x1F3D, 0x1F39, 0x0301}, - { 0x1F3F, 0x1F39, 0x0342}, - { 0x1F42, 0x1F40, 0x0300}, - { 0x1F44, 0x1F40, 0x0301}, - { 0x1F43, 0x1F41, 0x0300}, - { 0x1F45, 0x1F41, 0x0301}, - { 0x1F4A, 0x1F48, 0x0300}, - { 0x1F4C, 0x1F48, 0x0301}, - { 0x1F4B, 0x1F49, 0x0300}, - { 0x1F4D, 0x1F49, 0x0301}, - { 0x1F52, 0x1F50, 0x0300}, - { 0x1F54, 0x1F50, 0x0301}, - { 0x1F56, 0x1F50, 0x0342}, - { 0x1F53, 0x1F51, 0x0300}, - { 0x1F55, 0x1F51, 0x0301}, - { 0x1F57, 0x1F51, 0x0342}, - { 0x1F5B, 0x1F59, 0x0300}, - { 0x1F5D, 0x1F59, 0x0301}, - { 0x1F5F, 0x1F59, 0x0342}, - { 0x1F62, 0x1F60, 0x0300}, - { 0x1F64, 0x1F60, 0x0301}, - { 0x1F66, 0x1F60, 0x0342}, - { 0x1FA0, 0x1F60, 0x0345}, - { 0x1F63, 0x1F61, 0x0300}, - { 0x1F65, 0x1F61, 0x0301}, - { 0x1F67, 0x1F61, 0x0342}, - { 0x1FA1, 0x1F61, 0x0345}, - { 0x1FA2, 0x1F62, 0x0345}, - { 0x1FA3, 0x1F63, 0x0345}, - { 0x1FA4, 0x1F64, 0x0345}, - { 0x1FA5, 0x1F65, 0x0345}, - { 0x1FA6, 0x1F66, 0x0345}, - { 0x1FA7, 0x1F67, 0x0345}, - { 0x1F6A, 0x1F68, 0x0300}, - { 0x1F6C, 0x1F68, 0x0301}, - { 0x1F6E, 0x1F68, 0x0342}, - { 0x1FA8, 0x1F68, 0x0345}, - { 0x1F6B, 0x1F69, 0x0300}, - { 0x1F6D, 0x1F69, 0x0301}, - { 0x1F6F, 0x1F69, 0x0342}, - { 0x1FA9, 0x1F69, 0x0345}, - { 0x1FAA, 0x1F6A, 0x0345}, - { 0x1FAB, 0x1F6B, 0x0345}, - { 0x1FAC, 0x1F6C, 0x0345}, - { 0x1FAD, 0x1F6D, 0x0345}, - { 0x1FAE, 0x1F6E, 0x0345}, - { 0x1FAF, 0x1F6F, 0x0345}, - { 0x1FB2, 0x1F70, 0x0345}, - { 0x1FC2, 0x1F74, 0x0345}, - { 0x1FF2, 0x1F7C, 0x0345}, - { 0x1FB7, 0x1FB6, 0x0345}, - { 0x1FCD, 0x1FBF, 0x0300}, - { 0x1FCE, 0x1FBF, 0x0301}, - { 0x1FCF, 0x1FBF, 0x0342}, - { 0x1FC7, 0x1FC6, 0x0345}, - { 0x1FF7, 0x1FF6, 0x0345}, - { 0x1FDD, 0x1FFE, 0x0300}, - { 0x1FDE, 0x1FFE, 0x0301}, - { 0x1FDF, 0x1FFE, 0x0342}, - { 0x219A, 0x2190, 0x0338}, - { 0x219B, 0x2192, 0x0338}, - { 0x21AE, 0x2194, 0x0338}, - { 0x21CD, 0x21D0, 0x0338}, - { 0x21CF, 0x21D2, 0x0338}, - { 0x21CE, 0x21D4, 0x0338}, - { 0x2204, 0x2203, 0x0338}, - { 0x2209, 0x2208, 0x0338}, - { 0x220C, 0x220B, 0x0338}, - { 0x2224, 0x2223, 0x0338}, - { 0x2226, 0x2225, 0x0338}, - { 0x2241, 0x223C, 0x0338}, - { 0x2244, 0x2243, 0x0338}, - { 0x2247, 0x2245, 0x0338}, - { 0x2249, 0x2248, 0x0338}, - { 0x226D, 0x224D, 0x0338}, - { 0x2262, 0x2261, 0x0338}, - { 0x2270, 0x2264, 0x0338}, - { 0x2271, 0x2265, 0x0338}, - { 0x2274, 0x2272, 0x0338}, - { 0x2275, 0x2273, 0x0338}, - { 0x2278, 0x2276, 0x0338}, - { 0x2279, 0x2277, 0x0338}, - { 0x2280, 0x227A, 0x0338}, - { 0x2281, 0x227B, 0x0338}, - { 0x22E0, 0x227C, 0x0338}, - { 0x22E1, 0x227D, 0x0338}, - { 0x2284, 0x2282, 0x0338}, - { 0x2285, 0x2283, 0x0338}, - { 0x2288, 0x2286, 0x0338}, - { 0x2289, 0x2287, 0x0338}, - { 0x22E2, 0x2291, 0x0338}, - { 0x22E3, 0x2292, 0x0338}, - { 0x22AC, 0x22A2, 0x0338}, - { 0x22AD, 0x22A8, 0x0338}, - { 0x22AE, 0x22A9, 0x0338}, - { 0x22AF, 0x22AB, 0x0338}, - { 0x22EA, 0x22B2, 0x0338}, - { 0x22EB, 0x22B3, 0x0338}, - { 0x22EC, 0x22B4, 0x0338}, - { 0x22ED, 0x22B5, 0x0338}, - { 0x2ADC, 0x2ADD, 0x0338}, - { 0x3094, 0x3046, 0x3099}, - { 0x304C, 0x304B, 0x3099}, - { 0x304E, 0x304D, 0x3099}, - { 0x3050, 0x304F, 0x3099}, - { 0x3052, 0x3051, 0x3099}, - { 0x3054, 0x3053, 0x3099}, - { 0x3056, 0x3055, 0x3099}, - { 0x3058, 0x3057, 0x3099}, - { 0x305A, 0x3059, 0x3099}, - { 0x305C, 0x305B, 0x3099}, - { 0x305E, 0x305D, 0x3099}, - { 0x3060, 0x305F, 0x3099}, - { 0x3062, 0x3061, 0x3099}, - { 0x3065, 0x3064, 0x3099}, - { 0x3067, 0x3066, 0x3099}, - { 0x3069, 0x3068, 0x3099}, - { 0x3070, 0x306F, 0x3099}, - { 0x3071, 0x306F, 0x309A}, - { 0x3073, 0x3072, 0x3099}, - { 0x3074, 0x3072, 0x309A}, - { 0x3076, 0x3075, 0x3099}, - { 0x3077, 0x3075, 0x309A}, - { 0x3079, 0x3078, 0x3099}, - { 0x307A, 0x3078, 0x309A}, - { 0x307C, 0x307B, 0x3099}, - { 0x307D, 0x307B, 0x309A}, - { 0x309E, 0x309D, 0x3099}, - { 0x30F4, 0x30A6, 0x3099}, - { 0x30AC, 0x30AB, 0x3099}, - { 0x30AE, 0x30AD, 0x3099}, - { 0x30B0, 0x30AF, 0x3099}, - { 0x30B2, 0x30B1, 0x3099}, - { 0x30B4, 0x30B3, 0x3099}, - { 0x30B6, 0x30B5, 0x3099}, - { 0x30B8, 0x30B7, 0x3099}, - { 0x30BA, 0x30B9, 0x3099}, - { 0x30BC, 0x30BB, 0x3099}, - { 0x30BE, 0x30BD, 0x3099}, - { 0x30C0, 0x30BF, 0x3099}, - { 0x30C2, 0x30C1, 0x3099}, - { 0x30C5, 0x30C4, 0x3099}, - { 0x30C7, 0x30C6, 0x3099}, - { 0x30C9, 0x30C8, 0x3099}, - { 0x30D0, 0x30CF, 0x3099}, - { 0x30D1, 0x30CF, 0x309A}, - { 0x30D3, 0x30D2, 0x3099}, - { 0x30D4, 0x30D2, 0x309A}, - { 0x30D6, 0x30D5, 0x3099}, - { 0x30D7, 0x30D5, 0x309A}, - { 0x30D9, 0x30D8, 0x3099}, - { 0x30DA, 0x30D8, 0x309A}, - { 0x30DC, 0x30DB, 0x3099}, - { 0x30DD, 0x30DB, 0x309A}, - { 0x30F7, 0x30EF, 0x3099}, - { 0x30F8, 0x30F0, 0x3099}, - { 0x30F9, 0x30F1, 0x3099}, - { 0x30FA, 0x30F2, 0x3099}, - { 0x30FE, 0x30FD, 0x3099}, - { 0xFB2C, 0xFB49, 0x05C1}, - { 0xFB2D, 0xFB49, 0x05C2}, - }; - - private static final int UNICODE_SHIFT = 21; - - public static char precompose(char base, char comb) { - int min = 0; - int max = precompositions.length - 1; - int mid; - long sought = base << UNICODE_SHIFT | comb; - long that; - - while (max >= min) { - mid = (min + max) / 2; - that = precompositions[mid][1] << UNICODE_SHIFT | precompositions[mid][2]; - - if (that < sought) - min = mid + 1; - else if (that > sought) - max = mid - 1; - else - return precompositions[mid][0]; - } - - // No match; return character without combiner - return base; - } -}
--- a/src/de/mud/terminal/VDUBuffer.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,880 +0,0 @@ -/* - * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". - * - * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved. - * - * Please visit http://javatelnet.org/ for updates and contact. - * - * --LICENSE NOTICE-- - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * --LICENSE NOTICE-- - * - */ - -package de.mud.terminal; - -import java.util.Arrays; - -/** - * Implementation of a Video Display Unit (VDU) buffer. This class contains - * all methods to manipulate the buffer that stores characters and their - * attributes as well as the regions displayed. - * - * @author Matthias L. Jugel, Marcus Meißner - * @version $Id: VDUBuffer.java 503 2005-10-24 07:34:13Z marcus $ - */ -public class VDUBuffer { - - /** a generic display that should redraw on demand */ - protected VDUDisplay display; - - /** Enable debug messages. */ - public final static int debug = 0; - - public int height, width; /* rows and columns */ - public boolean[] update; /* contains the lines that need update */ - public char[][] charArray; /* contains the characters */ - public int[][] charAttributes; /* contains character attrs */ - public int bufSize; - public int maxBufSize; /* buffer sizes */ - public int screenBase; /* the actual screen start */ - public int windowBase; /* where the start displaying */ - public int scrollMarker; /* marks the last line inserted */ - - private int topMargin; /* top scroll margin */ - private int bottomMargin; /* bottom scroll margin */ - - // cursor variables - protected boolean showcursor = true; - protected int cursorX, cursorY; - - /** Scroll up when inserting a line. */ - public final static boolean SCROLL_UP = false; - /** Scroll down when inserting a line. */ - public final static boolean SCROLL_DOWN = true; - - /* Attributes bit-field usage: - * - * 8421 8421 8421 8421 8421 8421 8421 8421 - * |||| |||| |||| |||| |||| |||| |||| |||`- Bold - * |||| |||| |||| |||| |||| |||| |||| ||`-- Underline - * |||| |||| |||| |||| |||| |||| |||| |`--- Invert - * |||| |||| |||| |||| |||| |||| |||| `---- Low - * |||| |||| |||| |||| |||| |||| |||`------ Invisible - * |||| |||| |||| |||| ||`+-++++-+++------- Foreground Color - * |||| |||| |`++-++++-++------------------ Background Color - * |||| |||| `----------------------------- Fullwidth character - * `+++-++++------------------------------- Reserved for future use - */ - - /** Make character normal. */ - public final static int NORMAL = 0x00; - /** Make character bold. */ - public final static int BOLD = 0x01; - /** Underline character. */ - public final static int UNDERLINE = 0x02; - /** Invert character. */ - public final static int INVERT = 0x04; - /** Lower intensity character. */ - public final static int LOW = 0x08; - /** Invisible character. */ - public final static int INVISIBLE = 0x10; - /** Unicode full-width character (CJK, et al.) */ - public final static int FULLWIDTH = 0x8000000; - - /** how much to left shift the foreground color */ - public final static int COLOR_FG_SHIFT = 5; - /** how much to left shift the background color */ - public final static int COLOR_BG_SHIFT = 14; - /** color mask */ - public final static int COLOR = 0x7fffe0; /* 0000 0000 0111 1111 1111 1111 1110 0000 */ - /** foreground color mask */ - public final static int COLOR_FG = 0x003fe0; /* 0000 0000 0000 0000 0011 1111 1110 0000 */ - /** background color mask */ - public final static int COLOR_BG = 0x7fc000; /* 0000 0000 0111 1111 1100 0000 0000 0000 */ - - /** - * Create a new video display buffer with the passed width and height in - * characters. - * @param width the length of the character lines - * @param height the amount of lines on the screen - */ - public VDUBuffer(int width, int height) { - // set the display screen size - setScreenSize(width, height, false); - } - - /** - * Create a standard video display buffer with 80 columns and 24 lines. - */ - public VDUBuffer() { - this(80, 24); - } - - /** - * Put a character on the screen with normal font and outline. - * The character previously on that position will be overwritten. - * You need to call redraw() to update the screen. - * @param c x-coordinate (column) - * @param l y-coordinate (line) - * @param ch the character to show on the screen - * @see #insertChar - * @see #deleteChar - * @see #redraw - */ - public void putChar(int c, int l, char ch) { - putChar(c, l, ch, NORMAL); - } - - /** - * Put a character on the screen with specific font and outline. - * The character previously on that position will be overwritten. - * You need to call redraw() to update the screen. - * @param c x-coordinate (column) - * @param l y-coordinate (line) - * @param ch the character to show on the screen - * @param attributes the character attributes - * @see #BOLD - * @see #UNDERLINE - * @see #INVERT - * @see #INVISIBLE - * @see #NORMAL - * @see #LOW - * @see #insertChar - * @see #deleteChar - * @see #redraw - */ - - public void putChar(int c, int l, char ch, int attributes) { - int ll = screenBase + l; - - if ((ll >= bufSize) || (c >= width)) return; // ignore characters outside our buffer - - charArray[ll][c] = ch; - charAttributes[ll][c] = attributes; - - if (l < height) - update[l + 1] = true; - } - - /** - * Get the character at the specified position. - * @param c x-coordinate (column) - * @param l y-coordinate (line) - * @see #putChar - */ - public char getChar(int c, int l) { - return charArray[screenBase + l][c]; - } - - /** - * Get the attributes for the specified position. - * @param c x-coordinate (column) - * @param l y-coordinate (line) - * @see #putChar - */ - public int getAttributes(int c, int l) { - return charAttributes[screenBase + l][c]; - } - - /** - * Insert a character at a specific position on the screen. - * All character right to from this position will be moved one to the right. - * You need to call redraw() to update the screen. - * @param c x-coordinate (column) - * @param l y-coordinate (line) - * @param ch the character to insert - * @param attributes the character attributes - * @see #BOLD - * @see #UNDERLINE - * @see #INVERT - * @see #INVISIBLE - * @see #NORMAL - * @see #LOW - * @see #putChar - * @see #deleteChar - * @see #redraw - */ - public void insertChar(int c, int l, char ch, int attributes) { - System.arraycopy(charArray[screenBase + l], c, - charArray[screenBase + l], c + 1, width - c - 1); - System.arraycopy(charAttributes[screenBase + l], c, - charAttributes[screenBase + l], c + 1, width - c - 1); - putChar(c, l, ch, attributes); - } - - /** - * Delete a character at a given position on the screen. - * All characters right to the position will be moved one to the left. - * You need to call redraw() to update the screen. - * @param c x-coordinate (column) - * @param l y-coordinate (line) - * @see #putChar - * @see #insertChar - * @see #redraw - */ - public void deleteChar(int c, int l) { - if (c < width - 1) { - System.arraycopy(charArray[screenBase + l], c + 1, - charArray[screenBase + l], c, width - c - 1); - System.arraycopy(charAttributes[screenBase + l], c + 1, - charAttributes[screenBase + l], c, width - c - 1); - } - - putChar(width - 1, l, (char) 0); - } - - /** - * Put a String at a specific position. Any characters previously on that - * position will be overwritten. You need to call redraw() for screen update. - * @param c x-coordinate (column) - * @param l y-coordinate (line) - * @param s the string to be shown on the screen - * @see #BOLD - * @see #UNDERLINE - * @see #INVERT - * @see #INVISIBLE - * @see #NORMAL - * @see #LOW - * @see #putChar - * @see #insertLine - * @see #deleteLine - * @see #redraw - */ - public void putString(int c, int l, String s) { - putString(c, l, s, NORMAL); - } - - /** - * Put a String at a specific position giving all characters the same - * attributes. Any characters previously on that position will be - * overwritten. You need to call redraw() to update the screen. - * @param c x-coordinate (column) - * @param l y-coordinate (line) - * @param s the string to be shown on the screen - * @param attributes character attributes - * @see #BOLD - * @see #UNDERLINE - * @see #INVERT - * @see #INVISIBLE - * @see #NORMAL - * @see #LOW - * @see #putChar - * @see #insertLine - * @see #deleteLine - * @see #redraw - */ - public void putString(int c, int l, String s, int attributes) { - for (int i = 0; i < s.length() && c + i < width; i++) - putChar(c + i, l, s.charAt(i), attributes); - } - - /** - * Insert a blank line at a specific position. - * The current line and all previous lines are scrolled one line up. The - * top line is lost. You need to call redraw() to update the screen. - * @param l the y-coordinate to insert the line - * @see #deleteLine - * @see #redraw - */ - public void insertLine(int l) { - insertLine(l, 1, SCROLL_UP); - } - - /** - * Insert blank lines at a specific position. - * You need to call redraw() to update the screen - * @param l the y-coordinate to insert the line - * @param n amount of lines to be inserted - * @see #deleteLine - * @see #redraw - */ - public void insertLine(int l, int n) { - insertLine(l, n, SCROLL_UP); - } - - /** - * Insert a blank line at a specific position. Scroll text according to - * the argument. - * You need to call redraw() to update the screen - * @param l the y-coordinate to insert the line - * @param scrollDown scroll down - * @see #deleteLine - * @see #SCROLL_UP - * @see #SCROLL_DOWN - * @see #redraw - */ - public void insertLine(int l, boolean scrollDown) { - insertLine(l, 1, scrollDown); - } - - /** - * Insert blank lines at a specific position. - * The current line and all previous lines are scrolled one line up. The - * top line is lost. You need to call redraw() to update the screen. - * @param l the y-coordinate to insert the line - * @param n number of lines to be inserted - * @param scrollDown scroll down - * @see #deleteLine - * @see #SCROLL_UP - * @see #SCROLL_DOWN - * @see #redraw - */ - - public synchronized void insertLine(int l, int n, boolean scrollDown) { - char cbuf[][] = null; - int abuf[][] = null; - int offset = 0; - int oldBase = screenBase; - int newScreenBase = screenBase; - int newWindowBase = windowBase; - int newBufSize = bufSize; - - if (l > bottomMargin) /* We do not scroll below bottom margin (below the scrolling region). */ - return; - - int top = (l < topMargin ? - 0 : (l > bottomMargin ? - (bottomMargin + 1 < height ? - bottomMargin + 1 : height - 1) : topMargin)); - int bottom = (l > bottomMargin ? - height - 1 : (l < topMargin ? - (topMargin > 0 ? - topMargin - 1 : 0) : bottomMargin)); - - // System.out.println("l is "+l+", top is "+top+", bottom is "+bottom+", bottomargin is "+bottomMargin+", topMargin is "+topMargin); - if (scrollDown) { - if (n > (bottom - top)) n = (bottom - top); - - int size = bottom - l - (n - 1); - - if (size < 0) size = 0; - - cbuf = new char[size][]; - abuf = new int[size][]; - System.arraycopy(charArray, oldBase + l, cbuf, 0, bottom - l - (n - 1)); - System.arraycopy(charAttributes, oldBase + l, - abuf, 0, bottom - l - (n - 1)); - System.arraycopy(cbuf, 0, charArray, oldBase + l + n, - bottom - l - (n - 1)); - System.arraycopy(abuf, 0, charAttributes, oldBase + l + n, - bottom - l - (n - 1)); - cbuf = charArray; - abuf = charAttributes; - } - else { - try { - if (n > (bottom - top) + 1) n = (bottom - top) + 1; - - if (bufSize < maxBufSize) { - if (bufSize + n > maxBufSize) { - offset = n - (maxBufSize - bufSize); - scrollMarker += offset; - newBufSize = maxBufSize; - newScreenBase = maxBufSize - height - 1; - newWindowBase = screenBase; - } - else { - scrollMarker += n; - newScreenBase += n; - newWindowBase += n; - newBufSize += n; - } - - cbuf = new char[newBufSize][]; - abuf = new int[newBufSize][]; - } - else { - offset = n; - cbuf = charArray; - abuf = charAttributes; - } - - // copy anything from the top of the buffer (+offset) to the new top - // up to the screenBase. - if (oldBase > 0) { - System.arraycopy(charArray, offset, - cbuf, 0, - oldBase - offset); - System.arraycopy(charAttributes, offset, - abuf, 0, - oldBase - offset); - } - - // copy anything from the top of the screen (screenBase) up to the - // topMargin to the new screen - if (top > 0) { - System.arraycopy(charArray, oldBase, - cbuf, newScreenBase, - top); - System.arraycopy(charAttributes, oldBase, - abuf, newScreenBase, - top); - } - - // copy anything from the topMargin up to the amount of lines inserted - // to the gap left over between scrollback buffer and screenBase - if (oldBase >= 0) { - System.arraycopy(charArray, oldBase + top, - cbuf, oldBase - offset, - n); - System.arraycopy(charAttributes, oldBase + top, - abuf, oldBase - offset, - n); - } - - // copy anything from topMargin + n up to the line linserted to the - // topMargin - System.arraycopy(charArray, oldBase + top + n, - cbuf, newScreenBase + top, - l - top - (n - 1)); - System.arraycopy(charAttributes, oldBase + top + n, - abuf, newScreenBase + top, - l - top - (n - 1)); - - // - // copy the all lines next to the inserted to the new buffer - if (l < height - 1) { - System.arraycopy(charArray, oldBase + l + 1, - cbuf, newScreenBase + l + 1, - (height - 1) - l); - System.arraycopy(charAttributes, oldBase + l + 1, - abuf, newScreenBase + l + 1, - (height - 1) - l); - } - } - catch (ArrayIndexOutOfBoundsException e) { - // this should not happen anymore, but I will leave the code - // here in case something happens anyway. That code above is - // so complex I always have a hard time understanding what - // I did, even though there are comments - System.err.println("*** Error while scrolling up:"); - System.err.println("--- BEGIN STACK TRACE ---"); - e.printStackTrace(); - System.err.println("--- END STACK TRACE ---"); - System.err.println("bufSize=" + bufSize + ", maxBufSize=" + maxBufSize); - System.err.println("top=" + top + ", bottom=" + bottom); - System.err.println("n=" + n + ", l=" + l); - System.err.println("screenBase=" + screenBase + ", windowBase=" + windowBase); - System.err.println("newScreenBase=" + newScreenBase + ", newWindowBase=" + newWindowBase); - System.err.println("oldBase=" + oldBase); - System.err.println("size.width=" + width + ", size.height=" + height); - System.err.println("abuf.length=" + abuf.length + ", cbuf.length=" + cbuf.length); - System.err.println("*** done dumping debug information"); - } - } - - // this is a little helper to mark the scrolling - scrollMarker -= n; - - for (int i = 0; i < n; i++) { - cbuf[(newScreenBase + l) + (scrollDown ? i : -i)] = new char[width]; - Arrays.fill(cbuf[(newScreenBase + l) + (scrollDown ? i : -i)], ' '); - abuf[(newScreenBase + l) + (scrollDown ? i : -i)] = new int[width]; - } - - charArray = cbuf; - charAttributes = abuf; - screenBase = newScreenBase; - windowBase = newWindowBase; - bufSize = newBufSize; - - if (scrollDown) - markLine(l, bottom - l + 1); - else - markLine(top, l - top + 1); - - display.updateScrollBar(); - } - - /** - * Delete a line at a specific position. Subsequent lines will be scrolled - * up to fill the space and a blank line is inserted at the end of the - * screen. - * @param l the y-coordinate to insert the line - * @see #deleteLine - */ - public void deleteLine(int l) { - int bottom = (l > bottomMargin ? height - 1 : - (l < topMargin ? topMargin : bottomMargin + 1)); - int numRows = bottom - l - 1; - char[] discardedChars = charArray[screenBase + l]; - int[] discardedAttributes = charAttributes[screenBase + l]; - - if (numRows > 0) { - System.arraycopy(charArray, screenBase + l + 1, - charArray, screenBase + l, numRows); - System.arraycopy(charAttributes, screenBase + l + 1, - charAttributes, screenBase + l, numRows); - } - - int newBottomRow = screenBase + bottom - 1; - charArray[newBottomRow] = discardedChars; - charAttributes[newBottomRow] = discardedAttributes; - Arrays.fill(charArray[newBottomRow], ' '); - Arrays.fill(charAttributes[newBottomRow], 0); - markLine(l, bottom - l); - } - - /** - * Delete a rectangular portion of the screen. - * You need to call redraw() to update the screen. - * @param c x-coordinate (column) - * @param l y-coordinate (row) - * @param w with of the area in characters - * @param h height of the area in characters - * @param curAttr attribute to fill - * @see #deleteChar - * @see #deleteLine - * @see #redraw - */ - public void deleteArea(int c, int l, int w, int h, int curAttr) { - int endColumn = c + w; - int targetRow = screenBase + l; - - for (int i = 0; i < h && l + i < height; i++) { - Arrays.fill(charAttributes[targetRow], c, endColumn, curAttr); - Arrays.fill(charArray[targetRow], c, endColumn, ' '); - targetRow++; - } - - markLine(l, h); - } - - /** - * Delete a rectangular portion of the screen. - * You need to call redraw() to update the screen. - * @param c x-coordinate (column) - * @param l y-coordinate (row) - * @param w with of the area in characters - * @param h height of the area in characters - * @see #deleteChar - * @see #deleteLine - * @see #redraw - */ - public void deleteArea(int c, int l, int w, int h) { - deleteArea(c, l, w, h, 0); - } - - /** - * Sets whether the cursor is visible or not. - * @param doshow - */ - public void showCursor(boolean doshow) { - showcursor = doshow; - } - - /** - * Check whether the cursor is currently visible. - * @return visibility - */ - public boolean isCursorVisible() { - return showcursor; - } - - /** - * Puts the cursor at the specified position. - * @param c column - * @param l line - */ - public void setCursorPosition(int c, int l) { - cursorX = (c > width - 1) ? width - 1 : c; - cursorY = (l > height - 1) ? height - 1 : l; - } - - /** - * Get the current column of the cursor position. - */ - public int getCursorColumn() { - return cursorX; - } - - /** - * Get the current line of the cursor position. - */ - public int getCursorRow() { - return cursorY; - } - - /** - * Set the current window base. This allows to view the scrollback buffer. - * @param line the line where the screen window starts - * @see #setBufferSize - * @see #getBufferSize - */ - public void setWindowBase(int line) { - if (line > screenBase) - line = screenBase; - else if (line < 0) line = 0; - - windowBase = line; - update[0] = true; - redraw(); - } - - /** - * Get the current window base. - * @see #setWindowBase - */ - public int getWindowBase() { - return windowBase; - } - - /** - * Set the scroll margins simultaneously. If they're out of bounds, trim them. - * @param l1 line that is the top - * @param l2 line that is the bottom - */ - public void setMargins(int l1, int l2) { - if (l1 > l2) - return; - - if (l1 < 0) - l1 = 0; - - if (l2 >= height) - l2 = height - 1; - - topMargin = l1; - bottomMargin = l2; - } - - /** - * Set the top scroll margin for the screen. If the current bottom margin - * is smaller it will become the top margin and the line will become the - * bottom margin. - * @param l line that is the margin - */ - public void setTopMargin(int l) { - if (l > bottomMargin) { - topMargin = bottomMargin; - bottomMargin = l; - } - else - topMargin = l; - - if (topMargin < 0) topMargin = 0; - - if (bottomMargin >= height) bottomMargin = height - 1; - } - - /** - * Get the top scroll margin. - */ - public int getTopMargin() { - return topMargin; - } - - /** - * Set the bottom scroll margin for the screen. If the current top margin - * is bigger it will become the bottom margin and the line will become the - * top margin. - * @param l line that is the margin - */ - public void setBottomMargin(int l) { - if (l < topMargin) { - bottomMargin = topMargin; - topMargin = l; - } - else - bottomMargin = l; - - if (topMargin < 0) topMargin = 0; - - if (bottomMargin >= height) bottomMargin = height - 1; - } - - /** - * Get the bottom scroll margin. - */ - public int getBottomMargin() { - return bottomMargin; - } - - /** - * Set scrollback buffer size. - * @param amount new size of the buffer - */ - public void setBufferSize(int amount) { - if (amount < height) amount = height; - - if (amount < maxBufSize) { - char cbuf[][] = new char[amount][width]; - int abuf[][] = new int[amount][width]; - int copyStart = bufSize - amount < 0 ? 0 : bufSize - amount; - int copyCount = bufSize - amount < 0 ? bufSize : amount; - - if (charArray != null) - System.arraycopy(charArray, copyStart, cbuf, 0, copyCount); - - if (charAttributes != null) - System.arraycopy(charAttributes, copyStart, abuf, 0, copyCount); - - charArray = cbuf; - charAttributes = abuf; - bufSize = copyCount; - screenBase = bufSize - height; - windowBase = screenBase; - } - - maxBufSize = amount; - update[0] = true; - redraw(); - } - - /** - * Retrieve current scrollback buffer size. - * @see #setBufferSize - */ - public int getBufferSize() { - return bufSize; - } - - /** - * Retrieve maximum buffer Size. - * @see #getBufferSize - */ - public int getMaxBufferSize() { - return maxBufSize; - } - - /** - * Change the size of the screen. This will include adjustment of the - * scrollback buffer. - * @param w of the screen - * @param h of the screen - */ - public void setScreenSize(int w, int h, boolean broadcast) { - char cbuf[][]; - int abuf[][]; - int maxSize = bufSize; - - if (w < 1 || h < 1) return; - - if (debug > 0) - System.err.println("VDU: screen size [" + w + "," + h + "]"); - - if (h > maxBufSize) - maxBufSize = h; - - if (h > bufSize) { - bufSize = h; - screenBase = 0; - windowBase = 0; - } - - if (windowBase + h >= bufSize) - windowBase = bufSize - h; - - if (screenBase + h >= bufSize) - screenBase = bufSize - h; - - cbuf = new char[bufSize][w]; - abuf = new int[bufSize][w]; - - for (int i = 0; i < bufSize; i++) { - Arrays.fill(cbuf[i], ' '); - } - - if (bufSize < maxSize) - maxSize = bufSize; - - int rowLength; - - if (charArray != null && charAttributes != null) { - for (int i = 0; i < maxSize && charArray[i] != null; i++) { - rowLength = charArray[i].length; - System.arraycopy(charArray[i], 0, cbuf[i], 0, - w < rowLength ? w : rowLength); - System.arraycopy(charAttributes[i], 0, abuf[i], 0, - w < rowLength ? w : rowLength); - } - } - - int C = getCursorColumn(); - - if (C < 0) - C = 0; - else if (C >= width) - C = width - 1; - - int R = getCursorRow(); - - if (R < 0) - R = 0; - else if (R >= height) - R = height - 1; - - setCursorPosition(C, R); - charArray = cbuf; - charAttributes = abuf; - width = w; - height = h; - topMargin = 0; - bottomMargin = h - 1; - update = new boolean[h + 1]; - update[0] = true; - /* FIXME: ??? - if(resizeStrategy == RESIZE_FONT) - setBounds(getBounds()); - */ - } - - /** - * Get amount of rows on the screen. - */ - public int getRows() { - return height; - } - - /** - * Get amount of columns on the screen. - */ - public int getColumns() { - return width; - } - - /** - * Mark lines to be updated with redraw(). - * @param l starting line - * @param n amount of lines to be updated - * @see #redraw - */ - public void markLine(int l, int n) { - for (int i = 0; (i < n) && (l + i < height); i++) - update[l + i + 1] = true; - } - -// private static int checkBounds(int value, int lower, int upper) { -// if (value < lower) -// return lower; -// else if (value > upper) -// return upper; -// else -// return value; -// } - - public void setDisplay(VDUDisplay display) { - this.display = display; - } - - /** - * Trigger a redraw on the display. - */ - protected void redraw() { - if (display != null) - display.redraw(); - } -}
--- a/src/de/mud/terminal/VDUDisplay.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". - * - * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved. - * - * Please visit http://javatelnet.org/ for updates and contact. - * - * --LICENSE NOTICE-- - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * --LICENSE NOTICE-- - * - */ - -package de.mud.terminal; - -/** - * Generic display - */ -public interface VDUDisplay { - public void redraw(); - public void updateScrollBar(); - - public void setColor(int index, int red, int green, int blue); - public void resetColors(); -}
--- a/src/de/mud/terminal/VDUInput.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". - * - * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved. - * - * Please visit http://javatelnet.org/ for updates and contact. - * - * --LICENSE NOTICE-- - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * --LICENSE NOTICE-- - * - */ -package de.mud.terminal; - -import java.util.Properties; - -/** - * An interface for a terminal that accepts input from keyboard and mouse. - * - * @author Matthias L. Jugel, Marcus Meißner - * @version $Id: VDUInput.java 499 2005-09-29 08:24:54Z leo $ - */ -public interface VDUInput { - - public final static int KEY_CONTROL = 0x01; - public final static int KEY_SHIFT = 0x02; - public final static int KEY_ALT = 0x04; - public final static int KEY_ACTION = 0x08; - - - - /** - * Direct access to writing data ... - * @param b - */ - void write(byte b[]); - - /** - * Terminal is mouse-aware and requires (x,y) coordinates of - * on the terminal (character coordinates) and the button clicked. - * @param x - * @param y - * @param modifiers - */ - void mousePressed(int x, int y, int modifiers); - - /** - * Terminal is mouse-aware and requires the coordinates and button - * of the release. - * @param x - * @param y - * @param modifiers - */ - void mouseReleased(int x, int y, int modifiers); - - /** - * Override the standard key codes used by the terminal emulation. - * @param codes a properties object containing key code definitions - */ - void setKeyCodes(Properties codes); - - /** - * keytyping event handler for all the special function and modifier keys - * @param keyCode the key code - * @param keyChar the character represented by the key - * @param modifiers shift/alt/control modifiers - */ - void keyPressed(int keyCode, char keyChar, int modifiers); - -}
--- a/src/de/mud/terminal/vt320.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3423 +0,0 @@ -/* - * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform". - * - * (c) Matthias L. Jugel, Marcus Meiner 1996-2005. All Rights Reserved. - * - * Please visit http://javatelnet.org/ for updates and contact. - * - * --LICENSE NOTICE-- - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * --LICENSE NOTICE-- - * - */ - -package de.mud.terminal; - -import android.text.AndroidCharacter; - -import java.util.Properties; - -/** - * Implementation of a VT terminal emulation plus ANSI compatible. - * <P> - * <B>Maintainer:</B> Marcus Meißner - * - * @version $Id: vt320.java 507 2005-10-25 10:14:52Z marcus $ - * @author Matthias L. Jugel, Marcus Meißner - */ -public abstract class vt320 extends VDUBuffer implements VDUInput { - - /** the debug level */ - private final static int debug = 0; - private StringBuilder debugStr; - public abstract void debug(String notice); - - /** - * Write an answer back to the remote host. This is needed to be able to - * send terminal answers requests like status and type information. - * @param b the array of bytes to be sent - */ - public abstract void write(byte[] b); - - /** - * Write an answer back to the remote host. This is needed to be able to - * send terminal answers requests like status and type information. - * @param b the byte to be sent - */ - public abstract void write(int b); - - /** - * No more bytes to read from the transport, hook here to test screen changes - */ - public void testChanged() { - /* do nothing by default */ - } - - /** - * inject field contents as if typed - */ - public void setField(int l, int c, char [] d) { - // ignore line and column, just send the bytes to the host. - int n = d.length; - byte [] b = new byte [n]; - - for (int i = 0; i < n; i++) b[i] = (byte)(d[i] & 0x00ff); - - write(b); - } - - public void monitorKey(boolean down) { - // do nothing - } - - public void keyDepressed(int keyCode, char keyChar, int modifiers) { - keyPressed(keyCode, keyChar, modifiers); - } - - /** - * Play the beep sound ... - */ - public void beep() { - /* do nothing by default */ - } - - public void redrawPassthru() { - redraw(); // VDUBuffer.redraw is protected - } - - /** - * Convenience function for putString(char[], int, int) - */ - public void putString(String s) { - int len = s.length(); - char[] tmp = new char[len]; - s.getChars(0, len, tmp, 0); - putString(tmp, null, 0, len); - } - - /** - * Put string at current cursor position. Moves cursor - * according to the String. Does NOT wrap. - * @param s character array - * @param start place to start in array - * @param len number of characters to process - */ - public void putString(char[] s, byte[] fullwidths, int start, int len) { - if (len > 0) { - //markLine(R, 1); - int lastChar = -1; - char c; - boolean isWide = false; - - for (int i = 0; i < len; i++) { - c = s[start + i]; - - // Shortcut for my favorite ASCII - if (c <= 0x7F) { - if (lastChar != -1) - putChar((char) lastChar, isWide, false); - - lastChar = c; - isWide = false; - } - else if (!Character.isLowSurrogate(c) && !Character.isHighSurrogate(c)) { - if (Character.getType(c) == Character.NON_SPACING_MARK) { - if (lastChar != -1) { - char nc = Precomposer.precompose((char) lastChar, c); - putChar(nc, isWide, false); - lastChar = -1; - } - } - else { - if (lastChar != -1) - putChar((char) lastChar, isWide, false); - - lastChar = c; - - if (fullwidths != null) { - final byte width = fullwidths[i]; - isWide = (width == AndroidCharacter.EAST_ASIAN_WIDTH_WIDE) - || (width == AndroidCharacter.EAST_ASIAN_WIDTH_FULL_WIDTH); - } - } - } - } - - if (lastChar != -1) - putChar((char) lastChar, isWide, false); - - setCursorPosition(C, R); - redraw(); - } - } - - protected void sendTelnetCommand(byte cmd) { - /* do nothing by default */ - } - - /** - * Sent the changed window size from the terminal to all listeners. - */ - protected void setWindowSize(int c, int r) { - /* To be overridden by Terminal.java */ - } - - @Override - public void setScreenSize(int c, int r, boolean broadcast) { - int oldrows = height; - - if (debug > 2) { - if (debugStr == null) - debugStr = new StringBuilder(); - - debugStr.append("setscreensize (") - .append(c) - .append(',') - .append(r) - .append(',') - .append(broadcast) - .append(')'); - debug(debugStr.toString()); - debugStr.setLength(0); - } - - super.setScreenSize(c, r, false); - boolean cursorChanged = false; - - // Don't let the cursor go off the screen. - if (C >= c) { - C = c - 1; - cursorChanged = true; - } - - if (R >= r) { - R = r - 1; - cursorChanged = true; - } - - if (cursorChanged) { - setCursorPosition(C, R); - redraw(); - } - - if (broadcast) { - setWindowSize(c, r); /* broadcast up */ - } - } - - - /** - * Create a new vt320 terminal and intialize it with useful settings. - */ - public vt320(int width, int height) { - super(width, height); - debugStr = new StringBuilder(); - setVMS(false); - setIBMCharset(false); - setTerminalID("vt320"); - setBufferSize(100); - //setBorder(2, false); - gx = new char[4]; - reset(); - /* top row of numpad */ - PF1 = "\u001bOP"; - PF2 = "\u001bOQ"; - PF3 = "\u001bOR"; - PF4 = "\u001bOS"; - /* the 3x2 keyblock on PC keyboards */ - Insert = new String[4]; - Remove = new String[4]; - KeyHome = new String[4]; - KeyEnd = new String[4]; - NextScn = new String[4]; - PrevScn = new String[4]; - Escape = new String[4]; - BackSpace = new String[4]; - TabKey = new String[4]; - Insert[0] = Insert[1] = Insert[2] = Insert[3] = "\u001b[2~"; - Remove[0] = Remove[1] = Remove[2] = Remove[3] = "\u001b[3~"; - PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[5~"; - NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[6~"; - KeyHome[0] = KeyHome[1] = KeyHome[2] = KeyHome[3] = "\u001b[H"; - KeyEnd[0] = KeyEnd[1] = KeyEnd[2] = KeyEnd[3] = "\u001b[F"; - Escape[0] = Escape[1] = Escape[2] = Escape[3] = "\u001b"; - - if (vms) { - BackSpace[1] = "" + (char) 10; // VMS shift deletes word back - BackSpace[2] = "\u0018"; // VMS control deletes line back - BackSpace[0] = BackSpace[3] = "\u007f"; // VMS other is delete - } - else { - //BackSpace[0] = BackSpace[1] = BackSpace[2] = BackSpace[3] = "\b"; - // ConnectBot modifications. - BackSpace[0] = "\b"; - BackSpace[1] = "\u007f"; - BackSpace[2] = "\u001b[3~"; - BackSpace[3] = "\u001b[2~"; - } - - /* some more VT100 keys */ - Find = "\u001b[1~"; - Select = "\u001b[4~"; - Help = "\u001b[28~"; - Do = "\u001b[29~"; - FunctionKey = new String[21]; - FunctionKey[0] = ""; - FunctionKey[1] = PF1; - FunctionKey[2] = PF2; - FunctionKey[3] = PF3; - FunctionKey[4] = PF4; - /* following are defined differently for vt220 / vt132 ... */ - FunctionKey[5] = "\u001b[15~"; - FunctionKey[6] = "\u001b[17~"; - FunctionKey[7] = "\u001b[18~"; - FunctionKey[8] = "\u001b[19~"; - FunctionKey[9] = "\u001b[20~"; - FunctionKey[10] = "\u001b[21~"; - FunctionKey[11] = "\u001b[23~"; - FunctionKey[12] = "\u001b[24~"; - FunctionKey[13] = "\u001b[25~"; - FunctionKey[14] = "\u001b[26~"; - FunctionKey[15] = Help; - FunctionKey[16] = Do; - FunctionKey[17] = "\u001b[31~"; - FunctionKey[18] = "\u001b[32~"; - FunctionKey[19] = "\u001b[33~"; - FunctionKey[20] = "\u001b[34~"; - FunctionKeyShift = new String[21]; - FunctionKeyAlt = new String[21]; - FunctionKeyCtrl = new String[21]; - - for (int i = 0; i < 20; i++) { - FunctionKeyShift[i] = ""; - FunctionKeyAlt[i] = ""; - FunctionKeyCtrl[i] = ""; - } - - FunctionKeyShift[15] = Find; - FunctionKeyShift[16] = Select; - TabKey[0] = "\u0009"; - TabKey[1] = "\u001bOP\u0009"; - TabKey[2] = TabKey[3] = ""; - KeyUp = new String[4]; - KeyUp[0] = "\u001b[A"; - KeyDown = new String[4]; - KeyDown[0] = "\u001b[B"; - KeyRight = new String[4]; - KeyRight[0] = "\u001b[C"; - KeyLeft = new String[4]; - KeyLeft[0] = "\u001b[D"; - Numpad = new String[10]; - Numpad[0] = "\u001bOp"; - Numpad[1] = "\u001bOq"; - Numpad[2] = "\u001bOr"; - Numpad[3] = "\u001bOs"; - Numpad[4] = "\u001bOt"; - Numpad[5] = "\u001bOu"; - Numpad[6] = "\u001bOv"; - Numpad[7] = "\u001bOw"; - Numpad[8] = "\u001bOx"; - Numpad[9] = "\u001bOy"; - KPMinus = PF4; - KPComma = "\u001bOl"; - KPPeriod = "\u001bOn"; - KPEnter = "\u001bOM"; - NUMPlus = new String[4]; - NUMPlus[0] = "+"; - NUMDot = new String[4]; - NUMDot[0] = "."; - } - - public void setBackspace(int type) { - switch (type) { - case DELETE_IS_DEL: - BackSpace[0] = "\u007f"; - BackSpace[1] = "\b"; - break; - - case DELETE_IS_BACKSPACE: - BackSpace[0] = "\b"; - BackSpace[1] = "\u007f"; - break; - } - } - - /** - * Create a default vt320 terminal with 80 columns and 24 lines. - */ - public vt320() { - this(80, 24); - } - - /** - * Terminal is mouse-aware and requires (x,y) coordinates of - * on the terminal (character coordinates) and the button clicked. - * @param x - * @param y - * @param modifiers - */ - public void mousePressed(int x, int y, int modifiers) { - if (mouserpt == 0) - return; - - int mods = modifiers; - mousebut = 3; - - if ((mods & 16) == 16) mousebut = 0; - - if ((mods & 8) == 8) mousebut = 1; - - if ((mods & 4) == 4) mousebut = 2; - - int mousecode; - - if (mouserpt == 9) /* X10 Mouse */ - mousecode = 0x20 | mousebut; - else /* normal xterm mouse reporting */ - mousecode = mousebut | 0x20 | ((mods & 7) << 2); - - byte b[] = new byte[6]; - b[0] = 27; - b[1] = (byte) '['; - b[2] = (byte) 'M'; - b[3] = (byte) mousecode; - b[4] = (byte)(0x20 + x + 1); - b[5] = (byte)(0x20 + y + 1); - write(b); // FIXME: writeSpecial here - } - - /** - * Terminal is mouse-aware and requires the coordinates and button - * of the release. - * @param x - * @param y - * @param modifiers - */ - public void mouseReleased(int x, int y, int modifiers) { - if (mouserpt == 0) - return; - - /* problem is tht modifiers still have the released button set in them. - int mods = modifiers; - mousebut = 3; - if ((mods & 16)==16) mousebut=0; - if ((mods & 8)==8 ) mousebut=1; - if ((mods & 4)==4 ) mousebut=2; - */ - int mousecode; - - if (mouserpt == 9) - mousecode = 0x20 + mousebut; /* same as press? appears so. */ - else - mousecode = '#'; - - byte b[] = new byte[6]; - b[0] = 27; - b[1] = (byte) '['; - b[2] = (byte) 'M'; - b[3] = (byte) mousecode; - b[4] = (byte)(0x20 + x + 1); - b[5] = (byte)(0x20 + y + 1); - write(b); // FIXME: writeSpecial here - mousebut = 0; - } - - - /** we should do localecho (passed from other modules). false is default */ - private boolean localecho = false; - - /** - * Enable or disable the local echo property of the terminal. - * @param echo true if the terminal should echo locally - */ - public void setLocalEcho(boolean echo) { - localecho = echo; - } - - /** - * Enable the VMS mode of the terminal to handle some things differently - * for VMS hosts. - * @param vms true for vms mode, false for normal mode - */ - public void setVMS(boolean vms) { - this.vms = vms; - } - - /** - * Enable the usage of the IBM character set used by some BBS's. Special - * graphical character are available in this mode. - * @param ibm true to use the ibm character set - */ - public void setIBMCharset(boolean ibm) { - useibmcharset = ibm; - } - - /** - * Override the standard key codes used by the terminal emulation. - * @param codes a properties object containing key code definitions - */ - public void setKeyCodes(Properties codes) { - String res, prefixes[] = {"", "S", "C", "A"}; - int i; - - for (i = 0; i < 10; i++) { - res = codes.getProperty("NUMPAD" + i); - - if (res != null) Numpad[i] = unEscape(res); - } - - for (i = 1; i < 20; i++) { - res = codes.getProperty("F" + i); - - if (res != null) FunctionKey[i] = unEscape(res); - - res = codes.getProperty("SF" + i); - - if (res != null) FunctionKeyShift[i] = unEscape(res); - - res = codes.getProperty("CF" + i); - - if (res != null) FunctionKeyCtrl[i] = unEscape(res); - - res = codes.getProperty("AF" + i); - - if (res != null) FunctionKeyAlt[i] = unEscape(res); - } - - for (i = 0; i < 4; i++) { - res = codes.getProperty(prefixes[i] + "PGUP"); - - if (res != null) PrevScn[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "PGDOWN"); - - if (res != null) NextScn[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "END"); - - if (res != null) KeyEnd[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "HOME"); - - if (res != null) KeyHome[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "INSERT"); - - if (res != null) Insert[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "REMOVE"); - - if (res != null) Remove[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "UP"); - - if (res != null) KeyUp[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "DOWN"); - - if (res != null) KeyDown[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "LEFT"); - - if (res != null) KeyLeft[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "RIGHT"); - - if (res != null) KeyRight[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "ESCAPE"); - - if (res != null) Escape[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "BACKSPACE"); - - if (res != null) BackSpace[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "TAB"); - - if (res != null) TabKey[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "NUMPLUS"); - - if (res != null) NUMPlus[i] = unEscape(res); - - res = codes.getProperty(prefixes[i] + "NUMDECIMAL"); - - if (res != null) NUMDot[i] = unEscape(res); - } - } - - /** - * Set the terminal id used to identify this terminal. - * @param terminalID the id string - */ - public void setTerminalID(String terminalID) { - this.terminalID = terminalID; - - if (terminalID.equals("scoansi")) { - FunctionKey[1] = "\u001b[M"; FunctionKey[2] = "\u001b[N"; - FunctionKey[3] = "\u001b[O"; FunctionKey[4] = "\u001b[P"; - FunctionKey[5] = "\u001b[Q"; FunctionKey[6] = "\u001b[R"; - FunctionKey[7] = "\u001b[S"; FunctionKey[8] = "\u001b[T"; - FunctionKey[9] = "\u001b[U"; FunctionKey[10] = "\u001b[V"; - FunctionKey[11] = "\u001b[W"; FunctionKey[12] = "\u001b[X"; - FunctionKey[13] = "\u001b[Y"; FunctionKey[14] = "?"; - FunctionKey[15] = "\u001b[a"; FunctionKey[16] = "\u001b[b"; - FunctionKey[17] = "\u001b[c"; FunctionKey[18] = "\u001b[d"; - FunctionKey[19] = "\u001b[e"; FunctionKey[20] = "\u001b[f"; - PrevScn[0] = PrevScn[1] = PrevScn[2] = PrevScn[3] = "\u001b[I"; - NextScn[0] = NextScn[1] = NextScn[2] = NextScn[3] = "\u001b[G"; - // more theoretically. - } - } - - public void setAnswerBack(String ab) { - this.answerBack = unEscape(ab); - } - - /** - * Get the terminal id used to identify this terminal. - */ - public String getTerminalID() { - return terminalID; - } - - /** - * A small conveniance method thar converts the string to a byte array - * for sending. - * @param s the string to be sent - */ - private boolean write(String s, boolean doecho) { - if (debug > 2) { - debugStr.append("write(|") - .append(s) - .append("|,") - .append(doecho); - debug(debugStr.toString()); - debugStr.setLength(0); - } - - if (s == null) // aka the empty string. - return true; - - /* NOTE: getBytes() honours some locale, it *CONVERTS* the string. - * However, we output only 7bit stuff towards the target, and *some* - * 8 bit control codes. We must not mess up the latter, so we do hand - * by hand copy. - */ - byte arr[] = new byte[s.length()]; - - for (int i = 0; i < s.length(); i++) { - arr[i] = (byte) s.charAt(i); - } - - write(arr); - - if (doecho) - putString(s); - - return true; - } - - private boolean write(int s, boolean doecho) { - if (debug > 2) { - debugStr.append("write(|") - .append(s) - .append("|,") - .append(doecho); - debug(debugStr.toString()); - debugStr.setLength(0); - } - - write(s); - - // TODO check if character is wide - if (doecho) - putChar((char)s, false, false); - - return true; - } - - private boolean write(String s) { - return write(s, localecho); - } - - // =================================================================== - // the actual terminal emulation code comes here: - // =================================================================== - - private String terminalID = "vt320"; - private String answerBack = "Use Terminal.answerback to set ...\n"; - - // X - COLUMNS, Y - ROWS - int R, C; - int attributes = 0; - - int Sc, Sr, Sa, Stm, Sbm; - char Sgr, Sgl; - char Sgx[]; - - int insertmode = 0; - int statusmode = 0; - boolean vt52mode = false; - boolean keypadmode = false; /* false - numeric, true - application */ - boolean output8bit = false; - int normalcursor = 0; - boolean moveoutsidemargins = true; - boolean wraparound = true; - boolean sendcrlf = true; - boolean capslock = false; - boolean numlock = false; - int mouserpt = 0; - byte mousebut = 0; - - boolean useibmcharset = false; - - int lastwaslf = 0; - boolean usedcharsets = false; - - private final static char ESC = 27; - private final static char IND = 132; - private final static char NEL = 133; - private final static char RI = 141; - private final static char SS2 = 142; - private final static char SS3 = 143; - private final static char DCS = 144; - private final static char HTS = 136; - private final static char CSI = 155; - private final static char OSC = 157; - private final static int TSTATE_DATA = 0; - private final static int TSTATE_ESC = 1; /* ESC */ - private final static int TSTATE_CSI = 2; /* ESC [ */ - private final static int TSTATE_DCS = 3; /* ESC P */ - private final static int TSTATE_DCEQ = 4; /* ESC [? */ - private final static int TSTATE_ESCSQUARE = 5; /* ESC # */ - private final static int TSTATE_OSC = 6; /* ESC ] */ - private final static int TSTATE_SETG0 = 7; /* ESC (? */ - private final static int TSTATE_SETG1 = 8; /* ESC )? */ - private final static int TSTATE_SETG2 = 9; /* ESC *? */ - private final static int TSTATE_SETG3 = 10; /* ESC +? */ - private final static int TSTATE_CSI_DOLLAR = 11; /* ESC [ Pn $ */ - private final static int TSTATE_CSI_EX = 12; /* ESC [ ! */ - private final static int TSTATE_ESCSPACE = 13; /* ESC <space> */ - private final static int TSTATE_VT52X = 14; - private final static int TSTATE_VT52Y = 15; - private final static int TSTATE_CSI_TICKS = 16; - private final static int TSTATE_CSI_EQUAL = 17; /* ESC [ = */ - private final static int TSTATE_TITLE = 18; /* xterm title */ - - /* Keys we support */ - public final static int KEY_PAUSE = 1; - public final static int KEY_F1 = 2; - public final static int KEY_F2 = 3; - public final static int KEY_F3 = 4; - public final static int KEY_F4 = 5; - public final static int KEY_F5 = 6; - public final static int KEY_F6 = 7; - public final static int KEY_F7 = 8; - public final static int KEY_F8 = 9; - public final static int KEY_F9 = 10; - public final static int KEY_F10 = 11; - public final static int KEY_F11 = 12; - public final static int KEY_F12 = 13; - public final static int KEY_F13 = 14; // only used by tn5250 - public final static int KEY_F14 = 15; // only used by tn5250 - public final static int KEY_F15 = 16; // only used by tn5250 - public final static int KEY_F16 = 17; // only used by tn5250 - public final static int KEY_F17 = 18; // only used by tn5250 - public final static int KEY_F18 = 19; // only used by tn5250 - public final static int KEY_F19 = 20; // only used by tn5250 - public final static int KEY_F20 = 21; // only used by tn5250 - public final static int KEY_F21 = 22; // only used by tn5250 - public final static int KEY_F22 = 23; // only used by tn5250 - public final static int KEY_F23 = 24; // only used by tn5250 - public final static int KEY_F24 = 25; // only used by tn5250 - public final static int KEY_UP = 26; - public final static int KEY_DOWN = 27; - public final static int KEY_LEFT = 28; - public final static int KEY_RIGHT = 29; - public final static int KEY_PAGE_DOWN = 30; - public final static int KEY_PAGE_UP = 31; - public final static int KEY_INSERT = 32; - public final static int KEY_DELETE = 33; - public final static int KEY_BACK_SPACE = 34; - public final static int KEY_HOME = 35; - public final static int KEY_END = 36; - public final static int KEY_NUM_LOCK = 37; - public final static int KEY_CAPS_LOCK = 38; - public final static int KEY_SHIFT = 39; - public final static int KEY_CONTROL = 40; - public final static int KEY_ALT = 41; - public final static int KEY_ENTER = 42; - public final static int KEY_NUMPAD0 = 43; - public final static int KEY_NUMPAD1 = 44; - public final static int KEY_NUMPAD2 = 45; - public final static int KEY_NUMPAD3 = 46; - public final static int KEY_NUMPAD4 = 47; - public final static int KEY_NUMPAD5 = 48; - public final static int KEY_NUMPAD6 = 49; - public final static int KEY_NUMPAD7 = 50; - public final static int KEY_NUMPAD8 = 51; - public final static int KEY_NUMPAD9 = 52; - public final static int KEY_DECIMAL = 53; - public final static int KEY_ADD = 54; - public final static int KEY_ESCAPE = 55; - public final static int KEY_TAB = 56; - public final static int KEY_SYSREQ = 57; // only used by tn5250 - - public final static int DELETE_IS_DEL = 0; - public final static int DELETE_IS_BACKSPACE = 1; - - /* The graphics charsets - * B - default ASCII - * A - ISO Latin 1 - * 0 - DEC SPECIAL - * < - User defined - * .... - */ - char gx[]; - char gl; // GL (left charset) - char gr; // GR (right charset) - int onegl; // single shift override for GL. - - // Map from scoansi linedrawing to DEC _and_ unicode (for the stuff which - // is not in linedrawing). Got from experimenting with scoadmin. - private final static String scoansi_acs = "Tm7k3x4u?kZl@mYjEnB\u2566DqCtAvM\u2550:\u2551N\u2557I\u2554;\u2557H\u255a0a<\u255d"; - // array to store DEC Special -> Unicode mapping - // Unicode DEC Unicode name (DEC name) - private static char DECSPECIAL[] = { - '\u0040', //5f blank - '\u2666', //60 black diamond - '\u2592', //61 grey square - '\u2409', //62 Horizontal tab (ht) pict. for control - '\u240c', //63 Form Feed (ff) pict. for control - '\u240d', //64 Carriage Return (cr) pict. for control - '\u240a', //65 Line Feed (lf) pict. for control - '\u00ba', //66 Masculine ordinal indicator - '\u00b1', //67 Plus or minus sign - '\u2424', //68 New Line (nl) pict. for control - '\u240b', //69 Vertical Tab (vt) pict. for control - '\u2518', //6a Forms light up and left - '\u2510', //6b Forms light down and left - '\u250c', //6c Forms light down and right - '\u2514', //6d Forms light up and right - '\u253c', //6e Forms light vertical and horizontal - '\u2594', //6f Upper 1/8 block (Scan 1) - '\u2580', //70 Upper 1/2 block (Scan 3) - '\u2500', //71 Forms light horizontal or ?em dash? (Scan 5) - '\u25ac', //72 \u25ac black rect. or \u2582 lower 1/4 (Scan 7) - '\u005f', //73 \u005f underscore or \u2581 lower 1/8 (Scan 9) - '\u251c', //74 Forms light vertical and right - '\u2524', //75 Forms light vertical and left - '\u2534', //76 Forms light up and horizontal - '\u252c', //77 Forms light down and horizontal - '\u2502', //78 vertical bar - '\u2264', //79 less than or equal - '\u2265', //7a greater than or equal - '\u00b6', //7b paragraph - '\u2260', //7c not equal - '\u00a3', //7d Pound Sign (british) - '\u00b7' //7e Middle Dot - }; - - /** Strings to send on function key pressing */ - private String Numpad[]; - private String FunctionKey[]; - private String FunctionKeyShift[]; - private String FunctionKeyCtrl[]; - private String FunctionKeyAlt[]; - private String TabKey[]; - private String KeyUp[], KeyDown[], KeyLeft[], KeyRight[]; - private String KPMinus, KPComma, KPPeriod, KPEnter; - private String PF1, PF2, PF3, PF4; - private String Help, Do, Find, Select; - - private String KeyHome[], KeyEnd[], Insert[], Remove[], PrevScn[], NextScn[]; - private String Escape[], BackSpace[], NUMDot[], NUMPlus[]; - - private String osc, dcs; /* to memorize OSC & DCS control sequence */ - - /** vt320 state variable (internal) */ - private int term_state = TSTATE_DATA; - /** in vms mode, set by Terminal.VMS property */ - private boolean vms = false; - /** Tabulators */ - private byte[] Tabs; - /** The list of integers as used by CSI */ - private int[] DCEvars = new int[30]; - private int DCEvar; - - /** - * Replace escape code characters (backslash + identifier) with their - * respective codes. - * @param tmp the string to be parsed - * @return a unescaped string - */ - static String unEscape(String tmp) { - int idx = 0, oldidx = 0; - String cmd; - // f.println("unescape("+tmp+")"); - cmd = ""; - - while ((idx = tmp.indexOf('\\', oldidx)) >= 0 && - ++idx <= tmp.length()) { - cmd += tmp.substring(oldidx, idx - 1); - - if (idx == tmp.length()) return cmd; - - switch (tmp.charAt(idx)) { - case 'b': - cmd += "\b"; - break; - - case 'e': - cmd += "\u001b"; - break; - - case 'n': - cmd += "\n"; - break; - - case 'r': - cmd += "\r"; - break; - - case 't': - cmd += "\t"; - break; - - case 'v': - cmd += "\u000b"; - break; - - case 'a': - cmd += "\u0012"; - break; - - default : - if ((tmp.charAt(idx) >= '0') && (tmp.charAt(idx) <= '9')) { - int i; - - for (i = idx; i < tmp.length(); i++) - if ((tmp.charAt(i) < '0') || (tmp.charAt(i) > '9')) - break; - - cmd += (char) Integer.parseInt(tmp.substring(idx, i)); - idx = i - 1; - } - else - cmd += tmp.substring(idx, ++idx); - - break; - } - - oldidx = ++idx; - } - - if (oldidx <= tmp.length()) cmd += tmp.substring(oldidx); - - return cmd; - } - - /** - * A small conveniance method thar converts a 7bit string to the 8bit - * version depending on VT52/Output8Bit mode. - * - * @param s the string to be sent - */ - private boolean writeSpecial(String s) { - if (s == null) - return true; - - if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == 'O'))) { - if (vt52mode) { - if ((s.charAt(2) >= 'P') && (s.charAt(2) <= 'S')) { - s = "\u001b" + s.substring(2); /* ESC x */ - } - else { - s = "\u001b?" + s.substring(2); /* ESC ? x */ - } - } - else { - if (output8bit) { - s = "\u008f" + s.substring(2); /* SS3 x */ - } /* else keep string as it is */ - } - } - - if (((s.length() >= 3) && (s.charAt(0) == 27) && (s.charAt(1) == '['))) { - if (output8bit) { - s = "\u009b" + s.substring(2); /* CSI ... */ - } /* else keep */ - } - - return write(s, false); - } - - /** - * main keytyping event handler for all the special function and modifier keys - * the normal keys are processed by write(byte b); - */ - public void keyPressed(int keyCode, char keyChar, int modifiers) { - boolean control = (modifiers & VDUInput.KEY_CONTROL) != 0; - boolean shift = (modifiers & VDUInput.KEY_SHIFT) != 0; - boolean alt = (modifiers & VDUInput.KEY_ALT) != 0; - - if (debug > 1) { - debugStr.append("keyPressed(") - .append(keyCode) - .append(", ") - .append((int)keyChar) - .append(", ") - .append(modifiers) - .append(')'); - debug(debugStr.toString()); - debugStr.setLength(0); - } - - int xind; - String fmap[]; - xind = 0; - fmap = FunctionKey; - - if (shift) { - fmap = FunctionKeyShift; - xind = 1; - } - - if (control) { - fmap = FunctionKeyCtrl; - xind = 2; - } - - if (alt) { - fmap = FunctionKeyAlt; - xind = 3; - } - - switch (keyCode) { - case KEY_PAUSE: - if (shift || control) - sendTelnetCommand((byte) 243); // BREAK - - break; - - case KEY_F1: - writeSpecial(fmap[1]); - break; - - case KEY_F2: - writeSpecial(fmap[2]); - break; - - case KEY_F3: - writeSpecial(fmap[3]); - break; - - case KEY_F4: - writeSpecial(fmap[4]); - break; - - case KEY_F5: - writeSpecial(fmap[5]); - break; - - case KEY_F6: - writeSpecial(fmap[6]); - break; - - case KEY_F7: - writeSpecial(fmap[7]); - break; - - case KEY_F8: - writeSpecial(fmap[8]); - break; - - case KEY_F9: - writeSpecial(fmap[9]); - break; - - case KEY_F10: - writeSpecial(fmap[10]); - break; - - case KEY_F11: - writeSpecial(fmap[11]); - break; - - case KEY_F12: - writeSpecial(fmap[12]); - break; - - case KEY_F13: - case KEY_F14: - case KEY_F15: - case KEY_F16: - case KEY_F17: - case KEY_F18: - case KEY_F19: - case KEY_F20: - case KEY_F21: - case KEY_F22: - case KEY_F23: - case KEY_F24: - break; - - case KEY_UP: - writeSpecial(KeyUp[xind]); - break; - - case KEY_DOWN: - writeSpecial(KeyDown[xind]); - break; - - case KEY_LEFT: - writeSpecial(KeyLeft[xind]); - break; - - case KEY_RIGHT: - writeSpecial(KeyRight[xind]); - break; - - case KEY_PAGE_DOWN: - writeSpecial(NextScn[xind]); - break; - - case KEY_PAGE_UP: - writeSpecial(PrevScn[xind]); - break; - - case KEY_INSERT: - writeSpecial(Insert[xind]); - break; - - case KEY_DELETE: - writeSpecial(Remove[xind]); - break; - - case KEY_BACK_SPACE: - writeSpecial(BackSpace[xind]); - - if (localecho) { - if (BackSpace[xind] == "\b") { - putString("\b \b"); // make the last char 'deleted' - } - else { - putString(BackSpace[xind]); // echo it - } - } - - break; - - case KEY_HOME: - writeSpecial(KeyHome[xind]); - break; - - case KEY_END: - writeSpecial(KeyEnd[xind]); - break; - - case KEY_NUM_LOCK: - if (vms && control) { - writeSpecial(PF1); - } - - if (!control) - numlock = !numlock; - - break; - - case KEY_CAPS_LOCK: - capslock = !capslock; - break; - - case KEY_SHIFT: - case KEY_CONTROL: - case KEY_ALT: - break; - - case KEY_ESCAPE: - writeSpecial(Escape[xind]); - break; - - case KEY_ENTER: - write(0x0d); - break; - - case KEY_TAB: - writeSpecial(TabKey[xind]); - break; - - default: - break; - } - } - - private void handle_dcs(String dcs) { - debugStr.append("DCS: ") - .append(dcs); - debug(debugStr.toString()); - debugStr.setLength(0); - } - - private void handle_osc(String osc) { - if (osc.length() > 2 && osc.substring(0, 2).equals("4;")) { - // Define color palette - String[] colorData = osc.split(";"); - - try { - int colorIndex = Integer.parseInt(colorData[1]); - - if ("rgb:".equals(colorData[2].substring(0, 4))) { - String[] rgb = colorData[2].substring(4).split("/"); - int red = Integer.parseInt(rgb[0].substring(0, 2), 16) & 0xFF; - int green = Integer.parseInt(rgb[1].substring(0, 2), 16) & 0xFF; - int blue = Integer.parseInt(rgb[2].substring(0, 2), 16) & 0xFF; - display.setColor(colorIndex, red, green, blue); - } - } - catch (Exception e) { - debugStr.append("OSC: invalid color sequence encountered: ") - .append(osc); - debug(debugStr.toString()); - debugStr.setLength(0); - } - } - else - debug("OSC: " + osc); - } - - private final static char unimap[] = { - //# - //# Name: cp437_DOSLatinUS to Unicode table - //# Unicode version: 1.1 - //# Table version: 1.1 - //# Table format: Format A - //# Date: 03/31/95 - //# Authors: Michel Suignard <michelsu@microsoft.com> - //# Lori Hoerth <lorih@microsoft.com> - //# General notes: none - //# - //# Format: Three tab-separated columns - //# Column #1 is the cp1255_WinHebrew code (in hex) - //# Column #2 is the Unicode (in hex as 0xXXXX) - //# Column #3 is the Unicode name (follows a comment sign, '#') - //# - //# The entries are in cp437_DOSLatinUS order - //# - - 0x0000, // #NULL - 0x0001, // #START OF HEADING - 0x0002, // #START OF TEXT - 0x0003, // #END OF TEXT - 0x0004, // #END OF TRANSMISSION - 0x0005, // #ENQUIRY - 0x0006, // #ACKNOWLEDGE - 0x0007, // #BELL - 0x0008, // #BACKSPACE - 0x0009, // #HORIZONTAL TABULATION - 0x000a, // #LINE FEED - 0x000b, // #VERTICAL TABULATION - 0x000c, // #FORM FEED - 0x000d, // #CARRIAGE RETURN - 0x000e, // #SHIFT OUT - 0x000f, // #SHIFT IN - 0x0010, // #DATA LINK ESCAPE - 0x0011, // #DEVICE CONTROL ONE - 0x0012, // #DEVICE CONTROL TWO - 0x0013, // #DEVICE CONTROL THREE - 0x0014, // #DEVICE CONTROL FOUR - 0x0015, // #NEGATIVE ACKNOWLEDGE - 0x0016, // #SYNCHRONOUS IDLE - 0x0017, // #END OF TRANSMISSION BLOCK - 0x0018, // #CANCEL - 0x0019, // #END OF MEDIUM - 0x001a, // #SUBSTITUTE - 0x001b, // #ESCAPE - 0x001c, // #FILE SEPARATOR - 0x001d, // #GROUP SEPARATOR - 0x001e, // #RECORD SEPARATOR - 0x001f, // #UNIT SEPARATOR - 0x0020, // #SPACE - 0x0021, // #EXCLAMATION MARK - 0x0022, // #QUOTATION MARK - 0x0023, // #NUMBER SIGN - 0x0024, // #DOLLAR SIGN - 0x0025, // #PERCENT SIGN - 0x0026, // #AMPERSAND - 0x0027, // #APOSTROPHE - 0x0028, // #LEFT PARENTHESIS - 0x0029, // #RIGHT PARENTHESIS - 0x002a, // #ASTERISK - 0x002b, // #PLUS SIGN - 0x002c, // #COMMA - 0x002d, // #HYPHEN-MINUS - 0x002e, // #FULL STOP - 0x002f, // #SOLIDUS - 0x0030, // #DIGIT ZERO - 0x0031, // #DIGIT ONE - 0x0032, // #DIGIT TWO - 0x0033, // #DIGIT THREE - 0x0034, // #DIGIT FOUR - 0x0035, // #DIGIT FIVE - 0x0036, // #DIGIT SIX - 0x0037, // #DIGIT SEVEN - 0x0038, // #DIGIT EIGHT - 0x0039, // #DIGIT NINE - 0x003a, // #COLON - 0x003b, // #SEMICOLON - 0x003c, // #LESS-THAN SIGN - 0x003d, // #EQUALS SIGN - 0x003e, // #GREATER-THAN SIGN - 0x003f, // #QUESTION MARK - 0x0040, // #COMMERCIAL AT - 0x0041, // #LATIN CAPITAL LETTER A - 0x0042, // #LATIN CAPITAL LETTER B - 0x0043, // #LATIN CAPITAL LETTER C - 0x0044, // #LATIN CAPITAL LETTER D - 0x0045, // #LATIN CAPITAL LETTER E - 0x0046, // #LATIN CAPITAL LETTER F - 0x0047, // #LATIN CAPITAL LETTER G - 0x0048, // #LATIN CAPITAL LETTER H - 0x0049, // #LATIN CAPITAL LETTER I - 0x004a, // #LATIN CAPITAL LETTER J - 0x004b, // #LATIN CAPITAL LETTER K - 0x004c, // #LATIN CAPITAL LETTER L - 0x004d, // #LATIN CAPITAL LETTER M - 0x004e, // #LATIN CAPITAL LETTER N - 0x004f, // #LATIN CAPITAL LETTER O - 0x0050, // #LATIN CAPITAL LETTER P - 0x0051, // #LATIN CAPITAL LETTER Q - 0x0052, // #LATIN CAPITAL LETTER R - 0x0053, // #LATIN CAPITAL LETTER S - 0x0054, // #LATIN CAPITAL LETTER T - 0x0055, // #LATIN CAPITAL LETTER U - 0x0056, // #LATIN CAPITAL LETTER V - 0x0057, // #LATIN CAPITAL LETTER W - 0x0058, // #LATIN CAPITAL LETTER X - 0x0059, // #LATIN CAPITAL LETTER Y - 0x005a, // #LATIN CAPITAL LETTER Z - 0x005b, // #LEFT SQUARE BRACKET - 0x005c, // #REVERSE SOLIDUS - 0x005d, // #RIGHT SQUARE BRACKET - 0x005e, // #CIRCUMFLEX ACCENT - 0x005f, // #LOW LINE - 0x0060, // #GRAVE ACCENT - 0x0061, // #LATIN SMALL LETTER A - 0x0062, // #LATIN SMALL LETTER B - 0x0063, // #LATIN SMALL LETTER C - 0x0064, // #LATIN SMALL LETTER D - 0x0065, // #LATIN SMALL LETTER E - 0x0066, // #LATIN SMALL LETTER F - 0x0067, // #LATIN SMALL LETTER G - 0x0068, // #LATIN SMALL LETTER H - 0x0069, // #LATIN SMALL LETTER I - 0x006a, // #LATIN SMALL LETTER J - 0x006b, // #LATIN SMALL LETTER K - 0x006c, // #LATIN SMALL LETTER L - 0x006d, // #LATIN SMALL LETTER M - 0x006e, // #LATIN SMALL LETTER N - 0x006f, // #LATIN SMALL LETTER O - 0x0070, // #LATIN SMALL LETTER P - 0x0071, // #LATIN SMALL LETTER Q - 0x0072, // #LATIN SMALL LETTER R - 0x0073, // #LATIN SMALL LETTER S - 0x0074, // #LATIN SMALL LETTER T - 0x0075, // #LATIN SMALL LETTER U - 0x0076, // #LATIN SMALL LETTER V - 0x0077, // #LATIN SMALL LETTER W - 0x0078, // #LATIN SMALL LETTER X - 0x0079, // #LATIN SMALL LETTER Y - 0x007a, // #LATIN SMALL LETTER Z - 0x007b, // #LEFT CURLY BRACKET - 0x007c, // #VERTICAL LINE - 0x007d, // #RIGHT CURLY BRACKET - 0x007e, // #TILDE - 0x007f, // #DELETE - 0x00c7, // #LATIN CAPITAL LETTER C WITH CEDILLA - 0x00fc, // #LATIN SMALL LETTER U WITH DIAERESIS - 0x00e9, // #LATIN SMALL LETTER E WITH ACUTE - 0x00e2, // #LATIN SMALL LETTER A WITH CIRCUMFLEX - 0x00e4, // #LATIN SMALL LETTER A WITH DIAERESIS - 0x00e0, // #LATIN SMALL LETTER A WITH GRAVE - 0x00e5, // #LATIN SMALL LETTER A WITH RING ABOVE - 0x00e7, // #LATIN SMALL LETTER C WITH CEDILLA - 0x00ea, // #LATIN SMALL LETTER E WITH CIRCUMFLEX - 0x00eb, // #LATIN SMALL LETTER E WITH DIAERESIS - 0x00e8, // #LATIN SMALL LETTER E WITH GRAVE - 0x00ef, // #LATIN SMALL LETTER I WITH DIAERESIS - 0x00ee, // #LATIN SMALL LETTER I WITH CIRCUMFLEX - 0x00ec, // #LATIN SMALL LETTER I WITH GRAVE - 0x00c4, // #LATIN CAPITAL LETTER A WITH DIAERESIS - 0x00c5, // #LATIN CAPITAL LETTER A WITH RING ABOVE - 0x00c9, // #LATIN CAPITAL LETTER E WITH ACUTE - 0x00e6, // #LATIN SMALL LIGATURE AE - 0x00c6, // #LATIN CAPITAL LIGATURE AE - 0x00f4, // #LATIN SMALL LETTER O WITH CIRCUMFLEX - 0x00f6, // #LATIN SMALL LETTER O WITH DIAERESIS - 0x00f2, // #LATIN SMALL LETTER O WITH GRAVE - 0x00fb, // #LATIN SMALL LETTER U WITH CIRCUMFLEX - 0x00f9, // #LATIN SMALL LETTER U WITH GRAVE - 0x00ff, // #LATIN SMALL LETTER Y WITH DIAERESIS - 0x00d6, // #LATIN CAPITAL LETTER O WITH DIAERESIS - 0x00dc, // #LATIN CAPITAL LETTER U WITH DIAERESIS - 0x00a2, // #CENT SIGN - 0x00a3, // #POUND SIGN - 0x00a5, // #YEN SIGN - 0x20a7, // #PESETA SIGN - 0x0192, // #LATIN SMALL LETTER F WITH HOOK - 0x00e1, // #LATIN SMALL LETTER A WITH ACUTE - 0x00ed, // #LATIN SMALL LETTER I WITH ACUTE - 0x00f3, // #LATIN SMALL LETTER O WITH ACUTE - 0x00fa, // #LATIN SMALL LETTER U WITH ACUTE - 0x00f1, // #LATIN SMALL LETTER N WITH TILDE - 0x00d1, // #LATIN CAPITAL LETTER N WITH TILDE - 0x00aa, // #FEMININE ORDINAL INDICATOR - 0x00ba, // #MASCULINE ORDINAL INDICATOR - 0x00bf, // #INVERTED QUESTION MARK - 0x2310, // #REVERSED NOT SIGN - 0x00ac, // #NOT SIGN - 0x00bd, // #VULGAR FRACTION ONE HALF - 0x00bc, // #VULGAR FRACTION ONE QUARTER - 0x00a1, // #INVERTED EXCLAMATION MARK - 0x00ab, // #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - 0x00bb, // #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - 0x2591, // #LIGHT SHADE - 0x2592, // #MEDIUM SHADE - 0x2593, // #DARK SHADE - 0x2502, // #BOX DRAWINGS LIGHT VERTICAL - 0x2524, // #BOX DRAWINGS LIGHT VERTICAL AND LEFT - 0x2561, // #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE - 0x2562, // #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE - 0x2556, // #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE - 0x2555, // #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE - 0x2563, // #BOX DRAWINGS DOUBLE VERTICAL AND LEFT - 0x2551, // #BOX DRAWINGS DOUBLE VERTICAL - 0x2557, // #BOX DRAWINGS DOUBLE DOWN AND LEFT - 0x255d, // #BOX DRAWINGS DOUBLE UP AND LEFT - 0x255c, // #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE - 0x255b, // #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE - 0x2510, // #BOX DRAWINGS LIGHT DOWN AND LEFT - 0x2514, // #BOX DRAWINGS LIGHT UP AND RIGHT - 0x2534, // #BOX DRAWINGS LIGHT UP AND HORIZONTAL - 0x252c, // #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - 0x251c, // #BOX DRAWINGS LIGHT VERTICAL AND RIGHT - 0x2500, // #BOX DRAWINGS LIGHT HORIZONTAL - 0x253c, // #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - 0x255e, // #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE - 0x255f, // #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE - 0x255a, // #BOX DRAWINGS DOUBLE UP AND RIGHT - 0x2554, // #BOX DRAWINGS DOUBLE DOWN AND RIGHT - 0x2569, // #BOX DRAWINGS DOUBLE UP AND HORIZONTAL - 0x2566, // #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL - 0x2560, // #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT - 0x2550, // #BOX DRAWINGS DOUBLE HORIZONTAL - 0x256c, // #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL - 0x2567, // #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE - 0x2568, // #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE - 0x2564, // #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE - 0x2565, // #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE - 0x2559, // #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE - 0x2558, // #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE - 0x2552, // #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE - 0x2553, // #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE - 0x256b, // #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE - 0x256a, // #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE - 0x2518, // #BOX DRAWINGS LIGHT UP AND LEFT - 0x250c, // #BOX DRAWINGS LIGHT DOWN AND RIGHT - 0x2588, // #FULL BLOCK - 0x2584, // #LOWER HALF BLOCK - 0x258c, // #LEFT HALF BLOCK - 0x2590, // #RIGHT HALF BLOCK - 0x2580, // #UPPER HALF BLOCK - 0x03b1, // #GREEK SMALL LETTER ALPHA - 0x00df, // #LATIN SMALL LETTER SHARP S - 0x0393, // #GREEK CAPITAL LETTER GAMMA - 0x03c0, // #GREEK SMALL LETTER PI - 0x03a3, // #GREEK CAPITAL LETTER SIGMA - 0x03c3, // #GREEK SMALL LETTER SIGMA - 0x00b5, // #MICRO SIGN - 0x03c4, // #GREEK SMALL LETTER TAU - 0x03a6, // #GREEK CAPITAL LETTER PHI - 0x0398, // #GREEK CAPITAL LETTER THETA - 0x03a9, // #GREEK CAPITAL LETTER OMEGA - 0x03b4, // #GREEK SMALL LETTER DELTA - 0x221e, // #INFINITY - 0x03c6, // #GREEK SMALL LETTER PHI - 0x03b5, // #GREEK SMALL LETTER EPSILON - 0x2229, // #INTERSECTION - 0x2261, // #IDENTICAL TO - 0x00b1, // #PLUS-MINUS SIGN - 0x2265, // #GREATER-THAN OR EQUAL TO - 0x2264, // #LESS-THAN OR EQUAL TO - 0x2320, // #TOP HALF INTEGRAL - 0x2321, // #BOTTOM HALF INTEGRAL - 0x00f7, // #DIVISION SIGN - 0x2248, // #ALMOST EQUAL TO - 0x00b0, // #DEGREE SIGN - 0x2219, // #BULLET OPERATOR - 0x00b7, // #MIDDLE DOT - 0x221a, // #SQUARE ROOT - 0x207f, // #SUPERSCRIPT LATIN SMALL LETTER N - 0x00b2, // #SUPERSCRIPT TWO - 0x25a0, // #BLACK SQUARE - 0x00a0, // #NO-BREAK SPACE - }; - - public char map_cp850_unicode(char x) { - if (x >= 0x100) - return x; - - return unimap[x]; - } - - private void _SetCursor(int row, int col) { - int maxr = height - 1; - int tm = getTopMargin(); - R = (row < 0) ? 0 : row; - C = (col < 0) ? 0 : (col >= width) ? width - 1 : col; - - if (!moveoutsidemargins) { - R += tm; - maxr = getBottomMargin(); - } - - if (R > maxr) R = maxr; - } - - private void putChar(char c, boolean isWide, boolean doshowcursor) { - int rows = this.height; //statusline - int columns = this.width; - - // byte msg[]; -// if (debug > 4) { -// debugStr.append("putChar(") -// .append(c) -// .append(" [") -// .append((int) c) -// .append("]) at R=") -// .append(R) -// .append(" , C=") -// .append(C) -// .append(", columns=") -// .append(columns) -// .append(", rows=") -// .append(rows); -// debug(debugStr.toString()); -// debugStr.setLength(0); -// } -// markLine(R, 1); -// if (c > 255) { -// if (debug > 0) -// debug("char > 255:" + (int) c); -// //return; -// } - switch (term_state) { - case TSTATE_DATA: - - /* FIXME: we shouldn't use chars with bit 8 set if ibmcharset. - * probably... but some BBS do anyway... - */ - if (!useibmcharset) { - boolean doneflag = true; - - switch (c) { - case OSC: - osc = ""; - term_state = TSTATE_OSC; - break; - - case RI: - if (R > getTopMargin()) - R--; - else - insertLine(R, 1, SCROLL_DOWN); - - if (debug > 1) - debug("RI"); - - break; - - case IND: - if (debug > 2) { - debugStr.append("IND at ") - .append(R) - .append(", tm is ") - .append(getTopMargin()) - .append(", bm is ") - .append(getBottomMargin()); - debug(debugStr.toString()); - debugStr.setLength(0); - } - - if (R == getBottomMargin() || R == rows - 1) - insertLine(R, 1, SCROLL_UP); - else - R++; - - if (debug > 1) - debug("IND (at " + R + " )"); - - break; - - case NEL: - if (R == getBottomMargin() || R == rows - 1) - insertLine(R, 1, SCROLL_UP); - else - R++; - - C = 0; - - if (debug > 1) - debug("NEL (at " + R + " )"); - - break; - - case HTS: - Tabs[C] = 1; - - if (debug > 1) - debug("HTS"); - - break; - - case DCS: - dcs = ""; - term_state = TSTATE_DCS; - break; - - default: - doneflag = false; - break; - } - - if (doneflag) break; - } - - switch (c) { - case SS3: - onegl = 3; - break; - - case SS2: - onegl = 2; - break; - - case CSI: // should be in the 8bit section, but some BBS use this - DCEvar = 0; - DCEvars[0] = 0; - DCEvars[1] = 0; - DCEvars[2] = 0; - DCEvars[3] = 0; - term_state = TSTATE_CSI; - break; - - case ESC: - term_state = TSTATE_ESC; - lastwaslf = 0; - break; - - case 5: /* ENQ */ - write(answerBack, false); - break; - - case 12: - /* FormFeed, Home for the BBS world */ - deleteArea(0, 0, columns, rows, attributes); - C = R = 0; - break; - - case '\b': /* 8 */ - C--; - - if (C < 0) - C = 0; - - lastwaslf = 0; - break; - - case '\t': - do { - // Don't overwrite or insert! TABS are not destructive, but movement! - C++; - } - while (C < columns && (Tabs[C] == 0)); - - lastwaslf = 0; - break; - - case '\r': // 13 CR - C = 0; - break; - - case '\n': // 10 LF - if (debug > 3) - debug("R= " + R + ", bm " + getBottomMargin() + ", tm=" + getTopMargin() + ", rows=" + rows); - - if (!vms) { - if (lastwaslf != 0 && lastwaslf != c) // Ray: I do not understand this logic. - break; - - lastwaslf = c; - /*C = 0;*/ - } - - if (R == getBottomMargin() || R >= rows - 1) - insertLine(R, 1, SCROLL_UP); - else - R++; - - break; - - case 7: - beep(); - break; - - case '\016': /* SMACS , as */ - /* ^N, Shift out - Put G1 into GL */ - gl = 1; - usedcharsets = true; - break; - - case '\017': /* RMACS , ae */ - /* ^O, Shift in - Put G0 into GL */ - gl = 0; - usedcharsets = true; - break; - - default: { - int thisgl = gl; - - if (onegl >= 0) { - thisgl = onegl; - onegl = -1; - } - - lastwaslf = 0; - - if (c < 32) { - if (c != 0) - if (debug > 0) - debug("TSTATE_DATA char: " + ((int) c)); - - /*break; some BBS really want those characters, like hearst etc. */ - if (c == 0) /* print 0 ... you bet */ - break; - } - - if (C >= columns) { - if (wraparound) { - int bot = rows; - - // If we're in the scroll region, check against the bottom margin - if (R <= getBottomMargin() && R >= getTopMargin()) - bot = getBottomMargin() + 1; - - if (R < bot - 1) - R++; - else { - if (debug > 3) debug("scrolling due to wrap at " + R); - - insertLine(R, 1, SCROLL_UP); - } - - C = 0; - } - else { - // cursor stays on last character. - C = columns - 1; - } - } - - boolean mapped = false; - - // Mapping if DEC Special is chosen charset - if (usedcharsets) { - if (c >= '\u0020' && c <= '\u007f') { - switch (gx[thisgl]) { - case '0': - - // Remap SCOANSI line drawing to VT100 line drawing chars - // for our SCO using customers. - if (terminalID.equals("scoansi") || terminalID.equals("ansi")) { - for (int i = 0; i < scoansi_acs.length(); i += 2) { - if (c == scoansi_acs.charAt(i)) { - c = scoansi_acs.charAt(i + 1); - break; - } - } - } - - if (c >= '\u005f' && c <= '\u007e') { - c = DECSPECIAL[(short) c - 0x5f]; - mapped = true; - } - - break; - - case '<': // 'user preferred' is currently 'ISO Latin-1 suppl - c = (char)((c & 0x7f) | 0x80); - mapped = true; - break; - - case 'A': - case 'B': // Latin-1 , ASCII -> fall through - mapped = true; - break; - - default: - debug("Unsupported GL mapping: " + gx[thisgl]); - break; - } - } - - if (!mapped && (c >= '\u0080' && c <= '\u00ff')) { - switch (gx[gr]) { - case '0': - if (c >= '\u00df' && c <= '\u00fe') { - c = DECSPECIAL[c - '\u00df']; - mapped = true; - } - - break; - - case '<': - case 'A': - case 'B': - mapped = true; - break; - - default: - debug("Unsupported GR mapping: " + gx[gr]); - break; - } - } - } - - if (!mapped && useibmcharset) - c = map_cp850_unicode(c); - - /*if(true || (statusmode == 0)) { */ - if (isWide) { - if (C >= columns - 1) { - if (wraparound) { - int bot = rows; - - // If we're in the scroll region, check against the bottom margin - if (R <= getBottomMargin() && R >= getTopMargin()) - bot = getBottomMargin() + 1; - - if (R < bot - 1) - R++; - else { - if (debug > 3) debug("scrolling due to wrap at " + R); - - insertLine(R, 1, SCROLL_UP); - } - - C = 0; - } - else { - // cursor stays on last wide character. - C = columns - 2; - } - } - } - - if (insertmode == 1) { - if (isWide) { - insertChar(C++, R, c, attributes | FULLWIDTH); - insertChar(C, R, ' ', attributes | FULLWIDTH); - } - else - insertChar(C, R, c, attributes); - } - else { - if (isWide) { - putChar(C++, R, c, attributes | FULLWIDTH); - putChar(C, R, ' ', attributes | FULLWIDTH); - } - else - putChar(C, R, c, attributes); - } - - /* - } else { - if (insertmode==1) { - insertChar(C, rows, c, attributes); - } else { - putChar(C, rows, c, attributes); - } - } - */ - C++; - break; - } - } /* switch(c) */ - - break; - - case TSTATE_OSC: - if ((c < 0x20) && (c != ESC)) {// NP - No printing character - handle_osc(osc); - term_state = TSTATE_DATA; - break; - } - - //but check for vt102 ESC \ - if (c == '\\' && osc.charAt(osc.length() - 1) == ESC) { - handle_osc(osc); - term_state = TSTATE_DATA; - break; - } - - osc = osc + c; - break; - - case TSTATE_ESCSPACE: - term_state = TSTATE_DATA; - - switch (c) { - case 'F': /* S7C1T, Disable output of 8-bit controls, use 7-bit */ - output8bit = false; - break; - - case 'G': /* S8C1T, Enable output of 8-bit control codes*/ - output8bit = true; - break; - - default: - debug("ESC <space> " + c + " unhandled."); - } - - break; - - case TSTATE_ESC: - term_state = TSTATE_DATA; - - switch (c) { - case ' ': - term_state = TSTATE_ESCSPACE; - break; - - case '#': - term_state = TSTATE_ESCSQUARE; - break; - - case 'c': - /* Hard terminal reset */ - reset(); - break; - - case '[': - DCEvar = 0; - DCEvars[0] = 0; - DCEvars[1] = 0; - DCEvars[2] = 0; - DCEvars[3] = 0; - term_state = TSTATE_CSI; - break; - - case ']': - osc = ""; - term_state = TSTATE_OSC; - break; - - case 'P': - dcs = ""; - term_state = TSTATE_DCS; - break; - - case 'A': /* CUU */ - R--; - - if (R < 0) R = 0; - - break; - - case 'B': /* CUD */ - R++; - - if (R >= rows) R = rows - 1; - - break; - - case 'C': - C++; - - if (C >= columns) C = columns - 1; - - break; - - case 'I': // RI - insertLine(R, 1, SCROLL_DOWN); - break; - - case 'E': /* NEL */ - if (R == getBottomMargin() || R == rows - 1) - insertLine(R, 1, SCROLL_UP); - else - R++; - - C = 0; - - if (debug > 1) - debug("ESC E (at " + R + ")"); - - break; - - case 'D': /* IND */ - if (R == getBottomMargin() || R == rows - 1) - insertLine(R, 1, SCROLL_UP); - else - R++; - - if (debug > 1) - debug("ESC D (at " + R + " )"); - - break; - - case 'J': /* erase to end of screen */ - if (R < rows - 1) - deleteArea(0, R + 1, columns, rows - R - 1, attributes); - - if (C < columns - 1) - deleteArea(C, R, columns - C, 1, attributes); - - break; - - case 'K': - if (C < columns - 1) - deleteArea(C, R, columns - C, 1, attributes); - - break; - - case 'M': // RI - debug("ESC M : R is " + R + ", tm is " + getTopMargin() + ", bm is " + getBottomMargin()); - - if (R > getTopMargin()) { // just go up 1 line. - R--; - } - else { // scroll down - insertLine(R, 1, SCROLL_DOWN); - } - - /* else do nothing ; */ - if (debug > 2) - debug("ESC M "); - - break; - - case 'H': - if (debug > 1) - debug("ESC H at " + C); - - /* right border probably ...*/ - if (C >= columns) - C = columns - 1; - - Tabs[C] = 1; - break; - - case 'N': // SS2 - onegl = 2; - break; - - case 'O': // SS3 - onegl = 3; - break; - - case '=': - - /*application keypad*/ - if (debug > 0) - debug("ESC ="); - - keypadmode = true; - break; - - case '<': /* vt52 mode off */ - vt52mode = false; - break; - - case '>': /*normal keypad*/ - if (debug > 0) - debug("ESC >"); - - keypadmode = false; - break; - - case '7': /* DECSC: save cursor, attributes */ - Sc = C; - Sr = R; - Sgl = gl; - Sgr = gr; - Sa = attributes; - Sgx = new char[4]; - - for (int i = 0; i < 4; i++) Sgx[i] = gx[i]; - - if (debug > 1) - debug("ESC 7"); - - break; - - case '8': /* DECRC: restore cursor, attributes */ - C = Sc; - R = Sr; - gl = Sgl; - gr = Sgr; - - if (Sgx != null) - for (int i = 0; i < 4; i++) gx[i] = Sgx[i]; - - attributes = Sa; - - if (debug > 1) - debug("ESC 8"); - - break; - - case '(': /* Designate G0 Character set (ISO 2022) */ - term_state = TSTATE_SETG0; - usedcharsets = true; - break; - - case ')': /* Designate G1 character set (ISO 2022) */ - term_state = TSTATE_SETG1; - usedcharsets = true; - break; - - case '*': /* Designate G2 Character set (ISO 2022) */ - term_state = TSTATE_SETG2; - usedcharsets = true; - break; - - case '+': /* Designate G3 Character set (ISO 2022) */ - term_state = TSTATE_SETG3; - usedcharsets = true; - break; - - case '~': /* Locking Shift 1, right */ - gr = 1; - usedcharsets = true; - break; - - case 'n': /* Locking Shift 2 */ - gl = 2; - usedcharsets = true; - break; - - case '}': /* Locking Shift 2, right */ - gr = 2; - usedcharsets = true; - break; - - case 'o': /* Locking Shift 3 */ - gl = 3; - usedcharsets = true; - break; - - case '|': /* Locking Shift 3, right */ - gr = 3; - usedcharsets = true; - break; - - case 'Y': /* vt52 cursor address mode , next chars are x,y */ - term_state = TSTATE_VT52Y; - break; - - case '_': - term_state = TSTATE_TITLE; - break; - - case '\\': - // TODO save title - term_state = TSTATE_DATA; - break; - - default: - debug("ESC unknown letter: " + c + " (" + ((int) c) + ")"); - break; - } - - break; - - case TSTATE_VT52X: - C = c - 37; - - if (C < 0) - C = 0; - else if (C >= width) - C = width - 1; - - term_state = TSTATE_VT52Y; - break; - - case TSTATE_VT52Y: - R = c - 37; - - if (R < 0) - R = 0; - else if (R >= height) - R = height - 1; - - term_state = TSTATE_DATA; - break; - - case TSTATE_SETG0: - if (c != '0' && c != 'A' && c != 'B' && c != '<') - debug("ESC ( " + c + ": G0 char set? (" + ((int) c) + ")"); - else { - if (debug > 2) debug("ESC ( : G0 char set (" + c + " " + ((int) c) + ")"); - - gx[0] = c; - } - - term_state = TSTATE_DATA; - break; - - case TSTATE_SETG1: - if (c != '0' && c != 'A' && c != 'B' && c != '<') { - debug("ESC ) " + c + " (" + ((int) c) + ") :G1 char set?"); - } - else { - if (debug > 2) debug("ESC ) :G1 char set (" + c + " " + ((int) c) + ")"); - - gx[1] = c; - } - - term_state = TSTATE_DATA; - break; - - case TSTATE_SETG2: - if (c != '0' && c != 'A' && c != 'B' && c != '<') - debug("ESC*:G2 char set? (" + ((int) c) + ")"); - else { - if (debug > 2) debug("ESC*:G2 char set (" + c + " " + ((int) c) + ")"); - - gx[2] = c; - } - - term_state = TSTATE_DATA; - break; - - case TSTATE_SETG3: - if (c != '0' && c != 'A' && c != 'B' && c != '<') - debug("ESC+:G3 char set? (" + ((int) c) + ")"); - else { - if (debug > 2) debug("ESC+:G3 char set (" + c + " " + ((int) c) + ")"); - - gx[3] = c; - } - - term_state = TSTATE_DATA; - break; - - case TSTATE_ESCSQUARE: - switch (c) { - case '8': - for (int i = 0; i < columns; i++) - for (int j = 0; j < rows; j++) - putChar(i, j, 'E', 0); - - break; - - default: - debug("ESC # " + c + " not supported."); - break; - } - - term_state = TSTATE_DATA; - break; - - case TSTATE_DCS: - if (c == '\\' && dcs.charAt(dcs.length() - 1) == ESC) { - handle_dcs(dcs); - term_state = TSTATE_DATA; - break; - } - - dcs = dcs + c; - break; - - case TSTATE_DCEQ: - term_state = TSTATE_DATA; - - switch (c) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48; - term_state = TSTATE_DCEQ; - break; - - case ';': - DCEvar++; - DCEvars[DCEvar] = 0; - term_state = TSTATE_DCEQ; - break; - - case 's': // XTERM_SAVE missing! - if (true || debug > 1) - debug("ESC [ ? " + DCEvars[0] + " s unimplemented!"); - - break; - - case 'r': // XTERM_RESTORE - if (true || debug > 1) - debug("ESC [ ? " + DCEvars[0] + " r"); - - /* DEC Mode reset */ - for (int i = 0; i <= DCEvar; i++) { - switch (DCEvars[i]) { - case 3: /* 80 columns*/ - setScreenSize(80, height, true); - break; - - case 4: /* scrolling mode, smooth */ - break; - - case 5: /* light background */ - break; - - case 6: /* DECOM (Origin Mode) move inside margins. */ - moveoutsidemargins = true; - break; - - case 7: /* DECAWM: Autowrap Mode */ - wraparound = false; - break; - - case 12:/* local echo off */ - break; - - case 9: /* X10 mouse */ - case 1000: /* xterm style mouse report on */ - case 1001: - case 1002: - case 1003: - mouserpt = DCEvars[i]; - break; - - default: - debug("ESC [ ? " + DCEvars[0] + " r, unimplemented!"); - } - } - - break; - - case 'h': // DECSET - if (debug > 0) - debug("ESC [ ? " + DCEvars[0] + " h"); - - /* DEC Mode set */ - for (int i = 0; i <= DCEvar; i++) { - switch (DCEvars[i]) { - case 1: /* Application cursor keys */ - KeyUp[0] = "\u001bOA"; - KeyDown[0] = "\u001bOB"; - KeyRight[0] = "\u001bOC"; - KeyLeft[0] = "\u001bOD"; - break; - - case 2: /* DECANM */ - vt52mode = false; - break; - - case 3: /* 132 columns*/ - setScreenSize(132, height, true); - break; - - case 6: /* DECOM: move inside margins. */ - moveoutsidemargins = false; - break; - - case 7: /* DECAWM: Autowrap Mode */ - wraparound = true; - break; - - case 25: /* turn cursor on */ - showCursor(true); - break; - - case 9: /* X10 mouse */ - case 1000: /* xterm style mouse report on */ - case 1001: - case 1002: - case 1003: - mouserpt = DCEvars[i]; - break; - - /* unimplemented stuff, fall through */ - /* 4 - scrolling mode, smooth */ - /* 5 - light background */ - /* 12 - local echo off */ - /* 18 - DECPFF - Printer Form Feed Mode -> On */ - /* 19 - DECPEX - Printer Extent Mode -> Screen */ - default: - debug("ESC [ ? " + DCEvars[0] + " h, unsupported."); - break; - } - } - - break; - - case 'i': // DEC Printer Control, autoprint, echo screenchars to printer - - // This is different to CSI i! - // Also: "Autoprint prints a final display line only when the - // cursor is moved off the line by an autowrap or LF, FF, or - // VT (otherwise do not print the line)." - switch (DCEvars[0]) { - case 1: - if (debug > 1) - debug("CSI ? 1 i : Print line containing cursor"); - - break; - - case 4: - if (debug > 1) - debug("CSI ? 4 i : Start passthrough printing"); - - break; - - case 5: - if (debug > 1) - debug("CSI ? 4 i : Stop passthrough printing"); - - break; - } - - break; - - case 'l': //DECRST - - /* DEC Mode reset */ - if (debug > 0) - debug("ESC [ ? " + DCEvars[0] + " l"); - - for (int i = 0; i <= DCEvar; i++) { - switch (DCEvars[i]) { - case 1: /* Application cursor keys */ - KeyUp[0] = "\u001b[A"; - KeyDown[0] = "\u001b[B"; - KeyRight[0] = "\u001b[C"; - KeyLeft[0] = "\u001b[D"; - break; - - case 2: /* DECANM */ - vt52mode = true; - break; - - case 3: /* 80 columns*/ - setScreenSize(80, height, true); - break; - - case 6: /* DECOM: move outside margins. */ - moveoutsidemargins = true; - break; - - case 7: /* DECAWM: Autowrap Mode OFF */ - wraparound = false; - break; - - case 25: /* turn cursor off */ - showCursor(false); - break; - - /* Unimplemented stuff: */ - /* 4 - scrolling mode, jump */ - /* 5 - dark background */ - /* 7 - DECAWM - no wrap around mode */ - /* 12 - local echo on */ - /* 18 - DECPFF - Printer Form Feed Mode -> Off*/ - /* 19 - DECPEX - Printer Extent Mode -> Scrolling Region */ - case 9: /* X10 mouse */ - case 1000: /* xterm style mouse report OFF */ - case 1001: - case 1002: - case 1003: - mouserpt = 0; - break; - - default: - debug("ESC [ ? " + DCEvars[0] + " l, unsupported."); - break; - } - } - - break; - - case 'n': - if (debug > 0) - debug("ESC [ ? " + DCEvars[0] + " n"); - - switch (DCEvars[0]) { - case 15: - /* printer? no printer. */ - write((ESC) + "[?13n", false); - debug("ESC[5n"); - break; - - default: - debug("ESC [ ? " + DCEvars[0] + " n, unsupported."); - break; - } - - break; - - default: - debug("ESC [ ? " + DCEvars[0] + " " + c + ", unsupported."); - break; - } - - break; - - case TSTATE_CSI_EX: - term_state = TSTATE_DATA; - - switch (c) { - case ESC: - term_state = TSTATE_ESC; - break; - - default: - debug("Unknown character ESC[! character is " + (int) c); - break; - } - - break; - - case TSTATE_CSI_TICKS: - term_state = TSTATE_DATA; - - switch (c) { - case 'p': - debug("Conformance level: " + DCEvars[0] + " (unsupported)," + DCEvars[1]); - - if (DCEvars[0] == 61) { - output8bit = false; - break; - } - - if (DCEvars[1] == 1) { - output8bit = false; - } - else { - output8bit = true; /* 0 or 2 */ - } - - break; - - default: - debug("Unknown ESC [... \"" + c); - break; - } - - break; - - case TSTATE_CSI_EQUAL: - term_state = TSTATE_DATA; - - switch (c) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48; - term_state = TSTATE_CSI_EQUAL; - break; - - case ';': - DCEvar++; - DCEvars[DCEvar] = 0; - term_state = TSTATE_CSI_EQUAL; - break; - - case 'F': { /* SCO ANSI foreground */ - int newcolor; - debug("ESC [ = " + DCEvars[0] + " F"); - attributes &= ~COLOR_FG; - newcolor = ((DCEvars[0] & 1) << 2) | - (DCEvars[0] & 2) | - ((DCEvars[0] & 4) >> 2) ; - attributes |= (newcolor + 1) << COLOR_FG_SHIFT; - break; - } - - case 'G': { /* SCO ANSI background */ - int newcolor; - debug("ESC [ = " + DCEvars[0] + " G"); - attributes &= ~COLOR_BG; - newcolor = ((DCEvars[0] & 1) << 2) | - (DCEvars[0] & 2) | - ((DCEvars[0] & 4) >> 2) ; - attributes |= (newcolor + 1) << COLOR_BG_SHIFT; - break; - } - - default: - debugStr.append("Unknown ESC [ = "); - - for (int i = 0; i <= DCEvar; i++) { - debugStr.append(DCEvars[i]) - .append(','); - } - - debugStr.append(c); - debug(debugStr.toString()); - debugStr.setLength(0); - break; - } - - break; - - case TSTATE_CSI_DOLLAR: - term_state = TSTATE_DATA; - - switch (c) { - case '}': - debug("Active Status Display now " + DCEvars[0]); - statusmode = DCEvars[0]; - break; - - /* bad documentation? - case '-': - debug("Set Status Display now "+DCEvars[0]); - break; - */ - case '~': - debug("Status Line mode now " + DCEvars[0]); - break; - - default: - debug("UNKNOWN Status Display code " + c + ", with Pn=" + DCEvars[0]); - break; - } - - break; - - case TSTATE_CSI: - term_state = TSTATE_DATA; - - switch (c) { - case '"': - term_state = TSTATE_CSI_TICKS; - break; - - case '$': - term_state = TSTATE_CSI_DOLLAR; - break; - - case '=': - term_state = TSTATE_CSI_EQUAL; - break; - - case '!': - term_state = TSTATE_CSI_EX; - break; - - case '?': - DCEvar = 0; - DCEvars[0] = 0; - term_state = TSTATE_DCEQ; - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - DCEvars[DCEvar] = DCEvars[DCEvar] * 10 + (c) - 48; - term_state = TSTATE_CSI; - break; - - case ';': - DCEvar++; - DCEvars[DCEvar] = 0; - term_state = TSTATE_CSI; - break; - - case 'c':/* send primary device attributes */ - /* send (ESC[?61c) */ - String subcode = ""; - - if (terminalID.equals("vt320")) subcode = "63;"; - - if (terminalID.equals("vt220")) subcode = "62;"; - - if (terminalID.equals("vt100")) subcode = "61;"; - - write((ESC) + "[?" + subcode + "1;2c", false); - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " c"); - - break; - - case 'q': - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " q"); - - break; - - case 'g': - - /* used for tabsets */ - switch (DCEvars[0]) { - case 3:/* clear them */ - Tabs = new byte[width]; - break; - - case 0: - Tabs[C] = 0; - break; - } - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " g"); - - break; - - case 'h': - switch (DCEvars[0]) { - case 4: - insertmode = 1; - break; - - case 20: - debug("Setting CRLF to TRUE"); - sendcrlf = true; - break; - - default: - debug("unsupported: ESC [ " + DCEvars[0] + " h"); - break; - } - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " h"); - - break; - - case 'i': // Printer Controller mode. - - // "Transparent printing sends all output, except the CSI 4 i - // termination string, to the printer and not the screen, - // uses an 8-bit channel if no parity so NUL and DEL will be - // seen by the printer and by the termination recognizer code, - // and all translation and character set selections are - // bypassed." - switch (DCEvars[0]) { - case 0: - if (debug > 1) - debug("CSI 0 i: Print Screen, not implemented."); - - break; - - case 4: - if (debug > 1) - debug("CSI 4 i: Enable Transparent Printing, not implemented."); - - break; - - case 5: - if (debug > 1) - debug("CSI 4/5 i: Disable Transparent Printing, not implemented."); - - break; - - default: - debug("ESC [ " + DCEvars[0] + " i, unimplemented!"); - } - - break; - - case 'l': - switch (DCEvars[0]) { - case 4: - insertmode = 0; - break; - - case 20: - debug("Setting CRLF to FALSE"); - sendcrlf = false; - break; - - default: - debug("ESC [ " + DCEvars[0] + " l, unimplemented!"); - break; - } - - break; - - case 'A': { // CUU - int limit; - - /* FIXME: xterm only cares about 0 and topmargin */ - if (R >= getTopMargin()) { - limit = getTopMargin(); - } - else - limit = 0; - - if (DCEvars[0] == 0) - R--; - else - R -= DCEvars[0]; - - if (R < limit) - R = limit; - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " A"); - - break; - } - - case 'B': // CUD - /* cursor down n (1) times */ - { - int limit; - - if (R <= getBottomMargin()) { - limit = getBottomMargin(); - } - else - limit = rows - 1; - - if (DCEvars[0] == 0) - R++; - else - R += DCEvars[0]; - - if (R > limit) - R = limit; - else { - if (debug > 2) debug("Not limited."); - } - - if (debug > 2) debug("to: " + R); - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " B (at C=" + C + ")"); - - break; - } - - case 'C': - if (DCEvars[0] == 0) - DCEvars[0] = 1; - - while (DCEvars[0]-- > 0) { - C++; - } - - if (C >= columns) - C = columns - 1; - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " C"); - - break; - - case 'd': // CVA - R = DCEvars[0] - 1; - - if (R < 0) - R = 0; - else if (R >= height) - R = height - 1; - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " d"); - - break; - - case 'D': - if (DCEvars[0] == 0) - DCEvars[0] = 1; - - while (DCEvars[0]-- > 0) { - C--; - } - - if (C < 0) C = 0; - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " D"); - - break; - - case 'r': // DECSTBM - if (DCEvar > 0) { // Ray: Any argument is optional - R = DCEvars[1] - 1; - - if (R < 0) - R = rows - 1; - else if (R >= rows) { - R = rows - 1; - } - } - else - R = rows - 1; - - int bot = R; - - if (R >= DCEvars[0]) { - R = DCEvars[0] - 1; - - if (R < 0) - R = 0; - } - - setMargins(R, bot); - _SetCursor(0, 0); - - if (debug > 1) - debug("ESC [" + DCEvars[0] + " ; " + DCEvars[1] + " r"); - - break; - - case 'G': /* CUP / cursor absolute column */ - C = DCEvars[0]; - - if (C < 0) - C = 0; - else if (C >= width) - C = width - 1; - - if (debug > 1) debug("ESC [ " + DCEvars[0] + " G"); - - break; - - case 'H': /* CUP / cursor position */ - /* gets 2 arguments */ - _SetCursor(DCEvars[0] - 1, DCEvars[1] - 1); - - if (debug > 2) { - debug("ESC [ " + DCEvars[0] + ";" + DCEvars[1] + " H, moveoutsidemargins " + moveoutsidemargins); - debug(" -> R now " + R + ", C now " + C); - } - - break; - - case 'f': /* move cursor 2 */ - /* gets 2 arguments */ - R = DCEvars[0] - 1; - C = DCEvars[1] - 1; - - if (C < 0) - C = 0; - else if (C >= width) - C = width - 1; - - if (R < 0) - R = 0; - else if (R >= height) - R = height - 1; - - if (debug > 2) - debug("ESC [ " + DCEvars[0] + ";" + DCEvars[1] + " f"); - - break; - - case 'S': /* ind aka 'scroll forward' */ - if (DCEvars[0] == 0) - insertLine(getBottomMargin(), SCROLL_UP); - else - insertLine(getBottomMargin(), DCEvars[0], SCROLL_UP); - - break; - - case 'L': - - /* insert n lines */ - if (DCEvars[0] == 0) - insertLine(R, SCROLL_DOWN); - else - insertLine(R, DCEvars[0], SCROLL_DOWN); - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + "" + (c) + " (at R " + R + ")"); - - break; - - case 'T': /* 'ri' aka scroll backward */ - if (DCEvars[0] == 0) - insertLine(getTopMargin(), SCROLL_DOWN); - else - insertLine(getTopMargin(), DCEvars[0], SCROLL_DOWN); - - break; - - case 'M': - if (debug > 1) - debug("ESC [ " + DCEvars[0] + "" + (c) + " at R=" + R); - - if (DCEvars[0] == 0) - deleteLine(R); - else - for (int i = 0; i < DCEvars[0]; i++) - deleteLine(R); - - break; - - case 'K': - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " K"); - - /* clear in line */ - switch (DCEvars[0]) { - case 6: /* 97801 uses ESC[6K for delete to end of line */ - case 0:/*clear to right*/ - if (C < columns - 1) - deleteArea(C, R, columns - C, 1, attributes); - - break; - - case 1:/*clear to the left, including this */ - if (C > 0) - deleteArea(0, R, C + 1, 1, attributes); - - break; - - case 2:/*clear whole line */ - deleteArea(0, R, columns, 1, attributes); - break; - } - - break; - - case 'J': - - /* clear below current line */ - switch (DCEvars[0]) { - case 0: - if (R < rows - 1) - deleteArea(0, R + 1, columns, rows - R - 1, attributes); - - if (C < columns - 1) - deleteArea(C, R, columns - C, 1, attributes); - - break; - - case 1: - if (R > 0) - deleteArea(0, 0, columns, R, attributes); - - if (C > 0) - deleteArea(0, R, C + 1, 1, attributes); // include up to and including current - - break; - - case 2: - deleteArea(0, 0, columns, rows, attributes); - break; - } - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " J"); - - break; - - case '@': - if (DCEvars[0] == 0) DCEvars[0] = 1; - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " @"); - - for (int i = 0; i < DCEvars[0]; i++) - insertChar(C, R, ' ', attributes); - - break; - - case 'X': { - int toerase = DCEvars[0]; - - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " X, C=" + C + ",R=" + R); - - if (toerase == 0) - toerase = 1; - - if (toerase + C > columns) - toerase = columns - C; - - deleteArea(C, R, toerase, 1, attributes); - // does not change cursor position - break; - } - - case 'P': - if (debug > 1) - debug("ESC [ " + DCEvars[0] + " P, C=" + C + ",R=" + R); - - if (DCEvars[0] == 0) DCEvars[0] = 1; - - for (int i = 0; i < DCEvars[0]; i++) - deleteChar(C, R); - - break; - - case 'n': - switch (DCEvars[0]) { - case 5: /* malfunction? No malfunction. */ - writeSpecial((ESC) + "[0n"); - - if (debug > 1) - debug("ESC[5n"); - - break; - - case 6: - // DO NOT offset R and C by 1! (checked against /usr/X11R6/bin/resize - // FIXME check again. - // FIXME: but vttest thinks different??? - writeSpecial((ESC) + "[" + R + ";" + C + "R"); - - if (debug > 1) - debug("ESC[6n"); - - break; - - default: - if (debug > 0) - debug("ESC [ " + DCEvars[0] + " n??"); - - break; - } - - break; - - case 's': /* DECSC - save cursor */ - Sc = C; - Sr = R; - Sa = attributes; - - if (debug > 3) - debug("ESC[s"); - - break; - - case 'u': /* DECRC - restore cursor */ - C = Sc; - R = Sr; - attributes = Sa; - - if (debug > 3) - debug("ESC[u"); - - break; - - case 'm': /* attributes as color, bold , blink,*/ - if (debug > 3) - debug("ESC [ "); - - if (DCEvar == 0 && DCEvars[0] == 0) - attributes = 0; - - for (int i = 0; i <= DCEvar; i++) { - switch (DCEvars[i]) { - case 0: - if (DCEvar > 0) { - if (terminalID.equals("scoansi")) { - attributes &= COLOR; /* Keeps color. Strange but true. */ - } - else { - attributes = 0; - } - } - - break; - - case 1: - attributes |= BOLD; - attributes &= ~LOW; - break; - - case 2: - - /* SCO color hack mode */ - if (terminalID.equals("scoansi") && ((DCEvar - i) >= 2)) { - int ncolor; - attributes &= ~(COLOR | BOLD); - ncolor = DCEvars[i + 1]; - - if ((ncolor & 8) == 8) - attributes |= BOLD; - - ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2); - attributes |= ((ncolor) + 1) << COLOR_FG_SHIFT; - ncolor = DCEvars[i + 2]; - ncolor = ((ncolor & 1) << 2) | (ncolor & 2) | ((ncolor & 4) >> 2); - attributes |= ((ncolor) + 1) << COLOR_BG_SHIFT; - i += 2; - } - else { - attributes |= LOW; - } - - break; - - case 3: /* italics */ - attributes |= INVERT; - break; - - case 4: - attributes |= UNDERLINE; - break; - - case 7: - attributes |= INVERT; - break; - - case 8: - attributes |= INVISIBLE; - break; - - case 5: /* blink on */ - break; - - /* 10 - ANSI X3.64-1979, select primary font, don't display control - * chars, don't set bit 8 on output */ - case 10: - gl = 0; - usedcharsets = true; - break; - - /* 11 - ANSI X3.64-1979, select second alt. font, display control - * chars, set bit 8 on output */ - case 11: /* SMACS , as */ - case 12: - gl = 1; - usedcharsets = true; - break; - - case 21: /* normal intensity */ - attributes &= ~(LOW | BOLD); - break; - - case 23: /* italics off */ - attributes &= ~INVERT; - break; - - case 25: /* blinking off */ - break; - - case 27: - attributes &= ~INVERT; - break; - - case 28: - attributes &= ~INVISIBLE; - break; - - case 24: - attributes &= ~UNDERLINE; - break; - - case 22: - attributes &= ~BOLD; - break; - - case 30: - case 31: - case 32: - case 33: - case 34: - case 35: - case 36: - case 37: - attributes &= ~COLOR_FG; - attributes |= ((DCEvars[i] - 30) + 1) << COLOR_FG_SHIFT; - break; - - case 38: - if (DCEvars[i + 1] == 5) { - attributes &= ~COLOR_FG; - attributes |= ((DCEvars[i + 2]) + 1) << COLOR_FG_SHIFT; - i += 2; - } - - break; - - case 39: - attributes &= ~COLOR_FG; - break; - - case 40: - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - case 47: - attributes &= ~COLOR_BG; - attributes |= ((DCEvars[i] - 40) + 1) << COLOR_BG_SHIFT; - break; - - case 48: - if (DCEvars[i + 1] == 5) { - attributes &= ~COLOR_BG; - attributes |= (DCEvars[i + 2] + 1) << COLOR_BG_SHIFT; - i += 2; - } - - break; - - case 49: - attributes &= ~COLOR_BG; - break; - - case 90: - case 91: - case 92: - case 93: - case 94: - case 95: - case 96: - case 97: - attributes &= ~COLOR_FG; - attributes |= ((DCEvars[i] - 82) + 1) << COLOR_FG_SHIFT; - break; - - case 100: - case 101: - case 102: - case 103: - case 104: - case 105: - case 106: - case 107: - attributes &= ~COLOR_BG; - attributes |= ((DCEvars[i] - 92) + 1) << COLOR_BG_SHIFT; - break; - - default: - debugStr.append("ESC [ ") - .append(DCEvars[i]) - .append(" m unknown..."); - debug(debugStr.toString()); - debugStr.setLength(0); - break; - } - - if (debug > 3) { - debugStr.append(DCEvars[i]) - .append(';'); - debug(debugStr.toString()); - debugStr.setLength(0); - } - } - - if (debug > 3) { - debugStr.append(" (attributes = ") - .append(attributes) - .append(")m"); - debug(debugStr.toString()); - debugStr.setLength(0); - } - - break; - - default: - debugStr.append("ESC [ unknown letter: ") - .append(c) - .append(" (") - .append((int)c) - .append(')'); - debug(debugStr.toString()); - debugStr.setLength(0); - break; - } - - break; - - case TSTATE_TITLE: - switch (c) { - case ESC: - term_state = TSTATE_ESC; - break; - - default: - // TODO save title - break; - } - - break; - - default: - term_state = TSTATE_DATA; - break; - } - - setCursorPosition(C, R); - } - - /* hard reset the terminal */ - public void reset() { - gx[0] = 'B'; - gx[1] = 'B'; - gx[2] = 'B'; - gx[3] = 'B'; - gl = 0; // default GL to G0 - gr = 2; // default GR to G2 - onegl = -1; // Single shift override - /* reset tabs */ - int nw = width; - - if (nw < 132) nw = 132; - - Tabs = new byte[nw]; - - for (int i = 0; i < nw; i += 8) { - Tabs[i] = 1; - } - - deleteArea(0, 0, width, height, attributes); - setMargins(0, height); - C = R = 0; - _SetCursor(0, 0); - - if (display != null) - display.resetColors(); - - showCursor(true); - /*FIXME:*/ - term_state = TSTATE_DATA; - } -}
--- a/src/net/sourceforge/jsocks/Authentication.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -package net.sourceforge.jsocks; - -/** - The Authentication interface provides for performing method specific - authentication for SOCKS5 connections. -*/ -public interface Authentication{ - /** - This method is called when SOCKS5 server have selected a particular - authentication method, for whch an implementaion have been registered. - - <p> - This method should return an array {inputstream,outputstream - [,UDPEncapsulation]}. The reason for that is that SOCKS5 protocol - allows to have method specific encapsulation of data on the socket for - purposes of integrity or security. And this encapsulation should be - performed by those streams returned from the method. It is also possible - to encapsulate datagrams. If authentication method supports such - encapsulation an instance of the UDPEncapsulation interface should be - returned as third element of the array, otherwise either null should be - returned as third element, or array should contain only 2 elements. - - @param methodId Authentication method selected by the server. - @param proxySocket Socket used to conect to the proxy. - @return Two or three element array containing - Input/Output streams which should be used on this connection. - Third argument is optional and should contain an instance - of UDPEncapsulation. It should be provided if the authentication - method used requires any encapsulation to be done on the - datagrams. - */ - Object[] doSocksAuthentication(int methodId,java.net.Socket proxySocket) - throws java.io.IOException; -}
--- a/src/net/sourceforge/jsocks/AuthenticationNone.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package net.sourceforge.jsocks; - -/** - SOCKS5 none authentication. Dummy class does almost nothing. -*/ -public class AuthenticationNone implements Authentication{ - - public Object[] doSocksAuthentication(int methodId, - java.net.Socket proxySocket) - throws java.io.IOException{ - - if(methodId!=0) return null; - - return new Object[] { proxySocket.getInputStream(), - proxySocket.getOutputStream()}; - } -}
--- a/src/net/sourceforge/jsocks/CProxy.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,488 +0,0 @@ -package net.sourceforge.jsocks; -import java.net.*; -import java.io.*; -import java.util.Hashtable; -import java.util.Enumeration; - -/** - Abstract class CProxy, base for classes Socks4Proxy and Socks5Proxy. - Defines methods for specifying default proxy, to be - used by all classes of this package. -*/ - -public abstract class CProxy{ - -//Data members - protected InetRange directHosts = new InetRange(); - - protected InetAddress proxyIP = null; - protected String proxyHost = null; - protected int proxyPort; - protected Socket proxySocket = null; - - protected InputStream in; - protected OutputStream out; - - protected int version; - - protected CProxy chainProxy = null; - - -//Protected static/class variables - protected static CProxy defaultProxy = null; - -//Constructors -//==================== - CProxy(CProxy chainProxy, - String proxyHost,int proxyPort)throws UnknownHostException{ - this.chainProxy = chainProxy; - this.proxyHost = proxyHost; - - if(chainProxy == null) - this.proxyIP = InetAddress.getByName(proxyHost); - - this.proxyPort = proxyPort; - } - - - CProxy(String proxyHost,int proxyPort)throws UnknownHostException{ - this(null,proxyHost,proxyPort); - } - - CProxy(CProxy chainProxy,InetAddress proxyIP,int proxyPort){ - this.chainProxy = chainProxy; - this.proxyIP = proxyIP; - this.proxyPort = proxyPort; - } - - CProxy(InetAddress proxyIP,int proxyPort){ - this(null,proxyIP,proxyPort); - } - - CProxy(CProxy p){ - this.proxyIP = p.proxyIP; - this.proxyPort = p.proxyPort; - this.version = p.version; - this.directHosts = p.directHosts; - } - -//Public instance methods -//======================== - - /** - Get the port on which proxy server is running. - * @return CProxy port. - */ - public int getPort(){ - return proxyPort; - } - /** - Get the ip address of the proxy server host. - * @return CProxy InetAddress. - */ - public InetAddress getInetAddress(){ - return proxyIP; - } - /** - * Adds given ip to the list of direct addresses. - * This machine will be accessed without using proxy. - */ - public void addDirect(InetAddress ip){ - directHosts.add(ip); - } - /** - * Adds host to the list of direct addresses. - * This machine will be accessed without using proxy. - */ - public boolean addDirect(String host){ - return directHosts.add(host); - } - /** - * Adds given range of addresses to the lsit of direct addresses, - * machines within this range will be accessed without using proxy. - */ - public void addDirect(InetAddress from,InetAddress to){ - directHosts.add(from,to); - } - /** - * Sets given InetRange as the list of direct address, previous - * list will be discarded, any changes done previously with - * addDirect(Inetaddress) will be lost. - * The machines in this range will be accessed without using proxy. - * @param ir InetRange which should be used to look up direct addresses. - * @see InetRange - */ - public void setDirect(InetRange ir){ - directHosts = ir; - } - - /** - Get the list of direct hosts. - * @return Current range of direct address as InetRange object. - * @see InetRange - */ - public InetRange getDirect(){ - return directHosts; - } - /** - Check wether the given host is on the list of direct address. - @param host Host name to check. - * @return true if the given host is specified as the direct addresses. - */ - public boolean isDirect(String host){ - return directHosts.contains(host); - } - /** - Check wether the given host is on the list of direct addresses. - @param host Host address to check. - * @return true if the given host is specified as the direct address. - */ - public boolean isDirect(InetAddress host){ - return directHosts.contains(host); - } - /** - Set the proxy which should be used to connect to given proxy. - @param chainProxy CProxy to use to connect to this proxy. - */ - public void setChainProxy(CProxy chainProxy){ - this.chainProxy = chainProxy; - } - - /** - Get proxy which is used to connect to this proxy. - @return CProxy which is used to connect to this proxy, or null - if proxy is to be contacted directly. - */ - public CProxy getChainProxy(){ - return chainProxy; - } - - /** - Get string representation of this proxy. - * @returns string in the form:proxyHost:proxyPort \t Version versionNumber - */ - public String toString(){ - return (""+proxyIP.getHostName()+":"+proxyPort+"\tVersion "+version); - } - - -//Public Static(Class) Methods -//============================== - - /** - * Sets SOCKS4 proxy as default. - @param hostName Host name on which SOCKS4 server is running. - @param port Port on which SOCKS4 server is running. - @param user Username to use for communications with proxy. - */ - public static void setDefaultProxy(String hostName,int port,String user) - throws UnknownHostException{ - defaultProxy = new Socks4Proxy(hostName,port,user); - } - - /** - * Sets SOCKS4 proxy as default. - @param ipAddress Host address on which SOCKS4 server is running. - @param port Port on which SOCKS4 server is running. - @param user Username to use for communications with proxy. - */ - public static void setDefaultProxy(InetAddress ipAddress,int port, - String user){ - defaultProxy = new Socks4Proxy(ipAddress,port,user); - } - /** - * Sets SOCKS5 proxy as default. - * Default proxy only supports no-authentication. - @param hostName Host name on which SOCKS5 server is running. - @param port Port on which SOCKS5 server is running. - */ - public static void setDefaultProxy(String hostName,int port) - throws UnknownHostException{ - defaultProxy = new Socks5Proxy(hostName,port); - } - /** - * Sets SOCKS5 proxy as default. - * Default proxy only supports no-authentication. - @param ipAddress Host address on which SOCKS5 server is running. - @param port Port on which SOCKS5 server is running. - */ - public static void setDefaultProxy(InetAddress ipAddress,int port){ - defaultProxy = new Socks5Proxy(ipAddress,port); - } - /** - * Sets default proxy. - @param p CProxy to use as default proxy. - */ - public static void setDefaultProxy(CProxy p){ - defaultProxy = p; - } - - /** - Get current default proxy. - * @return Current default proxy, or null if none is set. - */ - public static CProxy getDefaultProxy(){ - return defaultProxy; - } - - /** - Parses strings in the form: host[:port:user:password], and creates - proxy from information obtained from parsing. - <p> - Defaults: port = 1080.<br> - If user specified but not password, creates Socks4Proxy, if user - not specified creates Socks5Proxy, if both user and password are - speciefied creates Socks5Proxy with user/password authentication. - @param proxy_entry String in the form host[:port:user:password] - @return CProxy created from the string, null if entry was somehow - invalid(host unknown for example, or empty string) - */ - public static CProxy parseProxy(String proxy_entry){ - - String proxy_host; - int proxy_port = 1080; - String proxy_user = null; - String proxy_password = null; - CProxy proxy; - - java.util.StringTokenizer st = new java.util.StringTokenizer( - proxy_entry,":"); - if(st.countTokens() < 1) return null; - - proxy_host = st.nextToken(); - if(st.hasMoreTokens()) - try{ - proxy_port = Integer.parseInt(st.nextToken().trim()); - }catch(NumberFormatException nfe){} - - if(st.hasMoreTokens()) - proxy_user = st.nextToken(); - - if(st.hasMoreTokens()) - proxy_password = st.nextToken(); - - try{ - if(proxy_user == null) - proxy = new Socks5Proxy(proxy_host,proxy_port); - else if(proxy_password == null) - proxy = new Socks4Proxy(proxy_host,proxy_port,proxy_user); - else{ - proxy = new Socks5Proxy(proxy_host,proxy_port); - UserPasswordAuthentication upa = new UserPasswordAuthentication( - proxy_user, proxy_password); - - ((Socks5Proxy)proxy).setAuthenticationMethod(upa.METHOD_ID,upa); - } - }catch(UnknownHostException uhe){ - return null; - } - - return proxy; - } - - -//Protected Methods -//================= - - protected void startSession()throws SocksException{ - try{ - if(chainProxy == null) - proxySocket = new Socket(proxyIP,proxyPort); - else if(proxyIP != null) - proxySocket = new SocksSocket(chainProxy,proxyIP,proxyPort); - else - proxySocket = new SocksSocket(chainProxy,proxyHost,proxyPort); - - in = proxySocket.getInputStream(); - out = proxySocket.getOutputStream(); - }catch(SocksException se){ - throw se; - }catch(IOException io_ex){ - throw new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex); - } - } - - protected abstract CProxy copy(); - protected abstract ProxyMessage formMessage(int cmd,InetAddress ip,int port); - protected abstract ProxyMessage formMessage(int cmd,String host,int port) - throws UnknownHostException; - protected abstract ProxyMessage formMessage(InputStream in) - throws SocksException, - IOException; - - - protected ProxyMessage connect(InetAddress ip,int port) - throws SocksException{ - try{ - startSession(); - ProxyMessage request = formMessage(SOCKS_CMD_CONNECT, - ip,port); - return exchange(request); - }catch(SocksException se){ - endSession(); - throw se; - } - } - protected ProxyMessage connect(String host,int port) - throws UnknownHostException,SocksException{ - try{ - startSession(); - ProxyMessage request = formMessage(SOCKS_CMD_CONNECT, - host,port); - return exchange(request); - }catch(SocksException se){ - endSession(); - throw se; - } - } - - protected ProxyMessage bind(InetAddress ip,int port) - throws SocksException{ - try{ - startSession(); - ProxyMessage request = formMessage(SOCKS_CMD_BIND, - ip,port); - return exchange(request); - }catch(SocksException se){ - endSession(); - throw se; - } - } - protected ProxyMessage bind(String host,int port) - throws UnknownHostException,SocksException{ - try{ - startSession(); - ProxyMessage request = formMessage(SOCKS_CMD_BIND, - host,port); - return exchange(request); - }catch(SocksException se){ - endSession(); - throw se; - } - } - - protected ProxyMessage accept() - throws IOException,SocksException{ - ProxyMessage msg; - try{ - msg = formMessage(in); - }catch(InterruptedIOException iioe){ - throw iioe; - }catch(IOException io_ex){ - endSession(); - throw new SocksException(SOCKS_PROXY_IO_ERROR,"While Trying accept:" - +io_ex); - } - return msg; - } - - protected ProxyMessage udpAssociate(InetAddress ip,int port) - throws SocksException{ - try{ - startSession(); - ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE, - ip,port); - if(request != null) - return exchange(request); - }catch(SocksException se){ - endSession(); - throw se; - } - //Only get here if request was null - endSession(); - throw new SocksException(SOCKS_METHOD_NOTSUPPORTED, - "This version of proxy does not support UDP associate, use version 5"); - } - protected ProxyMessage udpAssociate(String host,int port) - throws UnknownHostException,SocksException{ - try{ - startSession(); - ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE, - host,port); - if(request != null) return exchange(request); - }catch(SocksException se){ - endSession(); - throw se; - } - //Only get here if request was null - endSession(); - throw new SocksException(SOCKS_METHOD_NOTSUPPORTED, - "This version of proxy does not support UDP associate, use version 5"); - } - - - protected void endSession(){ - try{ - if(proxySocket!=null) proxySocket.close(); - proxySocket = null; - }catch(IOException io_ex){ - } - } - - /** - *Sends the request to SOCKS server - */ - protected void sendMsg(ProxyMessage msg)throws SocksException, - IOException{ - msg.write(out); - } - - /** - * Reads the reply from the SOCKS server - */ - protected ProxyMessage readMsg()throws SocksException, - IOException{ - return formMessage(in); - } - /** - *Sends the request reads reply and returns it - *throws exception if something wrong with IO - *or the reply code is not zero - */ - protected ProxyMessage exchange(ProxyMessage request) - throws SocksException{ - ProxyMessage reply; - try{ - request.write(out); - reply = formMessage(in); - }catch(SocksException s_ex){ - throw s_ex; - }catch(IOException ioe){ - throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+ioe)); - } - return reply; - } - - -//Private methods -//=============== - - -//Constants - - public static final int SOCKS_SUCCESS =0; - public static final int SOCKS_FAILURE =1; - public static final int SOCKS_BADCONNECT =2; - public static final int SOCKS_BADNETWORK =3; - public static final int SOCKS_HOST_UNREACHABLE =4; - public static final int SOCKS_CONNECTION_REFUSED =5; - public static final int SOCKS_TTL_EXPIRE =6; - public static final int SOCKS_CMD_NOT_SUPPORTED =7; - public static final int SOCKS_ADDR_NOT_SUPPORTED =8; - - public static final int SOCKS_NO_PROXY =1<<16; - public static final int SOCKS_PROXY_NO_CONNECT =2<<16; - public static final int SOCKS_PROXY_IO_ERROR =3<<16; - public static final int SOCKS_AUTH_NOT_SUPPORTED =4<<16; - public static final int SOCKS_AUTH_FAILURE =5<<16; - public static final int SOCKS_JUST_ERROR =6<<16; - - public static final int SOCKS_DIRECT_FAILED =7<<16; - public static final int SOCKS_METHOD_NOTSUPPORTED =8<<16; - - - public static final int SOCKS_CMD_CONNECT =0x1; - static final int SOCKS_CMD_BIND =0x2; - static final int SOCKS_CMD_UDP_ASSOCIATE =0x3; - -}
--- a/src/net/sourceforge/jsocks/InetRange.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,440 +0,0 @@ -package net.sourceforge.jsocks; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.*; - -/** - * Class InetRange provides the means of defining the range of inetaddresses. - * It's used by Proxy class to store and look up addresses of machines, that - * should be contacted directly rather then through the proxy. - * <P> - * InetRange provides several methods to add either standalone addresses, or - * ranges (e.g. 100.200.300.0:100.200.300.255, which covers all addresses - * on on someones local network). It also provides methods for checking wether - * given address is in this range. Any number of ranges and standalone - * addresses can be added to the range. - */ -public class InetRange implements Cloneable{ - - Hashtable host_names; - Vector all; - Vector end_names; - - boolean useSeparateThread = true; - - /** - * Creates the empty range. - */ - public InetRange(){ - all = new Vector(); - host_names = new Hashtable(); - end_names = new Vector(); - } - - /** - * Adds another host or range to this range. - The String can be one of those: - <UL> - <li> Host name. eg.(Athena.myhost.com or 45.54.56.65) - - <li> Range in the form .myhost.net.au <BR> - In which case anything that ends with .myhost.net.au will - be considered in the range. - - <li> Range in the form ddd.ddd.ddd. <BR> - This will be treated as range ddd.ddd.ddd.0 to ddd.ddd.ddd.255. - It is not necessary to specify 3 first bytes you can use just - one or two. For example 130. will cover address between 130.0.0.0 - and 13.255.255.255. - - <li> Range in the form host_from[: \t\n\r\f]host_to. <br> - That is two hostnames or ips separated by either whitespace - or colon. - </UL> - */ - public synchronized boolean add(String s){ - if(s == null) return false; - - s = s.trim(); - if(s.length() == 0) return false; - - Object[] entry; - - if(s.charAt(s.length()-1) == '.'){ - //thing like: 111.222.33. - //it is being treated as range 111.222.33.000 - 111.222.33.255 - - int[] addr = ip2intarray(s); - long from,to; - from = to = 0; - - if(addr == null) return false; - for(int i = 0; i< 4;++i){ - if(addr[i]>=0) - from += (((long)addr[i]) << 8*(3-i)); - else{ - to = from; - while(i<4) - to += 255l << 8*(3-i++); - break; - } - } - entry = new Object[] {s,null,new Long(from),new Long(to)}; - all.addElement(entry); - - }else if(s.charAt(0) == '.'){ - //Thing like: .myhost.com - - end_names.addElement(s); - all.addElement(new Object[]{s,null,null,null}); - }else{ - StringTokenizer tokens = new StringTokenizer(s," \t\r\n\f:"); - if(tokens.countTokens() > 1){ - entry = new Object[] {s,null,null,null}; - resolve(entry,tokens.nextToken(),tokens.nextToken()); - all.addElement(entry); - }else{ - entry = new Object[] {s,null,null,null}; - all.addElement(entry); - host_names.put(s,entry); - resolve(entry); - } - - } - - return true; - } - - /** - * Adds another ip for this range. - @param ip IP os the host which should be added to this range. - */ - public synchronized void add(InetAddress ip){ - long from, to; - from = to = ip2long(ip); - all.addElement(new Object[]{ip.getHostName(),ip,new Long(from), - new Long(to)}); - } - - /** - * Adds another range of ips for this range.Any host with ip address - greater than or equal to the address of from and smaller than or equal - to the address of to will be included in the range. - @param from IP from where range starts(including). - @param to IP where range ends(including). - */ - public synchronized void add(InetAddress from,InetAddress to){ - all.addElement(new Object[]{from.getHostAddress()+":"+to.getHostAddress() - ,null,new Long(ip2long(from)), - new Long(ip2long(to))}); - } - - /** - * Checks wether the givan host is in the range. Attempts to resolve - host name if required. - @param host Host name to check. - @return true If host is in the range, false otherwise. - * @see InetRange#contains(String,boolean) - */ - public synchronized boolean contains(String host){ - return contains(host,true); - } - - /** - * Checks wether the given host is in the range. - * <P> - * Algorithm: <BR> - * <ol> - * <li>Look up if the hostname is in the range (in the Hashtable). - * <li>Check if it ends with one of the speciefied endings. - * <li>Check if it is ip(eg.130.220.35.98). If it is check if it is - * in the range. - * <li>If attemptResolve is true, host is name, rather than ip, and - * all previous attempts failed, try to resolve the hostname, and - * check wether the ip associated with the host is in the range.It - * also repeats all previos steps with the hostname obtained from - * InetAddress, but the name is not allways the full name,it is - * quite likely to be the same. Well it was on my machine. - * </ol> - @param host Host name to check. - @param attemptResolve Wether to lookup ip address which corresponds - to the host,if required. - @return true If host is in the range, false otherwise. - */ - public synchronized boolean contains(String host,boolean attemptResolve){ - if(all.size() ==0) return false; //Empty range - - host = host.trim(); - if(host.length() == 0) return false; - - if(checkHost(host)) return true; - if(checkHostEnding(host)) return true; - - long l = host2long(host); - if(l >=0) return contains(l); - - if(!attemptResolve) return false; - - try{ - InetAddress ip = InetAddress.getByName(host); - return contains(ip); - }catch(UnknownHostException uhe){ - - } - - return false; - } - - /** - * Checks wether the given ip is in the range. - @param ip Address of the host to check. - @return true If host is in the range, false otherwise. - */ - public synchronized boolean contains(InetAddress ip){ - if(checkHostEnding(ip.getHostName())) return true; - if(checkHost(ip.getHostName())) return true; - return contains(ip2long(ip)); - } - /** - Get all entries in the range as strings. <BR> - These strings can be used to delete entries from the range - with remove function. - @return Array of entries as strings. - @see InetRange#remove(String) - */ - public synchronized String[] getAll(){ - int size = all.size(); - Object entry[]; - String all_names[] = new String[size]; - - for(int i=0;i<size;++i){ - entry = (Object[]) all.elementAt(i); - all_names[i] = (String) entry[0]; - } - return all_names; - } - /** - Removes an entry from this range.<BR> - @param s Entry to remove. - @return true if successfull. - */ - public synchronized boolean remove(String s){ - Enumeration eEnum = all.elements(); - while(eEnum.hasMoreElements()){ - Object[] entry = (Object[]) eEnum.nextElement(); - if(s.equals(entry[0])){ - all.removeElement(entry); - end_names.removeElement(s); - host_names.remove(s); - return true; - } - } - return false; - } - - /** Get string representaion of this Range.*/ - public String toString(){ - String all[] = getAll(); - if(all.length == 0) return ""; - - String s = all[0]; - for(int i=1;i<all.length;++i) - s += "; "+all[i]; - return s; - } - - /** Creates a clone of this Object*/ - public Object clone(){ - InetRange new_range = new InetRange(); - new_range.all = (Vector)all.clone(); - new_range.end_names = (Vector) end_names.clone(); - new_range.host_names = (Hashtable)host_names.clone(); - return new_range; - } - - -//Private methods -///////////////// - /** - * Same as previous but used internally, to avoid - * unnecessary convertion of IPs, when checking subranges - */ - private synchronized boolean contains(long ip){ - Enumeration eEnum = all.elements(); - while(eEnum.hasMoreElements()){ - Object[] obj = (Object[]) eEnum.nextElement(); - Long from = obj[2]==null?null:(Long)obj[2]; - Long to = obj[3]==null?null:(Long)obj[3]; - if(from != null && from.longValue()<= ip - && to.longValue() >= ip) return true; - - } - return false; - } - - private boolean checkHost(String host){ - return host_names.containsKey(host); - } - private boolean checkHostEnding(String host){ - Enumeration eEnum = end_names.elements(); - while(eEnum.hasMoreElements()){ - if(host.endsWith((String) eEnum.nextElement())) return true; - } - return false; - } - private void resolve(Object[] entry){ - //First check if it's in the form ddd.ddd.ddd.ddd. - long ip = host2long((String) entry[0]); - if(ip >= 0){ - entry[2] = entry[3] = new Long(ip); - }else{ - InetRangeResolver res = new InetRangeResolver(entry); - res.resolve(useSeparateThread); - } - } - private void resolve(Object[] entry,String from,String to){ - long f,t; - if((f=host2long(from))>= 0 && (t=host2long(to)) >= 0){ - entry[2] = new Long(f); - entry[3] = new Long(t); - }else{ - InetRangeResolver res = new InetRangeResolver(entry,from,to); - res.resolve(useSeparateThread); - } - } - - - -//Class methods -/////////////// - - //Converts ipv4 to long value(unsigned int) - /////////////////////////////////////////// - static long ip2long(InetAddress ip){ - long l=0; - byte[] addr = ip.getAddress(); - - if(addr.length ==4){ //IPV4 - for(int i=0;i<4;++i) - l += (((long)addr[i] &0xFF) << 8*(3-i)); - }else{ //IPV6 - return 0; //Have no idea how to deal with those - } - return l; - } - - - long host2long(String host){ - long ip=0; - - //check if it's ddd.ddd.ddd.ddd - if(!Character.isDigit(host.charAt(0))) return -1; - - int[] addr = ip2intarray(host); - if(addr == null) return -1; - - for(int i=0;i<addr.length;++i) - ip += ((long)(addr[i]>=0 ? addr[i] : 0)) << 8*(3-i); - - return ip; - } - - static int[] ip2intarray(String host){ - int[] address = {-1,-1,-1,-1}; - int i=0; - StringTokenizer tokens = new StringTokenizer(host,"."); - if(tokens.countTokens() > 4) return null; - while(tokens.hasMoreTokens()){ - try{ - address[i++] = Integer.parseInt(tokens.nextToken()) & 0xFF; - }catch(NumberFormatException nfe){ - return null; - } - - } - return address; - } - - -/* -//* This was the test main function -//********************************** - - public static void main(String args[])throws UnknownHostException{ - int i; - - InetRange ir = new InetRange(); - - - for(i=0;i<args.length;++i){ - System.out.println("Adding:" + args[i]); - ir.add(args[i]); - } - - String host; - java.io.DataInputStream din = new java.io.DataInputStream(System.in); - try{ - host = din.readLine(); - while(host!=null){ - if(ir.contains(host)){ - System.out.println("Range contains ip:"+host); - }else{ - System.out.println(host+" is not in the range"); - } - host = din.readLine(); - } - }catch(java.io.IOException io_ex){ - io_ex.printStackTrace(); - } - } -********************/ - -} - - -class InetRangeResolver implements Runnable{ - - Object[] entry; - - String from, to; - - InetRangeResolver(Object[] entry){ - this.entry = entry; - from = to = null; - } - InetRangeResolver(Object[] entry,String from,String to){ - this.entry = entry; - this.from = from; - this.to = to; - } - public final void resolve(){ - resolve(true); - } - public final void resolve(boolean inSeparateThread){ - if(inSeparateThread){ - Thread t = new Thread(this); - t.start(); - }else - run(); - - } - public void run(){ - try{ - if(from == null){ - InetAddress ip = InetAddress.getByName((String) entry[0]); - entry[1] = ip; - Long l = new Long(InetRange.ip2long(ip)); - entry[2] = entry[3] = l; - }else{ - InetAddress f = InetAddress.getByName(from); - InetAddress t = InetAddress.getByName(to); - entry[2] = new Long(InetRange.ip2long(f)); - entry[3] = new Long(InetRange.ip2long(t)); - - } - }catch(UnknownHostException uhe){ - //System.err.println("Resolve failed for "+from+','+to+','+entry[0]); - } - } - -}
--- a/src/net/sourceforge/jsocks/ProxyMessage.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -package net.sourceforge.jsocks; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.DataInputStream; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - Abstract class which describes SOCKS4/5 response/request. -*/ -public abstract class ProxyMessage{ - /** Host as an IP address */ - public InetAddress ip=null; - /** SOCKS version, or version of the response for SOCKS4*/ - public int version; - /** Port field of the request/response*/ - public int port; - /** Request/response code as an int*/ - public int command; - /** Host as string.*/ - public String host=null; - /** User field for SOCKS4 request messages*/ - public String user=null; - - ProxyMessage(int command,InetAddress ip,int port){ - this.command = command; - this.ip = ip; - this.port = port; - } - - ProxyMessage(){ - } - - - /** - Initialises Message from the stream. Reads server response from - given stream. - @param in Input stream to read response from. - @throws SocksException If server response code is not SOCKS_SUCCESS(0), or - if any error with protocol occurs. - @throws IOException If any error happens with I/O. - */ - public abstract void read(InputStream in) - throws SocksException, - IOException; - - - /** - Initialises Message from the stream. Reads server response or client - request from given stream. - - @param in Input stream to read response from. - @param clinetMode If true read server response, else read client request. - @throws SocksException If server response code is not SOCKS_SUCCESS(0) and - reading in client mode, or if any error with protocol occurs. - @throws IOException If any error happens with I/O. - */ - public abstract void read(InputStream in,boolean client_mode) - throws SocksException, - IOException; - - - /** - Writes the message to the stream. - @param out Output stream to which message should be written. - */ - public abstract void write(OutputStream out)throws SocksException, - IOException; - - /** - Get the Address field of this message as InetAddress object. - @return Host address or null, if one can't be determined. - */ - public InetAddress getInetAddress() throws UnknownHostException{ - return ip; - } - - - /** - Get string representaion of this message. - @return string representation of this message. - */ - public String toString(){ - return - "Proxy Message:\n"+ - "Version:"+ version+"\n"+ - "Command:"+ command+"\n"+ - "IP: "+ ip+"\n"+ - "Port: "+ port+"\n"+ - "User: "+ user+"\n" ; - } - -//Package methods -////////////////// - - static final String bytes2IPV4(byte[] addr,int offset){ - String hostName = ""+(addr[offset] & 0xFF); - for(int i = offset+1;i<offset+4;++i) - hostName+="."+(addr[i] & 0xFF); - return hostName; - } - - static final String bytes2IPV6(byte[] addr,int offset){ - //Have no idea how they look like! - return null; - } - -}
--- a/src/net/sourceforge/jsocks/ProxyServer.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,604 +0,0 @@ -package net.sourceforge.jsocks; -import net.sourceforge.jsocks.server.ServerAuthenticator; -import java.net.*; -import java.io.*; - -/** - SOCKS4 and SOCKS5 proxy, handles both protocols simultaniously. - Implements all SOCKS commands, including UDP relaying. - <p> - In order to use it you will need to implement ServerAuthenticator - interface. There is an implementation of this interface which does - no authentication ServerAuthenticatorNone, but it is very dangerous - to use, as it will give access to your local network to anybody - in the world. One should never use this authentication scheme unless - one have pretty good reason to do so. - There is a couple of other authentication schemes in socks.server package. - @see socks.server.ServerAuthenticator -*/ -public class ProxyServer implements Runnable{ - - ServerAuthenticator auth; - ProxyMessage msg = null; - - Socket sock=null,remote_sock=null; - ServerSocket ss=null; - UDPRelayServer relayServer = null; - InputStream in,remote_in; - OutputStream out,remote_out; - - int mode; - static final int START_MODE = 0; - static final int ACCEPT_MODE = 1; - static final int PIPE_MODE = 2; - static final int ABORT_MODE = 3; - - static final int BUF_SIZE = 8192; - - Thread pipe_thread1,pipe_thread2; - long lastReadTime; - - static int iddleTimeout = 180000; //3 minutes - static int acceptTimeout = 180000; //3 minutes - - static PrintStream log = null; - static CProxy proxy; - - -//Public Constructors -///////////////////// - - - /** - Creates a proxy server with given Authentication scheme. - @param auth Authentication scheme to be used. - */ - public ProxyServer(ServerAuthenticator auth){ - this.auth = auth; - } - -//Other constructors -//////////////////// - - ProxyServer(ServerAuthenticator auth,Socket s){ - this.auth = auth; - this.sock = s; - mode = START_MODE; - } - -//Public methods -///////////////// - - /** - Set the logging stream. Specifying null disables logging. - */ - public static void setLog(OutputStream out){ - if(out == null){ - log = null; - }else{ - log = new PrintStream(out,true); - } - - UDPRelayServer.log = log; - } - - /** - Set proxy. - <p> - Allows CProxy chaining so that one CProxy server is connected to another - and so on. If proxy supports SOCKSv4, then only some SOCKSv5 requests - can be handled, UDP would not work, however CONNECT and BIND will be - translated. - - @param p CProxy which should be used to handle user requests. - */ - public static void setProxy(CProxy p){ - proxy =p; - UDPRelayServer.proxy = proxy; - } - - /** - Get proxy. - @return CProxy wich is used to handle user requests. - */ - public static CProxy getProxy(){ - return proxy; - } - - /** - Sets the timeout for connections, how long shoud server wait - for data to arrive before dropping the connection.<br> - Zero timeout implies infinity.<br> - Default timeout is 3 minutes. - */ - public static void setIddleTimeout(int timeout){ - iddleTimeout = timeout; - } - /** - Sets the timeout for BIND command, how long the server should - wait for the incoming connection.<br> - Zero timeout implies infinity.<br> - Default timeout is 3 minutes. - */ - public static void setAcceptTimeout(int timeout){ - acceptTimeout = timeout; - } - - /** - Sets the timeout for UDPRelay server.<br> - Zero timeout implies infinity.<br> - Default timeout is 3 minutes. - */ - public static void setUDPTimeout(int timeout){ - UDPRelayServer.setTimeout(timeout); - } - - /** - Sets the size of the datagrams used in the UDPRelayServer.<br> - Default size is 64K, a bit more than maximum possible size of the - datagram. - */ - public static void setDatagramSize(int size){ - UDPRelayServer.setDatagramSize(size); - } - - - /** - Start the CProxy server at given port.<br> - This methods blocks. - */ - public void start(int port){ - start(port,5,null); - } - - /** - Create a server with the specified port, listen backlog, and local - IP address to bind to. The localIP argument can be used on a multi-homed - host for a ServerSocket that will only accept connect requests to one of - its addresses. If localIP is null, it will default accepting connections - on any/all local addresses. The port must be between 0 and 65535, - inclusive. <br> - This methods blocks. - */ - public void start(int port,int backlog,InetAddress localIP){ - try{ - ss = new ServerSocket(port,backlog,localIP); - log("Starting SOCKS Proxy on:"+ss.getInetAddress().getHostAddress()+":" - +ss.getLocalPort()); - while(true){ - Socket s = ss.accept(); - log("Accepted from:"+s.getInetAddress().getHostName()+":" - +s.getPort()); - ProxyServer ps = new ProxyServer(auth,s); - (new Thread(ps)).start(); - } - }catch(IOException ioe){ - ioe.printStackTrace(); - }finally{ - } - } - - /** - Stop server operation.It would be wise to interrupt thread running the - server afterwards. - */ - public void stop(){ - try{ - if(ss != null) ss.close(); - }catch(IOException ioe){ - } - } - -//Runnable interface -//////////////////// - public void run(){ - switch(mode){ - case START_MODE: - try{ - startSession(); - }catch(IOException ioe){ - handleException(ioe); - //ioe.printStackTrace(); - }finally{ - abort(); - if(auth!=null) auth.endSession(); - log("Main thread(client->remote)stopped."); - } - break; - case ACCEPT_MODE: - try{ - doAccept(); - mode = PIPE_MODE; - pipe_thread1.interrupt(); //Tell other thread that connection have - //been accepted. - pipe(remote_in,out); - }catch(IOException ioe){ - //log("Accept exception:"+ioe); - handleException(ioe); - }finally{ - abort(); - log("Accept thread(remote->client) stopped"); - } - break; - case PIPE_MODE: - try{ - pipe(remote_in,out); - }catch(IOException ioe){ - }finally{ - abort(); - log("Support thread(remote->client) stopped"); - } - break; - case ABORT_MODE: - break; - default: - log("Unexpected MODE "+mode); - } - } - -//Private methods -///////////////// - private void startSession() throws IOException{ - sock.setSoTimeout(iddleTimeout); - - try{ - auth = auth.startSession(sock); - }catch(IOException ioe){ - log("Auth throwed exception:"+ioe); - auth = null; - return; - } - - if(auth == null){ //Authentication failed - log("Authentication failed"); - return; - } - - in = auth.getInputStream(); - out = auth.getOutputStream(); - - msg = readMsg(in); - handleRequest(msg); - } - - private void handleRequest(ProxyMessage msg) - throws IOException{ - if(!auth.checkRequest(msg)) throw new - SocksException(CProxy.SOCKS_FAILURE); - - if(msg.ip == null){ - if(msg instanceof Socks5Message){ - msg.ip = InetAddress.getByName(msg.host); - }else - throw new SocksException(CProxy.SOCKS_FAILURE); - } - log(msg); - - switch(msg.command){ - case CProxy.SOCKS_CMD_CONNECT: - onConnect(msg); - break; - case CProxy.SOCKS_CMD_BIND: - onBind(msg); - break; - case CProxy.SOCKS_CMD_UDP_ASSOCIATE: - onUDP(msg); - break; - default: - throw new SocksException(CProxy.SOCKS_CMD_NOT_SUPPORTED); - } - } - - private void handleException(IOException ioe){ - //If we couldn't read the request, return; - if(msg == null) return; - //If have been aborted by other thread - if(mode == ABORT_MODE) return; - //If the request was successfully completed, but exception happened later - if(mode == PIPE_MODE) return; - - int error_code = CProxy.SOCKS_FAILURE; - - if(ioe instanceof SocksException) - error_code = ((SocksException)ioe).errCode; - else if(ioe instanceof NoRouteToHostException) - error_code = CProxy.SOCKS_HOST_UNREACHABLE; - else if(ioe instanceof ConnectException) - error_code = CProxy.SOCKS_CONNECTION_REFUSED; - else if(ioe instanceof InterruptedIOException) - error_code = CProxy.SOCKS_TTL_EXPIRE; - - if(error_code > CProxy.SOCKS_ADDR_NOT_SUPPORTED || error_code < 0){ - error_code = CProxy.SOCKS_FAILURE; - } - - sendErrorMessage(error_code); - } - - private void onConnect(ProxyMessage msg) throws IOException { - Socket s = null; - ProxyMessage response = null; - int iSock5Cmd = CProxy.SOCKS_FAILURE; //defaulting to failure - int iSock4Msg = Socks4Message.REPLY_NO_CONNECT; - InetAddress sIp = null; int iPort = 0; - - try { - if (proxy == null) { - s = new Socket(msg.ip, msg.port); - } else { - s = new SocksSocket(proxy, msg.ip, msg.port); - } - log("Connected to " + s.getInetAddress() + ":" + s.getPort()); - - iSock5Cmd = CProxy.SOCKS_SUCCESS; iSock4Msg = Socks4Message.REPLY_OK; - sIp = s.getInetAddress(); iPort = s.getPort(); - - } - catch (Exception sE) { - log("Failed connecting to remote socket. Exception: " + sE.getLocalizedMessage()); - - //TBD Pick proper socks error for corresponding socket error, below is too generic - iSock5Cmd = CProxy.SOCKS_CONNECTION_REFUSED; iSock4Msg = Socks4Message.REPLY_NO_CONNECT; - } - - if (msg instanceof Socks5Message) { - response = new Socks5Message(iSock5Cmd, sIp, iPort); - } else { - response = new Socks4Message(iSock4Msg, sIp, iPort); - } - - response.write(out); - - if (s != null) { - startPipe(s); - } - else { - throw (new RuntimeException("onConnect() Failed to create Socket()")); - } - - return; - } - - - private void onBind(ProxyMessage msg) throws IOException{ - ProxyMessage response = null; - - if(proxy == null) - ss = new ServerSocket(0); - else - ss = new SocksServerSocket(proxy, msg.ip, msg.port); - - ss.setSoTimeout(acceptTimeout); - - log("Trying accept on "+ss.getInetAddress()+":"+ss.getLocalPort()); - - if(msg.version == 5) - response = new Socks5Message(CProxy.SOCKS_SUCCESS,ss.getInetAddress(), - ss.getLocalPort()); - else - response = new Socks4Message(Socks4Message.REPLY_OK, - ss.getInetAddress(), - ss.getLocalPort()); - response.write(out); - - mode = ACCEPT_MODE; - - pipe_thread1 = Thread.currentThread(); - pipe_thread2 = new Thread(this); - pipe_thread2.start(); - - //Make timeout infinit. - sock.setSoTimeout(0); - int eof=0; - - try{ - while((eof=in.read())>=0){ - if(mode != ACCEPT_MODE){ - if(mode != PIPE_MODE) return;//Accept failed - - remote_out.write(eof); - break; - } - } - }catch(EOFException eofe){ - //System.out.println("EOF exception"); - return;//Connection closed while we were trying to accept. - }catch(InterruptedIOException iioe){ - //Accept thread interrupted us. - //System.out.println("Interrupted"); - if(mode != PIPE_MODE) - return;//If accept thread was not successfull return. - }finally{ - //System.out.println("Finnaly!"); - } - - if(eof < 0)//Connection closed while we were trying to accept; - return; - - //Do not restore timeout, instead timeout is set on the - //remote socket. It does not make any difference. - - pipe(in,remote_out); - } - - private void onUDP(ProxyMessage msg) throws IOException{ - if(msg.ip.getHostAddress().equals("0.0.0.0")) - msg.ip = sock.getInetAddress(); - log("Creating UDP relay server for "+msg.ip+":"+msg.port); - relayServer = new UDPRelayServer(msg.ip,msg.port, - Thread.currentThread(),sock,auth); - - ProxyMessage response; - - response = new Socks5Message(CProxy.SOCKS_SUCCESS, - relayServer.relayIP,relayServer.relayPort); - - response.write(out); - - relayServer.start(); - - //Make timeout infinit. - sock.setSoTimeout(0); - try{ - while(in.read()>=0) /*do nothing*/; - }catch(EOFException eofe){ - } - } - -//Private methods -////////////////// - - private void doAccept() throws IOException{ - Socket s; - long startTime = System.currentTimeMillis(); - - while(true){ - s = ss.accept(); - if(s.getInetAddress().equals(msg.ip)){ - //got the connection from the right host - //Close listenning socket. - ss.close(); - break; - }else if(ss instanceof SocksServerSocket){ - //We can't accept more then one connection - s.close(); - ss.close(); - throw new SocksException(CProxy.SOCKS_FAILURE); - }else{ - if(acceptTimeout!=0){ //If timeout is not infinit - int newTimeout = acceptTimeout-(int)(System.currentTimeMillis()- - startTime); - if(newTimeout <= 0) throw new InterruptedIOException( - "In doAccept()"); - ss.setSoTimeout(newTimeout); - } - s.close(); //Drop all connections from other hosts - } - } - - //Accepted connection - remote_sock = s; - remote_in = s.getInputStream(); - remote_out = s.getOutputStream(); - - //Set timeout - remote_sock.setSoTimeout(iddleTimeout); - - log("Accepted from "+s.getInetAddress()+":"+s.getPort()); - - ProxyMessage response; - - if(msg.version == 5) - response = new Socks5Message(CProxy.SOCKS_SUCCESS, s.getInetAddress(), - s.getPort()); - else - response = new Socks4Message(Socks4Message.REPLY_OK, - s.getInetAddress(), s.getPort()); - response.write(out); - } - - private ProxyMessage readMsg(InputStream in) throws IOException{ - PushbackInputStream push_in; - if(in instanceof PushbackInputStream) - push_in = (PushbackInputStream) in; - else - push_in = new PushbackInputStream(in); - - int version = push_in.read(); - push_in.unread(version); - - - ProxyMessage msg; - - if(version == 5){ - msg = new Socks5Message(push_in,false); - }else if(version == 4){ - msg = new Socks4Message(push_in,false); - }else{ - throw new SocksException(CProxy.SOCKS_FAILURE); - } - return msg; - } - - private void startPipe(Socket s){ - mode = PIPE_MODE; - remote_sock = s; - try{ - remote_in = s.getInputStream(); - remote_out = s.getOutputStream(); - pipe_thread1 = Thread.currentThread(); - pipe_thread2 = new Thread(this); - pipe_thread2.start(); - pipe(in,remote_out); - }catch(IOException ioe){ - } - } - - private void sendErrorMessage(int error_code){ - ProxyMessage err_msg; - if(msg instanceof Socks4Message) - err_msg = new Socks4Message(Socks4Message.REPLY_REJECTED); - else - err_msg = new Socks5Message(error_code); - try{ - err_msg.write(out); - }catch(IOException ioe){} - } - - private synchronized void abort(){ - if(mode == ABORT_MODE) return; - mode = ABORT_MODE; - try{ - log("Aborting operation"); - if(remote_sock != null) remote_sock.close(); - if(sock != null) sock.close(); - if(relayServer!=null) relayServer.stop(); - if(ss!=null) ss.close(); - if(pipe_thread1 != null) pipe_thread1.interrupt(); - if(pipe_thread2 != null) pipe_thread2.interrupt(); - }catch(IOException ioe){} - } - - static final void log(String s){ - if(log != null){ - log.println(s); - log.flush(); - } - } - - static final void log(ProxyMessage msg){ - log("Request version:"+msg.version+ - "\tCommand: "+command2String(msg.command)); - log("IP:"+msg.ip +"\tPort:"+msg.port+ - (msg.version==4?"\tUser:"+msg.user:"")); - } - - private void pipe(InputStream in,OutputStream out) throws IOException{ - lastReadTime = System.currentTimeMillis(); - byte[] buf = new byte[BUF_SIZE]; - int len = 0; - while(len >= 0){ - try{ - if(len!=0){ - out.write(buf,0,len); - out.flush(); - } - len= in.read(buf); - lastReadTime = System.currentTimeMillis(); - }catch(InterruptedIOException iioe){ - if(iddleTimeout == 0) return;//Other thread interrupted us. - long timeSinceRead = System.currentTimeMillis() - lastReadTime; - if(timeSinceRead >= iddleTimeout - 1000) //-1s for adjustment. - return; - len = 0; - - } - } - } - static final String command_names[] = {"CONNECT","BIND","UDP_ASSOCIATE"}; - - static final String command2String(int cmd){ - if(cmd > 0 && cmd < 4) return command_names[cmd-1]; - else return "Unknown Command "+cmd; - } -}
--- a/src/net/sourceforge/jsocks/Socks4Message.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -package net.sourceforge.jsocks; -import java.io.*; -import java.net.*; - -/** - SOCKS4 Reply/Request message. -*/ - -public class Socks4Message extends ProxyMessage{ - - private byte[] msgBytes; - private int msgLength; - - /** - * Server failed reply, cmd command for failed request - */ - public Socks4Message(int cmd){ - super(cmd,null,0); - this.user = null; - - msgLength = 2; - msgBytes = new byte[2]; - - msgBytes[0] = (byte) 0; - msgBytes[1] = (byte) command; - } - - /** - * Server successfull reply - */ - public Socks4Message(int cmd,InetAddress ip,int port){ - this(0,cmd,ip,port,null); - } - - /** - * Client request - */ - public Socks4Message(int cmd,InetAddress ip,int port,String user){ - this(SOCKS_VERSION,cmd,ip,port,user); - } - - /** - * Most general constructor - */ - public Socks4Message(int version, int cmd, - InetAddress ip,int port,String user){ - super(cmd,ip,port); - this.user = user; - this.version = version; - - msgLength = user == null?8:9+user.length(); - msgBytes = new byte[msgLength]; - - msgBytes[0] = (byte) version; - msgBytes[1] = (byte) command; - msgBytes[2] = (byte) (port >> 8); - msgBytes[3] = (byte) port; - - byte[] addr; - - if(ip != null) - addr = ip.getAddress(); - else{ - addr = new byte[4]; - addr[0]=addr[1]=addr[2]=addr[3]=0; - } - System.arraycopy(addr,0,msgBytes,4,4); - - if(user != null){ - byte[] buf = user.getBytes(); - System.arraycopy(buf,0,msgBytes,8,buf.length); - msgBytes[msgBytes.length -1 ] = 0; - } - } - - /** - *Initialise from the stream - *If clientMode is true attempts to read a server response - *otherwise reads a client request - *see read for more detail - */ - public Socks4Message(InputStream in, boolean clientMode) throws IOException{ - msgBytes = null; - read(in,clientMode); - } - - public void read(InputStream in) throws IOException{ - read(in,true); - } - - public void read(InputStream in, boolean clientMode) throws IOException{ - DataInputStream d_in = new DataInputStream(in); - version= d_in.readUnsignedByte(); - command = d_in.readUnsignedByte(); - if(clientMode && command != REPLY_OK){ - String errMsg; - if(command >REPLY_OK && command < REPLY_BAD_IDENTD) - errMsg = replyMessage[command-REPLY_OK]; - else - errMsg = "Unknown Reply Code"; - throw new SocksException(command,errMsg); - } - port = d_in.readUnsignedShort(); - byte[] addr = new byte[4]; - d_in.readFully(addr); - ip=bytes2IP(addr); - host = ip.getHostName(); - if(!clientMode){ - int b = in.read(); - //Hope there are no idiots with user name bigger than this - byte[] userBytes = new byte[256]; - int i = 0; - for(i =0;i<userBytes.length && b>0;++i){ - userBytes[i] = (byte) b; - b = in.read(); - } - user = new String(userBytes,0,i); - } - } - public void write(OutputStream out) throws IOException{ - if(msgBytes == null){ - Socks4Message msg = new Socks4Message(version,command,ip,port,user); - msgBytes = msg.msgBytes; - msgLength = msg.msgLength; - } - out.write(msgBytes); - } - - //Class methods - static InetAddress bytes2IP(byte[] addr){ - String s = bytes2IPV4(addr,0); - try{ - return InetAddress.getByName(s); - }catch(UnknownHostException uh_ex){ - return null; - } - } - - //Constants - - static final String[] replyMessage ={ - "Request Granted", - "Request Rejected or Failed", - "Failed request, can't connect to Identd", - "Failed request, bad user name"}; - - static final int SOCKS_VERSION = 4; - - public final static int REQUEST_CONNECT = 1; - public final static int REQUEST_BIND = 2; - - public final static int REPLY_OK = 90; - public final static int REPLY_REJECTED = 91; - public final static int REPLY_NO_CONNECT = 92; - public final static int REPLY_BAD_IDENTD = 93; - -}
--- a/src/net/sourceforge/jsocks/Socks4Proxy.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -package net.sourceforge.jsocks; -import java.net.*; -import java.io.*; -import java.util.Hashtable; -import java.util.Enumeration; - -/** - CProxy which describes SOCKS4 proxy. -*/ - -public class Socks4Proxy extends CProxy implements Cloneable{ - -//Data members - String user; - -//Public Constructors -//==================== - - /** - Creates the SOCKS4 proxy - @param p CProxy to use to connect to this proxy, allows proxy chaining. - @param proxyHost Address of the proxy server. - @param proxyPort Port of the proxy server - @param user User name to use for identification purposes. - @throws UnknownHostException If proxyHost can't be resolved. - */ - public Socks4Proxy(CProxy p,String proxyHost,int proxyPort,String user) - throws UnknownHostException{ - super(p,proxyHost,proxyPort); - this.user = new String(user); - version = 4; - } - - /** - Creates the SOCKS4 proxy - @param proxyHost Address of the proxy server. - @param proxyPort Port of the proxy server - @param user User name to use for identification purposes. - @throws UnknownHostException If proxyHost can't be resolved. - */ - public Socks4Proxy(String proxyHost,int proxyPort,String user) - throws UnknownHostException{ - this(null,proxyHost,proxyPort,user); - } - - /** - Creates the SOCKS4 proxy - @param p CProxy to use to connect to this proxy, allows proxy chaining. - @param proxyIP Address of the proxy server. - @param proxyPort Port of the proxy server - @param user User name to use for identification purposes. - */ - public Socks4Proxy(CProxy p,InetAddress proxyIP,int proxyPort,String user){ - super(p,proxyIP,proxyPort); - this.user = new String(user); - version = 4; - } - - /** - Creates the SOCKS4 proxy - @param proxyIP Address of the proxy server. - @param proxyPort Port of the proxy server - @param user User name to use for identification purposes. - */ - public Socks4Proxy(InetAddress proxyIP,int proxyPort,String user){ - this(null,proxyIP,proxyPort,user); - } - -//Public instance methods -//======================== - - /** - * Creates a clone of this proxy. Changes made to the clone should not - * affect this object. - */ - public Object clone(){ - Socks4Proxy newProxy = new Socks4Proxy(proxyIP,proxyPort,user); - newProxy.directHosts = (InetRange)directHosts.clone(); - newProxy.chainProxy = chainProxy; - return newProxy; - } - - -//Public Static(Class) Methods -//============================== - - -//Protected Methods -//================= - - protected CProxy copy(){ - Socks4Proxy copy = new Socks4Proxy(proxyIP,proxyPort,user); - copy.directHosts = this.directHosts; - copy.chainProxy = chainProxy; - return copy; - } - - protected ProxyMessage formMessage(int cmd,InetAddress ip,int port){ - switch(cmd){ - case SOCKS_CMD_CONNECT: - cmd = Socks4Message.REQUEST_CONNECT; - break; - case SOCKS_CMD_BIND: - cmd = Socks4Message.REQUEST_BIND; - break; - default: - return null; - } - return new Socks4Message(cmd,ip,port,user); - } - protected ProxyMessage formMessage(int cmd,String host,int port) - throws UnknownHostException{ - return formMessage(cmd,InetAddress.getByName(host),port); - } - protected ProxyMessage formMessage(InputStream in) - throws SocksException, - IOException{ - return new Socks4Message(in,true); - } - -}
--- a/src/net/sourceforge/jsocks/Socks5DatagramSocket.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,487 +0,0 @@ -package net.sourceforge.jsocks; -import java.net.*; -import java.io.*; - -/** - Datagram socket to interract through the firewall.<BR> - Can be used same way as the normal DatagramSocket. One should - be carefull though with the datagram sizes used, as additional data - is present in both incomming and outgoing datagrams. - <p> - SOCKS5 protocol allows to send host address as either: - <ul> - <li> IPV4, normal 4 byte address. (10 bytes header size) - <li> IPV6, version 6 ip address (not supported by Java as for now). - 22 bytes header size. - <li> Host name,(7+length of the host name bytes header size). - </ul> - As with other Socks equivalents, direct addresses are handled - transparently, that is data will be send directly when required - by the proxy settings. - <p> - <b>NOTE:</b><br> - Unlike other SOCKS Sockets, it <b>does not</b> support proxy chaining, - and will throw an exception if proxy has a chain proxy attached. The - reason for that is not my laziness, but rather the restrictions of - the SOCKSv5 protocol. Basicaly SOCKSv5 proxy server, needs to know from - which host:port datagrams will be send for association, and returns address - to which datagrams should be send by the client, but it does not - inform client from which host:port it is going to send datagrams, in fact - there is even no guarantee they will be send at all and from the same address - each time. - - */ -public class Socks5DatagramSocket extends DatagramSocket{ - - InetAddress relayIP; - int relayPort; - Socks5Proxy proxy; - private boolean server_mode = false; - UDPEncapsulation encapsulation; - - - /** - Construct Datagram socket for communication over SOCKS5 proxy - server. This constructor uses default proxy, the one set with - CProxy.setDefaultProxy() method. If default proxy is not set or - it is set to version4 proxy, which does not support datagram - forwarding, throws SocksException. - - */ - public Socks5DatagramSocket() throws SocksException, - IOException{ - this(CProxy.defaultProxy,0,null); - } - /** - Construct Datagram socket for communication over SOCKS5 proxy - server. And binds it to the specified local port. - This constructor uses default proxy, the one set with - CProxy.setDefaultProxy() method. If default proxy is not set or - it is set to version4 proxy, which does not support datagram - forwarding, throws SocksException. - */ - public Socks5DatagramSocket(int port) throws SocksException, - IOException{ - this(CProxy.defaultProxy,port,null); - } - /** - Construct Datagram socket for communication over SOCKS5 proxy - server. And binds it to the specified local port and address. - This constructor uses default proxy, the one set with - CProxy.setDefaultProxy() method. If default proxy is not set or - it is set to version4 proxy, which does not support datagram - forwarding, throws SocksException. - */ - public Socks5DatagramSocket(int port,InetAddress ip) throws SocksException, - IOException{ - this(CProxy.defaultProxy,port,ip); - } - - /** - Constructs datagram socket for communication over specified proxy. - And binds it to the given local address and port. Address of null - and port of 0, signify any availabale port/address. - Might throw SocksException, if: - <ol> - <li> Given version of proxy does not support UDP_ASSOCIATE. - <li> CProxy can't be reached. - <li> Authorization fails. - <li> CProxy does not want to perform udp forwarding, for any reason. - </ol> - Might throw IOException if binding dtagram socket to given address/port - fails. - See java.net.DatagramSocket for more details. - */ - public Socks5DatagramSocket(CProxy p,int port,InetAddress ip) - throws SocksException, - IOException{ - super(port,ip); - if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); - if(!(p instanceof Socks5Proxy)) - throw new SocksException(-1,"Datagram Socket needs Proxy version 5"); - - if(p.chainProxy != null) - throw new SocksException(CProxy.SOCKS_JUST_ERROR, - "Datagram Sockets do not support proxy chaining."); - - proxy =(Socks5Proxy) p.copy(); - - ProxyMessage msg = proxy.udpAssociate(super.getLocalAddress(), - super.getLocalPort()); - relayIP = msg.ip; - if(relayIP.getHostAddress().equals("0.0.0.0")) relayIP = proxy.proxyIP; - relayPort = msg.port; - - encapsulation = proxy.udp_encapsulation; - - //debug("Datagram Socket:"+getLocalAddress()+":"+getLocalPort()+"\n"); - //debug("Socks5Datagram: "+relayIP+":"+relayPort+"\n"); - } - - /** - Used by UDPRelayServer. - */ - Socks5DatagramSocket(boolean server_mode,UDPEncapsulation encapsulation, - InetAddress relayIP,int relayPort) - throws IOException{ - super(); - this.server_mode = server_mode; - this.relayIP = relayIP; - this.relayPort = relayPort; - this.encapsulation = encapsulation; - this.proxy = null; - } - - /** - Sends the Datagram either through the proxy or directly depending - on current proxy settings and destination address. <BR> - - <B> NOTE: </B> DatagramPacket size should be at least 10 bytes less - than the systems limit. - - <P> - See documentation on java.net.DatagramSocket - for full details on how to use this method. - @param dp Datagram to send. - @throws IOException If error happens with I/O. - */ - public void send(DatagramPacket dp) throws IOException{ - //If the host should be accessed directly, send it as is. - if(!server_mode && proxy.isDirect(dp.getAddress())){ - super.send(dp); - //debug("Sending directly:"); - return; - } - - byte[] head = formHeader(dp.getAddress(),dp.getPort()); - byte[] buf = new byte[head.length + dp.getLength()]; - byte[] data = dp.getData(); - //Merge head and data - System.arraycopy(head,0,buf,0,head.length); - //System.arraycopy(data,dp.getOffset(),buf,head.length,dp.getLength()); - System.arraycopy(data,0,buf,head.length,dp.getLength()); - - if(encapsulation != null) - buf = encapsulation.udpEncapsulate(buf,true); - - super.send(new DatagramPacket(buf,buf.length,relayIP,relayPort)); - } - /** - This method allows to send datagram packets with address type DOMAINNAME. - SOCKS5 allows to specify host as names rather than ip addresses.Using - this method one can send udp datagrams through the proxy, without having - to know the ip address of the destination host. - <p> - If proxy specified for that socket has an option resolveAddrLocally set - to true host will be resolved, and the datagram will be send with address - type IPV4, if resolve fails, UnknownHostException is thrown. - @param dp Datagram to send, it should contain valid port and data - @param host Host name to which datagram should be send. - @throws IOException If error happens with I/O, or the host can't be - resolved when proxy settings say that hosts should be resolved locally. - @see Socks5Proxy#resolveAddrLocally(boolean) - */ - public void send(DatagramPacket dp, String host) throws IOException{ - if(proxy.isDirect(host)){ - dp.setAddress(InetAddress.getByName(host)); - super.send(dp); - return; - } - - if(((Socks5Proxy)proxy).resolveAddrLocally){ - dp.setAddress(InetAddress.getByName(host)); - } - - byte[] head = formHeader(host,dp.getPort()); - byte[] buf = new byte[head.length + dp.getLength()]; - byte[] data = dp.getData(); - //Merge head and data - System.arraycopy(head,0,buf,0,head.length); - //System.arraycopy(data,dp.getOffset(),buf,head.length,dp.getLength()); - System.arraycopy(data,0,buf,head.length,dp.getLength()); - - if(encapsulation != null) - buf = encapsulation.udpEncapsulate(buf,true); - - super.send(new DatagramPacket(buf,buf.length,relayIP,relayPort)); - } - - /** - * Receives udp packet. If packet have arrived from the proxy relay server, - * it is processed and address and port of the packet are set to the - * address and port of sending host.<BR> - * If the packet arrived from anywhere else it is not changed.<br> - * <B> NOTE: </B> DatagramPacket size should be at least 10 bytes bigger - * than the largest packet you expect (this is for IPV4 addresses). - * For hostnames and IPV6 it is even more. - @param dp Datagram in which all relevent information will be copied. - */ - public void receive(DatagramPacket dp) throws IOException{ - super.receive(dp); - - if(server_mode){ - //Drop all datagrams not from relayIP/relayPort - int init_length = dp.getLength(); - int initTimeout = getSoTimeout(); - long startTime = System.currentTimeMillis(); - - while(!relayIP.equals(dp.getAddress()) || - relayPort != dp.getPort()){ - - //Restore datagram size - dp.setLength(init_length); - - //If there is a non-infinit timeout on this socket - //Make sure that it happens no matter how often unexpected - //packets arrive. - if(initTimeout != 0){ - int newTimeout = initTimeout - (int)(System.currentTimeMillis() - - startTime); - if(newTimeout <= 0) throw new InterruptedIOException( - "In Socks5DatagramSocket->receive()"); - setSoTimeout(newTimeout); - } - - super.receive(dp); - } - - //Restore timeout settings - if(initTimeout != 0) setSoTimeout(initTimeout); - - }else if(!relayIP.equals(dp.getAddress()) || - relayPort != dp.getPort()) - return; // Recieved direct packet - //If the datagram is not from the relay server, return it it as is. - - byte[] data; - data = dp.getData(); - - if(encapsulation != null) - data = encapsulation.udpEncapsulate(data,false); - - int offset = 0; //Java 1.1 - //int offset = dp.getOffset(); //Java 1.2 - - ByteArrayInputStream bIn = new ByteArrayInputStream(data,offset, - dp.getLength()); - - - ProxyMessage msg = new Socks5Message(bIn); - dp.setPort(msg.port); - dp.setAddress(msg.getInetAddress()); - - //what wasn't read by the Message is the data - int data_length = bIn.available(); - //Shift data to the left - System.arraycopy(data,offset+dp.getLength()-data_length, - data,offset,data_length); - - - dp.setLength(data_length); - } - - /** - * Returns port assigned by the proxy, to which datagrams are relayed. - * It is not the same port to which other party should send datagrams. - @return Port assigned by socks server to which datagrams are send - for association. - */ - public int getLocalPort(){ - if(server_mode) return super.getLocalPort(); - return relayPort; - } - /** - * Address assigned by the proxy, to which datagrams are send for relay. - * It is not necesseraly the same address, to which other party should send - * datagrams. - @return Address to which datagrams are send for association. - */ - public InetAddress getLocalAddress(){ - if(server_mode) return super.getLocalAddress(); - return relayIP; - } - - /** - * Closes datagram socket, and proxy connection. - */ - public void close(){ - if(!server_mode) proxy.endSession(); - super.close(); - } - - /** - This method checks wether proxy still runs udp forwarding service - for this socket. - <p> - This methods checks wether the primary connection to proxy server - is active. If it is, chances are that proxy continues to forward - datagrams being send from this socket. If it was closed, most likely - datagrams are no longer being forwarded by the server. - <p> - CProxy might decide to stop forwarding datagrams, in which case it - should close primary connection. This method allows to check, wether - this have been done. - <p> - You can specify timeout for which we should be checking EOF condition - on the primary connection. Timeout is in milliseconds. Specifying 0 as - timeout implies infinity, in which case method will block, until - connection to proxy is closed or an error happens, and then return false. - <p> - One possible scenario is to call isProxyactive(0) in separate thread, - and once it returned notify other threads about this event. - - @param timeout For how long this method should block, before returning. - @return true if connection to proxy is active, false if eof or error - condition have been encountered on the connection. - */ - public boolean isProxyAlive(int timeout){ - if(server_mode) return false; - if(proxy != null){ - try{ - proxy.proxySocket.setSoTimeout(timeout); - - int eof = proxy.in.read(); - if(eof < 0) return false; // EOF encountered. - else return true; // This really should not happen - - }catch(InterruptedIOException iioe){ - return true; // read timed out. - }catch(IOException ioe){ - return false; - } - } - return false; - } - -//PRIVATE METHODS -////////////////// - - - private byte[] formHeader(InetAddress ip, int port){ - Socks5Message request = new Socks5Message(0,ip,port); - request.data[0] = 0; - return request.data; - } - - - private byte[] formHeader(String host,int port){ - Socks5Message request = new Socks5Message(0,host,port); - request.data[0] = 0; - return request.data; - } - - -/*====================================================================== - -//Mainly Test functions -////////////////////// - - private String bytes2String(byte[] b){ - String s=""; - char[] hex_digit = { '0','1','2','3','4','5','6','7','8','9', - 'A','B','C','D','E','F'}; - for(int i=0;i<b.length;++i){ - int i1 = (b[i] & 0xF0) >> 4; - int i2 = b[i] & 0xF; - s+=hex_digit[i1]; - s+=hex_digit[i2]; - s+=" "; - } - return s; - } - private static final void debug(String s){ - if(DEBUG) - System.out.print(s); - } - - private static final boolean DEBUG = true; - - - public static void usage(){ - System.err.print( - "Usage: java Socks.SocksDatagramSocket host port [socksHost socksPort]\n"); - } - - static final int defaultProxyPort = 1080; //Default Port - static final String defaultProxyHost = "www-proxy"; //Default proxy - - public static void main(String args[]){ - int port; - String host; - int proxyPort; - String proxyHost; - InetAddress ip; - - if(args.length > 1 && args.length < 5){ - try{ - - host = args[0]; - port = Integer.parseInt(args[1]); - - proxyPort =(args.length > 3)? Integer.parseInt(args[3]) - : defaultProxyPort; - - host = args[0]; - ip = InetAddress.getByName(host); - - proxyHost =(args.length > 2)? args[2] - : defaultProxyHost; - - CProxy.setDefaultProxy(proxyHost,proxyPort); - CProxy p = CProxy.getDefaultProxy(); - p.addDirect("lux"); - - - DatagramSocket ds = new Socks5DatagramSocket(); - - - BufferedReader in = new BufferedReader( - new InputStreamReader(System.in)); - String s; - - System.out.print("Enter line:"); - s = in.readLine(); - - while(s != null){ - byte[] data = (s+"\r\n").getBytes(); - DatagramPacket dp = new DatagramPacket(data,0,data.length, - ip,port); - System.out.println("Sending to: "+ip+":"+port); - ds.send(dp); - dp = new DatagramPacket(new byte[1024],1024); - - System.out.println("Trying to recieve on port:"+ - ds.getLocalPort()); - ds.receive(dp); - System.out.print("Recieved:\n"+ - "From:"+dp.getAddress()+":"+dp.getPort()+ - "\n\n"+ - new String(dp.getData(),dp.getOffset(),dp.getLength())+"\n" - ); - System.out.print("Enter line:"); - s = in.readLine(); - - } - ds.close(); - System.exit(1); - - }catch(SocksException s_ex){ - System.err.println("SocksException:"+s_ex); - s_ex.printStackTrace(); - System.exit(1); - }catch(IOException io_ex){ - io_ex.printStackTrace(); - System.exit(1); - }catch(NumberFormatException num_ex){ - usage(); - num_ex.printStackTrace(); - System.exit(1); - } - - }else{ - usage(); - } - } -*/ - -}
--- a/src/net/sourceforge/jsocks/Socks5Message.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ -package net.sourceforge.jsocks; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.DataInputStream; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - SOCKS5 request/response message. -*/ - -public class Socks5Message extends ProxyMessage{ - /** Address type of given message*/ - public int addrType; - - byte[] data; - - /** - Server error response. - @param cmd Error code. - */ - public Socks5Message(int cmd){ - super(cmd,null,0); - data = new byte[3]; - data[0] = SOCKS_VERSION; //Version. - data[1] = (byte)cmd; //Reply code for some kind of failure. - data[2] = 0; //Reserved byte. - } - - /** - Construct client request or server response. - @param cmd - Request/Response code. - @param ip - IP field. - @paarm port - port field. - */ - public Socks5Message(int cmd,InetAddress ip,int port){ - super(cmd,ip,port); - this.host = ip==null?"0.0.0.0":ip.getHostName(); - this.version = SOCKS_VERSION; - - byte[] addr; - - if(ip == null){ - addr = new byte[4]; - addr[0]=addr[1]=addr[2]=addr[3]=0; - }else - addr = ip.getAddress(); - - addrType = addr.length == 4 ? SOCKS_ATYP_IPV4 - : SOCKS_ATYP_IPV6; - - data = new byte[6+addr.length]; - data[0] = (byte) SOCKS_VERSION; //Version - data[1] = (byte) command; //Command - data[2] = (byte) 0; //Reserved byte - data[3] = (byte) addrType; //Address type - - //Put Address - System.arraycopy(addr,0,data,4,addr.length); - //Put port - data[data.length-2] = (byte)(port>>8); - data[data.length-1] = (byte)(port); - } - - - /** - Construct client request or server response. - @param cmd - Request/Response code. - @param hostName - IP field as hostName, uses ADDR_TYPE of HOSTNAME. - @paarm port - port field. - */ - public Socks5Message(int cmd,String hostName,int port){ - super(cmd,null,port); - this.host = hostName; - this.version = SOCKS_VERSION; - - //System.out.println("Doing ATYP_DOMAINNAME"); - - addrType = SOCKS_ATYP_DOMAINNAME; - byte addr[] = hostName.getBytes(); - - data =new byte[7+addr.length]; - data[0] = (byte) SOCKS_VERSION; //Version - data[1] = (byte) command; //Command - data[2] = (byte) 0; //Reserved byte - data[3] = (byte) SOCKS_ATYP_DOMAINNAME; //Address type - data[4] = (byte) addr.length; //Length of the address - - //Put Address - System.arraycopy(addr,0,data,5,addr.length); - //Put port - data[data.length-2] = (byte)(port >>8); - data[data.length-1] = (byte)(port); - } - - /** - Initialises Message from the stream. Reads server response from - given stream. - @param in Input stream to read response from. - @throws SocksException If server response code is not SOCKS_SUCCESS(0), or - if any error with protocol occurs. - @throws IOException If any error happens with I/O. - */ - public Socks5Message(InputStream in) throws SocksException, - IOException{ - this(in,true); - } - - /** - Initialises Message from the stream. Reads server response or client - request from given stream. - - @param in Input stream to read response from. - @param clinetMode If true read server response, else read client request. - @throws SocksException If server response code is not SOCKS_SUCCESS(0) and - reading in client mode, or if any error with protocol occurs. - @throws IOException If any error happens with I/O. - */ - public Socks5Message(InputStream in,boolean clientMode)throws SocksException, - IOException{ - read(in,clientMode); - } - - - /** - Initialises Message from the stream. Reads server response from - given stream. - @param in Input stream to read response from. - @throws SocksException If server response code is not SOCKS_SUCCESS(0), or - if any error with protocol occurs. - @throws IOException If any error happens with I/O. - */ - public void read(InputStream in) throws SocksException, - IOException{ - read(in,true); - } - - - /** - Initialises Message from the stream. Reads server response or client - request from given stream. - - @param in Input stream to read response from. - @param clinetMode If true read server response, else read client request. - @throws SocksException If server response code is not SOCKS_SUCCESS(0) and - reading in client mode, or if any error with protocol occurs. - @throws IOException If any error happens with I/O. - */ - public void read(InputStream in,boolean clientMode) throws SocksException, - IOException{ - data = null; - ip = null; - - DataInputStream di = new DataInputStream(in); - - version = di.readUnsignedByte(); - command = di.readUnsignedByte(); - if(clientMode && command != 0) - throw new SocksException(command); - - int reserved = di.readUnsignedByte(); - addrType = di.readUnsignedByte(); - - byte addr[]; - - switch(addrType){ - case SOCKS_ATYP_IPV4: - addr = new byte[4]; - di.readFully(addr); - host = bytes2IPV4(addr,0); - break; - case SOCKS_ATYP_IPV6: - addr = new byte[SOCKS_IPV6_LENGTH];//I believe it is 16 bytes,huge! - di.readFully(addr); - host = bytes2IPV6(addr,0); - break; - case SOCKS_ATYP_DOMAINNAME: - //System.out.println("Reading ATYP_DOMAINNAME"); - addr = new byte[di.readUnsignedByte()];//Next byte shows the length - di.readFully(addr); - host = new String(addr); - break; - default: - throw(new SocksException(CProxy.SOCKS_JUST_ERROR)); - } - - port = di.readUnsignedShort(); - - if(addrType != SOCKS_ATYP_DOMAINNAME && doResolveIP){ - try{ - ip = InetAddress.getByName(host); - }catch(UnknownHostException uh_ex){ - } - } - } - - /** - Writes the message to the stream. - @param out Output stream to which message should be written. - */ - public void write(OutputStream out)throws SocksException, - IOException{ - if(data == null){ - Socks5Message msg; - - if(addrType == SOCKS_ATYP_DOMAINNAME) - msg = new Socks5Message(command,host,port); - else{ - if(ip == null){ - try{ - ip = InetAddress.getByName(host); - }catch(UnknownHostException uh_ex){ - throw new SocksException(CProxy.SOCKS_JUST_ERROR); - } - } - msg = new Socks5Message(command,ip,port); - } - data = msg.data; - } - out.write(data); - } - - /** - Returns IP field of the message as IP, if the message was created - with ATYP of HOSTNAME, it will attempt to resolve the hostname, - which might fail. - @throws UnknownHostException if host can't be resolved. - */ - public InetAddress getInetAddress() throws UnknownHostException{ - if(ip!=null) return ip; - - return (ip=InetAddress.getByName(host)); - } - - /** - Returns string representation of the message. - */ - public String toString(){ - String s= - "Socks5Message:"+"\n"+ - "VN "+version+"\n"+ - "CMD "+command+"\n"+ - "ATYP "+addrType+"\n"+ - "ADDR "+host+"\n"+ - "PORT "+port+"\n"; - return s; - } - - - /** - *Wether to resolve hostIP returned from SOCKS server - *that is wether to create InetAddress object from the - *hostName string - */ - static public boolean resolveIP(){ return doResolveIP;} - - /** - *Wether to resolve hostIP returned from SOCKS server - *that is wether to create InetAddress object from the - *hostName string - *@param doResolve Wether to resolve hostIP from SOCKS server. - *@return Previous value. - */ - static public boolean resolveIP(boolean doResolve){ - boolean old = doResolveIP; - doResolveIP = doResolve; - return old; - } - - /* - private static final void debug(String s){ - if(DEBUG) - System.out.print(s); - } - private static final boolean DEBUG = false; - */ - - //SOCKS5 constants - public static final int SOCKS_VERSION =5; - - public static final int SOCKS_ATYP_IPV4 =0x1; //Where is 2?? - public static final int SOCKS_ATYP_DOMAINNAME =0x3; //!!!!rfc1928 - public static final int SOCKS_ATYP_IPV6 =0x4; - - public static final int SOCKS_IPV6_LENGTH =16; - - static boolean doResolveIP = true; - -}
--- a/src/net/sourceforge/jsocks/Socks5Proxy.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,248 +0,0 @@ -package net.sourceforge.jsocks; -import java.net.*; -import java.io.*; -import java.util.Hashtable; -import java.util.Enumeration; - -/** - SOCKS5 CProxy. -*/ - -public class Socks5Proxy extends CProxy implements Cloneable{ - -//Data members - private Hashtable authMethods = new Hashtable(); - private int selectedMethod; - - boolean resolveAddrLocally = true; - UDPEncapsulation udp_encapsulation=null; - - -//Public Constructors -//==================== - - /** - Creates SOCKS5 proxy. - @param p CProxy to use to connect to this proxy, allows proxy chaining. - @param proxyHost Host on which a CProxy server runs. - @param proxyPort Port on which a CProxy server listens for connections. - @throws UnknownHostException If proxyHost can't be resolved. - */ - public Socks5Proxy(CProxy p,String proxyHost,int proxyPort) - throws UnknownHostException{ - super(p,proxyHost,proxyPort); - version = 5; - setAuthenticationMethod(0,new AuthenticationNone()); - } - - /** - Creates SOCKS5 proxy. - @param proxyHost Host on which a CProxy server runs. - @param proxyPort Port on which a CProxy server listens for connections. - @throws UnknownHostException If proxyHost can't be resolved. - */ - public Socks5Proxy(String proxyHost,int proxyPort) - throws UnknownHostException{ - this(null,proxyHost,proxyPort); - } - - - /** - Creates SOCKS5 proxy. - @param p CProxy to use to connect to this proxy, allows proxy chaining. - @param proxyIP Host on which a CProxy server runs. - @param proxyPort Port on which a CProxy server listens for connections. - */ - public Socks5Proxy(CProxy p,InetAddress proxyIP,int proxyPort){ - super(p,proxyIP,proxyPort); - version = 5; - setAuthenticationMethod(0,new AuthenticationNone()); - } - - /** - Creates SOCKS5 proxy. - @param proxyIP Host on which a CProxy server runs. - @param proxyPort Port on which a CProxy server listens for connections. - */ - public Socks5Proxy(InetAddress proxyIP,int proxyPort){ - this(null,proxyIP,proxyPort); - } - -//Public instance methods -//======================== - - - /** - * Wether to resolve address locally or to let proxy do so. - <p> - SOCKS5 protocol allows to send host names rather then IPs in the - requests, this option controls wether the hostnames should be send - to the proxy server as names, or should they be resolved locally. - @param doResolve Wether to perform resolution locally. - @return Previous settings. - */ - public boolean resolveAddrLocally(boolean doResolve){ - boolean old = resolveAddrLocally; - resolveAddrLocally = doResolve; - return old; - } - /** - Get current setting on how the addresses should be handled. - @return Current setting for address resolution. - @see Socks5Proxy#resolveAddrLocally(boolean doResolve) - */ - public boolean resolveAddrLocally(){ - return resolveAddrLocally; - } - - /** - Adds another authentication method. - @param methodId Authentication method id, see rfc1928 - @param method Implementation of Authentication - @see Authentication - */ - public boolean setAuthenticationMethod(int methodId, - Authentication method){ - if(methodId<0 || methodId > 255) - return false; - if(method == null){ - //Want to remove a particular method - return (authMethods.remove(new Integer(methodId)) != null); - }else{//Add the method, or rewrite old one - authMethods.put(new Integer(methodId),method); - } - return true; - } - - /** - Get authentication method, which corresponds to given method id - @param methodId Authentication method id. - @return Implementation for given method or null, if one was not set. - */ - public Authentication getAuthenticationMethod(int methodId){ - Object method = authMethods.get(new Integer(methodId)); - if(method == null) return null; - return (Authentication)method; - } - - /** - Creates a clone of this CProxy. - */ - public Object clone(){ - Socks5Proxy newProxy = new Socks5Proxy(proxyIP,proxyPort); - newProxy.authMethods = (Hashtable) this.authMethods.clone(); - newProxy.directHosts = (InetRange)directHosts.clone(); - newProxy.resolveAddrLocally = resolveAddrLocally; - newProxy.chainProxy = chainProxy; - return newProxy; - } - -//Public Static(Class) Methods -//============================== - - -//Protected Methods -//================= - - protected CProxy copy(){ - Socks5Proxy copy = new Socks5Proxy(proxyIP,proxyPort); - copy.authMethods = this.authMethods; //same Hash, no copy - copy.directHosts = this.directHosts; - copy.chainProxy = this.chainProxy; - copy.resolveAddrLocally = this.resolveAddrLocally; - return copy; - } - /** - * - * - */ - protected void startSession()throws SocksException{ - super.startSession(); - Authentication auth; - Socket ps = proxySocket; //The name is too long - - try{ - - byte nMethods = (byte) authMethods.size(); //Number of methods - - byte[] buf = new byte[2+nMethods]; //2 is for VER,NMETHODS - buf[0] = (byte) version; - buf[1] = nMethods; //Number of methods - int i=2; - - Enumeration ids = authMethods.keys(); - while(ids.hasMoreElements()) - buf[i++] = (byte)((Integer)ids.nextElement()).intValue(); - - out.write(buf); - out.flush(); - - int versionNumber = in.read(); - selectedMethod = in.read(); - - if(versionNumber < 0 || selectedMethod < 0){ - //EOF condition was reached - endSession(); - throw(new SocksException(SOCKS_PROXY_IO_ERROR, - "Connection to proxy lost.")); - } - if(versionNumber < version){ - //What should we do?? - } - if(selectedMethod == 0xFF){ //No method selected - ps.close(); - throw ( new SocksException(SOCKS_AUTH_NOT_SUPPORTED)); - } - - auth = getAuthenticationMethod(selectedMethod); - if(auth == null){ - //This shouldn't happen, unless method was removed by other - //thread, or the server stuffed up - throw(new SocksException(SOCKS_JUST_ERROR, - "Speciefied Authentication not found!")); - } - Object[] in_out = auth.doSocksAuthentication(selectedMethod,ps); - if(in_out == null){ - //Authentication failed by some reason - throw(new SocksException(SOCKS_AUTH_FAILURE)); - } - //Most authentication methods are expected to return - //simply the input/output streams associated with - //the socket. However if the auth. method requires - //some kind of encryption/decryption being done on the - //connection it should provide classes to handle I/O. - - in = (InputStream) in_out[0]; - out = (OutputStream) in_out[1]; - if(in_out.length > 2) - udp_encapsulation = (UDPEncapsulation) in_out[2]; - - }catch(SocksException s_ex){ - throw s_ex; - }catch(UnknownHostException uh_ex){ - throw(new SocksException(SOCKS_PROXY_NO_CONNECT)); - }catch(SocketException so_ex){ - throw(new SocksException(SOCKS_PROXY_NO_CONNECT)); - }catch(IOException io_ex){ - //System.err.println(io_ex); - throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex)); - } - } - - protected ProxyMessage formMessage(int cmd,InetAddress ip,int port){ - return new Socks5Message(cmd,ip,port); - } - protected ProxyMessage formMessage(int cmd,String host,int port) - throws UnknownHostException{ - if(resolveAddrLocally) - return formMessage(cmd,InetAddress.getByName(host),port); - else - return new Socks5Message(cmd,host,port); - } - protected ProxyMessage formMessage(InputStream in) - throws SocksException, - IOException{ - return new Socks5Message(in); - } - -}
--- a/src/net/sourceforge/jsocks/SocksException.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -package net.sourceforge.jsocks; - -/** - Exception thrown by various socks classes to indicate errors - with protocol or unsuccessfull server responses. -*/ -public class SocksException extends java.io.IOException{ - /** - Construct a SocksException with given errorcode. - <p> - Tries to look up message which corresponds to this error code. - @param errCode Error code for this exception. - */ - public SocksException(int errCode){ - this.errCode = errCode; - if((errCode >> 16) == 0){ - //Server reply error message - errString = errCode <= serverReplyMessage.length ? - serverReplyMessage[errCode] : - UNASSIGNED_ERROR_MESSAGE; - }else{ - //Local error - errCode = (errCode >> 16) -1; - errString = errCode <= localErrorMessage.length ? - localErrorMessage[errCode] : - UNASSIGNED_ERROR_MESSAGE; - } - } - /** - Constructs a SocksException with given error code and message. - @param errCode Error code. - @param errString Error Message. - */ - public SocksException(int errCode,String errString){ - this.errCode = errCode; - this.errString = errString; - } - /** - Get the error code associated with this exception. - @return Error code associated with this exception. - */ - public int getErrorCode(){ - return errCode; - } - /** - Get human readable representation of this exception. - @return String represntation of this exception. - */ - public String toString(){ - return errString; - } - - static final String UNASSIGNED_ERROR_MESSAGE = - "Unknown error message"; - static final String serverReplyMessage[] = { - "Succeeded", - "General SOCKS server failure", - "Connection not allowed by ruleset", - "Network unreachable", - "Host unreachable", - "Connection refused", - "TTL expired", - "Command not supported", - "Address type not supported" }; - - static final String localErrorMessage[] ={ - "SOCKS server not specified", - "Unable to contact SOCKS server", - "IO error", - "None of Authentication methods are supported", - "Authentication failed", - "General SOCKS fault" }; - - String errString; - public int errCode; - -}//End of SocksException class -
--- a/src/net/sourceforge/jsocks/SocksServerSocket.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,207 +0,0 @@ -package net.sourceforge.jsocks; - -import java.net.*; -import java.io.*; - -/** - SocksServerSocket allows to accept connections from one particular - host through the SOCKS4 or SOCKS5 proxy. -*/ -public class SocksServerSocket extends ServerSocket{ - //Data members - protected CProxy proxy; - protected String localHost; - protected InetAddress localIP; - protected int localPort; - - boolean doing_direct = false; - InetAddress remoteAddr; - - /** - * Creates ServerSocket capable of accepting one connection - * through the firewall, uses default CProxy. - *@param host Host from which the connection should be recieved. - *@param port Port number of the primary connection. - */ - public SocksServerSocket(String host,int port) - throws SocksException,UnknownHostException,IOException{ - this(CProxy.defaultProxy,host,port); - } - /** - *Creates ServerSocket capable of accepting one connection - *through the firewall, uses given proxy. - *@param p CProxy object to use. - *@param host Host from which the connection should be recieved. - *@param port Port number of the primary connection. - */ - public SocksServerSocket(CProxy p,String host,int port) - throws SocksException,UnknownHostException,IOException{ - - - super(0); - if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); - //proxy=p; - proxy = p.copy(); - if(proxy.isDirect(host)){ - remoteAddr = InetAddress.getByName(host); - proxy = null; - doDirect(); - }else{ - processReply(proxy.bind(host,port)); - } - } - - /** - * Creates ServerSocket capable of accepting one connection - * through the firewall, uses default CProxy. - *@param ip Host from which the connection should be recieved. - *@param port Port number of the primary connection. - */ - public SocksServerSocket(InetAddress ip, int port) throws SocksException, - IOException{ - this(CProxy.defaultProxy,ip,port); - } - - /** - *Creates ServerSocket capable of accepting one connection - *through the firewall, uses given proxy. - *@param p CProxy object to use. - *@param ip Host from which the connection should be recieved. - *@param port Port number of the primary connection. - */ - public SocksServerSocket(CProxy p,InetAddress ip, int port) - throws SocksException,IOException{ - super(0); - - if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); - this.proxy = p.copy(); - - if(proxy.isDirect(ip)){ - remoteAddr = ip; - doDirect(); - }else{ - processReply(proxy.bind(ip,port)); - } - } - - - /** - * Accepts the incoming connection. - */ - public Socket accept() throws IOException{ - Socket s; - - if(!doing_direct){ - if(proxy == null) return null; - - ProxyMessage msg = proxy.accept(); - s = msg.ip == null? new SocksSocket(msg.host,msg.port,proxy) - : new SocksSocket(msg.ip,msg.port,proxy); - //Set timeout back to 0 - proxy.proxySocket.setSoTimeout(0); - }else{ //Direct Connection - - //Mimic the proxy behaviour, - //only accept connections from the speciefed host. - while(true){ - s = super.accept(); - if(s.getInetAddress().equals(remoteAddr)){ - //got the connection from the right host - //Close listenning socket. - break; - }else - s.close(); //Drop all connections from other hosts - } - - } - proxy = null; - //Return accepted socket - return s; - } - - /** - * Closes the connection to proxy if socket have not been accepted, if - * the direct connection is used, closes direct ServerSocket. If the - * client socket have been allready accepted, does nothing. - */ - public void close() throws IOException{ - super.close(); - if(proxy != null) proxy.endSession(); - proxy = null; - } - - /** - Get the name of the host proxy is using to listen for incoming - connection. - <P> - Usefull when address is returned by proxy as the hostname. - @return the hostname of the address proxy is using to listen - for incoming connection. - */ - public String getHost(){ - return localHost; - } - - /** - * Get address assigned by proxy to listen for incomming - * connections, or the local machine address if doing direct - * connection. - */ - public InetAddress getInetAddress(){ - if(localIP == null){ - try{ - localIP = InetAddress.getByName(localHost); - }catch(UnknownHostException e){ - return null; - } - } - return localIP; - } - - /** - * Get port assigned by proxy to listen for incoming connections, or - the port chosen by local system, if accepting directly. - */ - public int getLocalPort(){ - return localPort; - } - - /** - Set Timeout. - - @param timeout Amount of time in milliseconds, accept should wait for - incoming connection before failing with exception. - Zero timeout implies infinity. - */ - public void setSoTimeout(int timeout) throws SocketException{ - super.setSoTimeout(timeout); - if(!doing_direct) proxy.proxySocket.setSoTimeout(timeout); - } - - -//Private Methods -////////////////// - - private void processReply(ProxyMessage reply)throws SocksException{ - localPort = reply.port; - /* - * If the server have assigned same host as it was contacted on - * it might return an address of all zeros - */ - if(reply.host.equals("0.0.0.0")){ - localIP = proxy.proxyIP; - localHost = localIP.getHostName(); - }else{ - localHost = reply.host; - localIP = reply.ip; - } - } - - private void doDirect(){ - doing_direct = true; - localPort = super.getLocalPort(); - localIP = super.getInetAddress(); - localHost = localIP.getHostName(); - } - -}
--- a/src/net/sourceforge/jsocks/SocksSocket.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,332 +0,0 @@ -package net.sourceforge.jsocks; - -import java.net.*; -import java.io.*; - -/** - * SocksSocket tryies to look very similar to normal Socket, - * while allowing connections through the SOCKS4 or 5 proxy. - * To use this class you will have to identify proxy you need - * to use, CProxy class allows you to set default proxy, which - * will be used by all Socks aware sockets. You can also create - * either Socks4Proxy or Socks5Proxy, and use them by passing to the - * appropriate constructors. - * <P> - * Using Socks package can be as easy as that: - * - * <pre><tt> - * - * import Socks.*; - * .... - * - * try{ - * //Specify SOCKS5 proxy - * CProxy.setDefaultProxy("socks-proxy",1080); - * - * //OR you still use SOCKS4 - * //Code below uses SOCKS4 proxy - * //CProxy.setDefaultProxy("socks-proxy",1080,userName); - * - * Socket s = SocksSocket("some.host.of.mine",13); - * readTimeFromSock(s); - * }catch(SocksException sock_ex){ - * //Usually it will turn in more or less meaningfull message - * System.err.println("SocksException:"+sock_ex); - * } - * - * </tt></pre> - *<P> - * However if the need exist for more control, like resolving addresses - * remotely, or using some non-trivial authentication schemes, it can be done. - */ - -public class SocksSocket extends Socket{ - //Data members - protected CProxy proxy; - protected String localHost, remoteHost; - protected InetAddress localIP, remoteIP; - protected int localPort,remotePort; - - private Socket directSock = null; - - /** - * Tryies to connect to given host and port - * using default proxy. If no default proxy speciefied - * it throws SocksException with error code SOCKS_NO_PROXY. - @param host Machine to connect to. - @param port Port to which to connect. - * @see SocksSocket#SocksSocket(CProxy,String,int) - * @see Socks5Proxy#resolveAddrLocally - */ - public SocksSocket(String host,int port) - throws SocksException,UnknownHostException{ - this(CProxy.defaultProxy,host,port); - } - /** - * Connects to host port using given proxy server. - @param p CProxy to use. - @param host Machine to connect to. - @param port Port to which to connect. - @throws UnknownHostException - If one of the following happens: - <ol> - - <li> CProxy settings say that address should be resolved locally, but - this fails. - <li> CProxy settings say that the host should be contacted directly but - host name can't be resolved. - </ol> - @throws SocksException - If one of the following happens: - <ul> - <li> CProxy is is null. - <li> CProxy settings say that the host should be contacted directly but - this fails. - <li> Socks Server can't be contacted. - <li> Authentication fails. - <li> Connection is not allowed by the SOCKS proxy. - <li> SOCKS proxy can't establish the connection. - <li> Any IO error occured. - <li> Any protocol error occured. - </ul> - @throws IOexception if anything is wrong with I/O. - @see Socks5Proxy#resolveAddrLocally - */ - public SocksSocket(CProxy p,String host,int port) - throws SocksException,UnknownHostException{ - - - if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); - //proxy=p; - proxy = p.copy(); - remoteHost = host; - remotePort = port; - if(proxy.isDirect(host)){ - remoteIP = InetAddress.getByName(host); - doDirect(); - } - else - processReply(proxy.connect(host,port)); - } - - - /** - * Tryies to connect to given ip and port - * using default proxy. If no default proxy speciefied - * it throws SocksException with error code SOCKS_NO_PROXY. - @param ip Machine to connect to. - @param port Port to which to connect. - * @see SocksSocket#SocksSocket(CProxy,String,int) - */ - public SocksSocket(InetAddress ip, int port) throws SocksException{ - this(CProxy.defaultProxy,ip,port); - } - - /** - Connects to given ip and port using given CProxy server. - @param p CProxy to use. - @param ip Machine to connect to. - @param port Port to which to connect. - - */ - public SocksSocket(CProxy p,InetAddress ip, int port) throws SocksException{ - if(p == null) throw new SocksException(CProxy.SOCKS_NO_PROXY); - this.proxy = p.copy(); - this.remoteIP = ip; - this.remotePort = port; - this.remoteHost = ip.getHostName(); - if(proxy.isDirect(remoteIP)) - doDirect(); - else - processReply(proxy.connect(ip,port)); - } - - - /** - * These 2 constructors are used by the SocksServerSocket. - * This socket simply overrides remoteHost, remotePort - */ - protected SocksSocket(String host,int port,CProxy proxy){ - this.remotePort = port; - this.proxy = proxy; - this.localIP = proxy.proxySocket.getLocalAddress(); - this.localPort = proxy.proxySocket.getLocalPort(); - this.remoteHost = host; - } - protected SocksSocket(InetAddress ip,int port,CProxy proxy){ - remoteIP = ip; - remotePort = port; - this.proxy = proxy; - this.localIP = proxy.proxySocket.getLocalAddress(); - this.localPort = proxy.proxySocket.getLocalPort(); - remoteHost = remoteIP.getHostName(); - } - - /** - * Same as Socket - */ - public void close() throws IOException{ - if(proxy!= null)proxy.endSession(); - proxy = null; - } - /** - * Same as Socket - */ - public InputStream getInputStream(){ - return proxy.in; - } - /** - * Same as Socket - */ - public OutputStream getOutputStream(){ - return proxy.out; - } - /** - * Same as Socket - */ - public int getPort(){ - return remotePort; - } - /** - * Returns remote host name, it is usefull in cases when addresses - * are resolved by proxy, and we can't create InetAddress object. - @return The name of the host this socket is connected to. - */ - public String getHost(){ - return remoteHost; - } - /** - * Get remote host as InetAddress object, might return null if - * addresses are resolved by proxy, and it is not possible to resolve - * it locally - @return Ip address of the host this socket is connected to, or null - if address was returned by the proxy as DOMAINNAME and can't be - resolved locally. - */ - public InetAddress getInetAddress(){ - if(remoteIP == null){ - try{ - remoteIP = InetAddress.getByName(remoteHost); - }catch(UnknownHostException e){ - return null; - } - } - return remoteIP; - } - - /** - * Get the port assigned by the proxy for the socket, not - * the port on locall machine as in Socket. - @return Port of the socket used on the proxy server. - */ - public int getLocalPort(){ - return localPort; - } - - /** - * Get address assigned by proxy to make a remote connection, - * it might be different from the host specified for the proxy. - * Can return null if socks server returned this address as hostname - * and it can't be resolved locally, use getLocalHost() then. - @return Address proxy is using to make a connection. - */ - public InetAddress getLocalAddress(){ - if(localIP == null){ - try{ - localIP = InetAddress.getByName(localHost); - }catch(UnknownHostException e){ - return null; - } - } - return localIP; - } - /** - Get name of the host, proxy has assigned to make a remote connection - for this socket. This method is usefull when proxy have returned - address as hostname, and we can't resolve it on this machine. - @return The name of the host proxy is using to make a connection. - */ - public String getLocalHost(){ - return localHost; - } - - /** - Same as socket. - */ - public void setSoLinger(boolean on,int val) throws SocketException{ - proxy.proxySocket.setSoLinger(on,val); - } - /** - Same as socket. - */ - public int getSoLinger(int timeout) throws SocketException{ - return proxy.proxySocket.getSoLinger(); - } - /** - Same as socket. - */ - public void setSoTimeout(int timeout) throws SocketException{ - proxy.proxySocket.setSoTimeout(timeout); - } - /** - Same as socket. - */ - public int getSoTimeout(int timeout) throws SocketException{ - return proxy.proxySocket.getSoTimeout(); - } - /** - Same as socket. - */ - public void setTcpNoDelay(boolean on) throws SocketException{ - proxy.proxySocket.setTcpNoDelay(on); - } - /** - Same as socket. - */ - public boolean getTcpNoDelay() throws SocketException{ - return proxy.proxySocket.getTcpNoDelay(); - } - - /** - Get string representation of the socket. - */ - public String toString(){ - if(directSock!=null) return "Direct connection:"+directSock; - return ("Proxy:"+proxy+";"+"addr:"+remoteHost+",port:"+remotePort - +",localport:"+localPort); - - } - -//Private Methods -////////////////// - - private void processReply(ProxyMessage reply)throws SocksException{ - localPort = reply.port; - /* - * If the server have assigned same host as it was contacted on - * it might return an address of all zeros - */ - if(reply.host.equals("0.0.0.0")){ - localIP = proxy.proxyIP; - localHost = localIP.getHostName(); - }else{ - localHost = reply.host; - localIP = reply.ip; - } - } - private void doDirect()throws SocksException{ - try{ - //System.out.println("IP:"+remoteIP+":"+remotePort); - directSock = new Socket(remoteIP,remotePort); - proxy.out = directSock.getOutputStream(); - proxy.in = directSock.getInputStream(); - proxy.proxySocket = directSock; - localIP = directSock.getLocalAddress(); - localPort = directSock.getLocalPort(); - }catch(IOException io_ex){ - throw new SocksException(CProxy.SOCKS_DIRECT_FAILED, - "Direct connect failed:"+io_ex); - } - } - -}
--- a/src/net/sourceforge/jsocks/UDPEncapsulation.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -package net.sourceforge.jsocks; -/** - This interface provides for datagram encapsulation for SOCKSv5 protocol. - <p> - SOCKSv5 allows for datagrams to be encapsulated for purposes of integrity - and/or authenticity. How it should be done is aggreed during the - authentication stage, and is authentication dependent. This interface is - provided to allow this encapsulation. - @see Authentication -*/ -public interface UDPEncapsulation{ - - /** - This method should provide any authentication depended transformation - on datagrams being send from/to the client. - - @param data Datagram data (including any SOCKS related bytes), to be - encapsulated/decapsulated. - @param out Wether the data is being send out. If true method should - encapsulate/encrypt data, otherwise it should decapsulate/ - decrypt data. - @throw IOException if for some reason data can be transformed correctly. - @return Should return byte array containing data after transformation. - It is possible to return same array as input, if transformation - only involves bit mangling, and no additional data is being - added or removed. - */ - byte[] udpEncapsulate(byte[] data, boolean out) throws java.io.IOException; -}
--- a/src/net/sourceforge/jsocks/UDPRelayServer.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -package net.sourceforge.jsocks; -import net.sourceforge.jsocks.server.*; -import java.net.*; -import java.io.*; - -/** - UDP Relay server, used by ProxyServer to perform udp forwarding. -*/ -class UDPRelayServer implements Runnable{ - - - DatagramSocket client_sock; - DatagramSocket remote_sock; - - Socket controlConnection; - - int relayPort; - InetAddress relayIP; - - Thread pipe_thread1,pipe_thread2; - Thread master_thread; - - ServerAuthenticator auth; - - long lastReadTime; - - static PrintStream log = null; - static CProxy proxy = null; - static int datagramSize = 0xFFFF;//64K, a bit more than max udp size - static int iddleTimeout = 180000;//3 minutes - - - /** - Constructs UDP relay server to communicate with client - on given ip and port. - @param clientIP Address of the client from whom datagrams - will be recieved and to whom they will be forwarded. - @param clientPort Clients port. - @param master_thread Thread which will be interrupted, when - UDP relay server stoppes for some reason. - @param controlConnection Socket which will be closed, before - interrupting the master thread, it is introduced due to a bug - in windows JVM which does not throw InterruptedIOException in - threads which block in I/O operation. - */ - public UDPRelayServer(InetAddress clientIP,int clientPort, - Thread master_thread, - Socket controlConnection, - ServerAuthenticator auth) - throws IOException{ - this.master_thread = master_thread; - this.controlConnection = controlConnection; - this.auth = auth; - - client_sock = new Socks5DatagramSocket(true,auth.getUdpEncapsulation(), - clientIP,clientPort); - relayPort = client_sock.getLocalPort(); - relayIP = client_sock.getLocalAddress(); - - if(relayIP.getHostAddress().equals("0.0.0.0")) - relayIP = InetAddress.getLocalHost(); - - if(proxy == null) - remote_sock = new DatagramSocket(); - else - remote_sock = new Socks5DatagramSocket(proxy,0,null); - } - - -//Public methods -///////////////// - - - /** - Sets the timeout for UDPRelay server.<br> - Zero timeout implies infinity.<br> - Default timeout is 3 minutes. - */ - - static public void setTimeout(int timeout){ - iddleTimeout = timeout; - } - - - /** - Sets the size of the datagrams used in the UDPRelayServer.<br> - Default size is 64K, a bit more than maximum possible size of the - datagram. - */ - static public void setDatagramSize(int size){ - datagramSize = size; - } - - /** - Port to which client should send datagram for association. - */ - public int getRelayPort(){ - return relayPort; - } - /** - IP address to which client should send datagrams for association. - */ - public InetAddress getRelayIP(){ - return relayIP; - } - - /** - Starts udp relay server. - Spawns two threads of execution and returns. - */ - public void start() throws IOException{ - remote_sock.setSoTimeout(iddleTimeout); - client_sock.setSoTimeout(iddleTimeout); - - log("Starting UDP relay server on "+relayIP+":"+relayPort); - log("Remote socket "+remote_sock.getLocalAddress()+":"+ - remote_sock.getLocalPort()); - - pipe_thread1 = new Thread(this,"pipe1"); - pipe_thread2 = new Thread(this,"pipe2"); - - lastReadTime = System.currentTimeMillis(); - - pipe_thread1.start(); - pipe_thread2.start(); - } - - /** - Stops Relay server. - <p> - Does not close control connection, does not interrupt master_thread. - */ - public synchronized void stop(){ - master_thread = null; - controlConnection = null; - abort(); - } - -//Runnable interface -//////////////////// - public void run(){ - try{ - if(Thread.currentThread().getName().equals("pipe1")) - pipe(remote_sock,client_sock,false); - else - pipe(client_sock,remote_sock,true); - }catch(IOException ioe){ - }finally{ - abort(); - log("UDP Pipe thread "+Thread.currentThread().getName()+" stopped."); - } - - } - -//Private methods -///////////////// - private synchronized void abort(){ - if(pipe_thread1 == null) return; - - log("Aborting UDP Relay Server"); - - remote_sock.close(); - client_sock.close(); - - if(controlConnection != null) - try{ controlConnection.close();} catch(IOException ioe){} - - if(master_thread!=null) master_thread.interrupt(); - - pipe_thread1.interrupt(); - pipe_thread2.interrupt(); - - pipe_thread1 = null; - } - - - static private void log(String s){ - if(log != null){ - log.println(s); - log.flush(); - } - } - - private void pipe(DatagramSocket from,DatagramSocket to,boolean out) - throws IOException{ - byte[] data = new byte[datagramSize]; - DatagramPacket dp = new DatagramPacket(data,data.length); - - while(true){ - try{ - from.receive(dp); - lastReadTime = System.currentTimeMillis(); - - if(auth.checkRequest(dp,out)) - to.send(dp); - - }catch(UnknownHostException uhe){ - log("Dropping datagram for unknown host"); - }catch(InterruptedIOException iioe){ - //log("Interrupted: "+iioe); - //If we were interrupted by other thread. - if(iddleTimeout == 0) return; - - //If last datagram was received, long time ago, return. - long timeSinceRead = System.currentTimeMillis() - lastReadTime; - if(timeSinceRead >= iddleTimeout -100) //-100 for adjustment - return; - } - dp.setLength(data.length); - } - } -}
--- a/src/net/sourceforge/jsocks/UserPasswordAuthentication.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -package net.sourceforge.jsocks; - -/** - SOCKS5 User Password authentication scheme. -*/ -public class UserPasswordAuthentication implements Authentication{ - - /**SOCKS ID for User/Password authentication method*/ - public final static int METHOD_ID = 2; - - String userName, password; - byte[] request; - - /** - Create an instance of UserPasswordAuthentication. - @param userName User Name to send to SOCKS server. - @param password Password to send to SOCKS server. - */ - public UserPasswordAuthentication(String userName,String password){ - this.userName = userName; - this.password = password; - formRequest(); - } - /** Get the user name. - @return User name. - */ - public String getUser(){ - return userName; - } - /** Get password - @return Password - */ - public String getPassword(){ - return password; - } - /** - Does User/Password authentication as defined in rfc1929. - @return An array containnig in, out streams, or null if authentication - fails. - */ - public Object[] doSocksAuthentication(int methodId, - java.net.Socket proxySocket) - throws java.io.IOException{ - - if(methodId != METHOD_ID) return null; - - java.io.InputStream in = proxySocket.getInputStream(); - java.io.OutputStream out = proxySocket.getOutputStream(); - - out.write(request); - int version = in.read(); - if(version < 0) return null; //Server closed connection - int status = in.read(); - if(status != 0) return null; //Server closed connection, or auth failed. - - return new Object[] {in,out}; - } - -//Private methods -////////////////// - -/** Convert UserName password in to binary form, ready to be send to server*/ - private void formRequest(){ - byte[] user_bytes = userName.getBytes(); - byte[] password_bytes = password.getBytes(); - - request = new byte[3+user_bytes.length+password_bytes.length]; - request[0] = (byte) 1; - request[1] = (byte) user_bytes.length; - System.arraycopy(user_bytes,0,request,2,user_bytes.length); - request[2+user_bytes.length] = (byte) password_bytes.length; - System.arraycopy(password_bytes,0, - request,3+user_bytes.length,password_bytes.length); - } -}
--- a/src/net/sourceforge/jsocks/server/Ident.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -package net.sourceforge.jsocks.server; -import net.sourceforge.jsocks.*; -import java.net.*; -import java.io.*; -import java.util.StringTokenizer; - -/** - Class Ident provides means to obtain user name of the owner of the socket - on remote machine, providing remote machine runs identd daemon. - <p> - To use it: - <tt><pre> - Socket s = ss.accept(); - Ident id = new Ident(s); - if(id.successful) goUseUser(id.userName); - else handleIdentError(id.errorCode,id.errorMessage) - </pre></tt> -*/ -public class Ident{ - - /** Error Message can be null.*/ - public String errorMessage; - /** Host type as returned by daemon, can be null, if error happened*/ - public String hostType; - /** User name as returned by the identd daemon, or null, if it failed*/ - public String userName; - - /** If this is true then userName and hostType contain valid values. - Else errorCode contain the error code, and errorMessage contains - the corresponding message. - */ - public boolean successful; - /** Error code*/ - public int errorCode; - /** Identd on port 113 can't be contacted*/ - public static final int ERR_NO_CONNECT = 1; - /** Connection timed out*/ - public static final int ERR_TIMEOUT = 2; - /** Identd daemon responded with ERROR, in this case errorMessage - contains the string explanation, as send by the daemon. - */ - public static final int ERR_PROTOCOL = 3; - /** - When parsing server response protocol error happened. - */ - public static final int ERR_PROTOCOL_INCORRECT = 4; - - - /** Maximum amount of time we should wait before dropping the - connection to identd server.Setting it to 0 implies infinit - timeout. - */ - public static final int connectionTimeout = 10000; - - - /** - Constructor tries to connect to Identd daemon on the host of the - given socket, and retrieve user name of the owner of given socket - connection on remote machine. After constructor returns public - fields are initialised to whatever the server returned. - <p> - If user name was successfully retrieved successful is set to true, - and userName and hostType are set to whatever server returned. If - however for some reason user name was not obtained, successful is set - to false and errorCode contains the code explaining the reason of - failure, and errorMessage contains human readable explanation. - <p> - Constructor may block, for a while. - @param s Socket whose ownership on remote end should be obtained. - */ - public Ident(Socket s ){ - Socket sock = null; - successful = false; //We are pessimistic - - try{ - sock = new Socket(s.getInetAddress(),113); - sock.setSoTimeout(connectionTimeout); - byte[] request = (""+s.getPort()+" , "+ - s.getLocalPort()+"\r\n").getBytes(); - - sock.getOutputStream().write(request); - - BufferedReader in = new BufferedReader( - new InputStreamReader(sock.getInputStream())); - - parseResponse(in.readLine()); - - }catch(InterruptedIOException iioe){ - errorCode = ERR_TIMEOUT; - errorMessage = "Connection to identd timed out."; - }catch(ConnectException ce){ - errorCode = ERR_NO_CONNECT; - errorMessage = "Connection to identd server failed."; - - }catch(IOException ioe){ - errorCode = ERR_NO_CONNECT; - errorMessage = ""+ioe; - }finally{ - try{ if(sock!=null) sock.close();}catch(IOException ioe){}; - } - } - - private void parseResponse(String response){ - if(response == null){ - errorCode = ERR_PROTOCOL_INCORRECT; - errorMessage = "Identd server closed connection."; - return; - } - - StringTokenizer st = new StringTokenizer(response,":"); - if(st.countTokens() < 3){ - errorCode = ERR_PROTOCOL_INCORRECT; - errorMessage = "Can't parse server response."; - return; - } - - st.nextToken(); //Discard first token, it's basically what we have send - String command = st.nextToken().trim().toUpperCase(); - - if(command.equals("USERID") && st.countTokens() >= 2){ - successful = true; - hostType = st.nextToken().trim(); - userName = st.nextToken("").substring(1);//Get all that is left - }else if(command.equals("ERROR")){ - errorCode = ERR_PROTOCOL; - errorMessage = st.nextToken(); - }else{ - errorCode = ERR_PROTOCOL_INCORRECT; - System.out.println("Opa!"); - errorMessage = "Can't parse server response."; - } - - - } - -/////////////////////////////////////////////// -//USED for Testing -/* - public static void main(String[] args) throws IOException{ - - Socket s = null; - s = new Socket("gp101-16", 1391); - - Ident id = new Ident(s); - if(id.successful){ - System.out.println("User: "+id.userName); - System.out.println("HostType: "+id.hostType); - }else{ - System.out.println("ErrorCode: "+id.errorCode); - System.out.println("ErrorMessage: "+id.errorMessage); - - } - - if(s!= null) s.close(); - } -//*/ - -}
--- a/src/net/sourceforge/jsocks/server/IdentAuthenticator.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -package net.sourceforge.jsocks.server; -import net.sourceforge.jsocks.InetRange; -import net.sourceforge.jsocks.ProxyMessage; -import java.util.Hashtable; -import java.util.Vector; -import java.util.Enumeration; -import java.net.*; -import java.io.*; - -/** - An implementation of socks.ServerAuthentication which provides - simple authentication based on the host from which the connection - is made and the name of the user on the remote machine, as reported - by identd daemon on the remote machine. - <p> - It can also be used to provide authentication based only on the contacting - host address. -*/ - -public class IdentAuthenticator extends ServerAuthenticatorNone{ - /** Vector of InetRanges */ - Vector hosts; - - /** Vector of user hashes*/ - Vector users; - - String user; - - - /** - Constructs empty IdentAuthenticator. - */ - public IdentAuthenticator(){ - hosts = new Vector(); - users = new Vector(); - } - /** - Used to create instances returned from startSession. - @param in Input stream. - @param out OutputStream. - @param user Username associated with this connection,could be - null if name was not required. - */ - IdentAuthenticator(InputStream in,OutputStream out, String user){ - super(in,out); - this.user = user; - } - - /** - Adds range of addresses from which connection is allowed. Hashtable - users should contain user names as keys and anything as values - (value is not used and will be ignored). - @param hostRange Range of ip addresses from which connection is allowed. - @param users Hashtable of users for whom connection is allowed, or null - to indicate that anybody is allowed to connect from the hosts within given - range. - */ - public synchronized void add(InetRange hostRange,Hashtable users){ - this.hosts.addElement(hostRange); - this.users.addElement(users); - } - - /** - Grants permission only to those users, who connect from one of the - hosts registered with add(InetRange,Hashtable) and whose names, as - reported by identd daemon, are listed for the host the connection - came from. - */ - public ServerAuthenticator startSession(Socket s) - throws IOException{ - - int ind = getRangeIndex(s.getInetAddress()); - String user = null; - - //System.out.println("getRangeReturned:"+ind); - - if(ind < 0) return null; //Host is not on the list. - - ServerAuthenticatorNone auth = (ServerAuthenticatorNone) - super.startSession(s); - - //System.out.println("super.startSession() returned:"+auth); - if(auth == null) return null; - - //do the authentication - - Hashtable user_names = (Hashtable) users.elementAt(ind); - - if(user_names != null){ //If need to do authentication - Ident ident; - ident = new Ident(s); - //If can't obtain user name, fail - if(!ident.successful) return null; - //If user name is not listed for this address, fail - if(!user_names.containsKey(ident.userName)) return null; - user = ident.userName; - } - return new IdentAuthenticator(auth.in,auth.out,user); - - } - /** - For SOCKS5 requests allways returns true. For SOCKS4 requests - checks wether the user name supplied in the request corresponds - to the name obtained from the ident daemon. - */ - public boolean checkRequest(ProxyMessage msg,java.net.Socket s){ - //If it's version 5 request, or if anybody is permitted, return true; - if(msg.version == 5 || user == null) - return true; - - if(msg.version != 4) return false; //Who knows? - - return user.equals(msg.user); - } - - /** Get String representaion of the IdentAuthenticator.*/ - public String toString(){ - String s = ""; - - for(int i=0;i<hosts.size();++i) - s += "Range:"+hosts.elementAt(i)+"\nUsers:"+userNames(i)+"\n"; - return s; - } - -//Private Methods -////////////////// - private int getRangeIndex(InetAddress ip){ - int index = 0; - Enumeration eEnum = hosts.elements(); - while(eEnum.hasMoreElements()){ - InetRange ir = (InetRange) eEnum.nextElement(); - if(ir.contains(ip)) return index; - index++; - } - return -1; //Not found - } - - private String userNames(int i){ - if(users.elementAt(i) == null) return "Everybody is permitted."; - - Enumeration eEnum = ((Hashtable)users.elementAt(i)).keys(); - if(!eEnum.hasMoreElements()) return ""; - String s = eEnum.nextElement().toString(); - while(eEnum.hasMoreElements()) - s += "; "+eEnum.nextElement(); - - return s; - } - -}
--- a/src/net/sourceforge/jsocks/server/ServerAuthenticator.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -package net.sourceforge.jsocks.server; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.net.DatagramPacket; -import net.sourceforge.jsocks.ProxyMessage; -import net.sourceforge.jsocks.UDPEncapsulation; - -/** - Classes implementing this interface should provide socks server with - authentication and authorization of users. -**/ -public interface ServerAuthenticator{ - - /** - This method is called when a new connection accepted by the server. - <p> - At this point no data have been extracted from the connection. It is - responsibility of this method to ensure that the next byte in the - stream after this method have been called is the first byte of the - socks request message. For SOCKSv4 there is no authentication data and - the first byte in the stream is part of the request. With SOCKSv5 however - there is an authentication data first. It is expected that implementaions - will process this authentication data. - <p> - If authentication was successful an instance of ServerAuthentication - should be returned, it later will be used by the server to perform - authorization and some other things. If authentication fails null should - be returned, or an exception may be thrown. - - @param s Accepted Socket. - @return An instance of ServerAuthenticator to be used for this connection - or null - */ - ServerAuthenticator startSession(Socket s) throws IOException; - - /** - This method should return input stream which should be used on the - accepted socket. - <p> - SOCKSv5 allows to have multiple authentication methods, and these methods - might require some kind of transformations being made on the data. - <p> - This method is called on the object returned from the startSession - function. - */ - InputStream getInputStream(); - /** - This method should return output stream to use to write to the accepted - socket. - <p> - SOCKSv5 allows to have multiple authentication methods, and these methods - might require some kind of transformations being made on the data. - <p> - This method is called on the object returned from the startSession - function. - */ - OutputStream getOutputStream(); - - /** - This method should return UDPEncapsulation, which should be used - on the datagrams being send in/out. - <p> - If no transformation should be done on the datagrams, this method - should return null. - <p> - This method is called on the object returned from the startSession - function. - */ - - UDPEncapsulation getUdpEncapsulation(); - - /** - This method is called when a request have been read. - <p> - Implementation should decide wether to grant request or not. Returning - true implies granting the request, false means request should be rejected. - <p> - This method is called on the object returned from the startSession - function. - @param msg Request message. - @return true to grant request, false to reject it. - */ - boolean checkRequest(ProxyMessage msg); - - /** - This method is called when datagram is received by the server. - <p> - Implementaions should decide wether it should be forwarded or dropped. - It is expecteed that implementation will use datagram address and port - information to make a decision, as well as anything else. Address and - port of the datagram are always correspond to remote machine. It is - either destination or source address. If out is true address is destination - address, else it is a source address, address of the machine from which - datagram have been received for the client. - <p> - Implementaions should return true if the datagram is to be forwarded, and - false if the datagram should be dropped. - <p> - This method is called on the object returned from the startSession - function. - - @param out If true the datagram is being send out(from the client), - otherwise it is an incoming datagram. - @return True to forward datagram false drop it silently. - */ - boolean checkRequest(DatagramPacket dp, boolean out); - - /** - This method is called when session is completed. Either due to normal - termination or due to any error condition. - <p> - This method is called on the object returned from the startSession - function. - */ - void endSession(); -}
--- a/src/net/sourceforge/jsocks/server/ServerAuthenticatorNone.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -package net.sourceforge.jsocks.server; -import net.sourceforge.jsocks.ProxyMessage; -import net.sourceforge.jsocks.UDPEncapsulation; - -import java.io.IOException; -import java.io.InputStream; -import java.io.DataInputStream; -import java.io.OutputStream; -import java.io.PushbackInputStream; -import java.net.Socket; - -/** - An implementation of ServerAuthenticator, which does <b>not</b> do - any authentication. -<P> -<FONT size="+3" color ="FF0000"> Warning!!</font><br> Should not be -used on machines which are not behind the firewall. -<p> -It is only provided to make implementing other authentication schemes -easier.<br> -For Example: <tt><pre> - class MyAuth extends socks.server.ServerAuthenticator{ - ... - public ServerAuthenticator startSession(java.net.Socket s){ - if(!checkHost(s.getInetAddress()) return null; - return super.startSession(s); - } - - boolean checkHost(java.net.Inetaddress addr){ - boolean allow; - //Do it somehow - return allow; - } - } -</pre></tt> -*/ -public class ServerAuthenticatorNone implements ServerAuthenticator{ - - static final byte[] socks5response = {5,0}; - - InputStream in; - OutputStream out; - - /** - Creates new instance of the ServerAuthenticatorNone. - */ - public ServerAuthenticatorNone(){ - this.in = null; - this.out = null; - } - /** - Constructs new ServerAuthenticatorNone object suitable for returning - from the startSession function. - @param in Input stream to return from getInputStream method. - @param out Output stream to return from getOutputStream method. - */ - public ServerAuthenticatorNone(InputStream in, OutputStream out){ - this.in = in; - this.out = out; - } - /** - Grants access to everyone.Removes authentication related bytes from - the stream, when a SOCKS5 connection is being made, selects an - authentication NONE. - */ - public ServerAuthenticator startSession(Socket s) - throws IOException{ - - PushbackInputStream in = new PushbackInputStream(s.getInputStream()); - OutputStream out = s.getOutputStream(); - - int version = in.read(); - if(version == 5){ - if(!selectSocks5Authentication(in,out,0)) - return null; - }else if(version == 4){ - //Else it is the request message allready, version 4 - in.unread(version); - }else - return null; - - - return new ServerAuthenticatorNone(in,out); - } - - /** - Get input stream. - @return Input stream speciefied in the constructor. - */ - public InputStream getInputStream(){ - return in; - } - /** - Get output stream. - @return Output stream speciefied in the constructor. - */ - public OutputStream getOutputStream(){ - return out; - } - /** - Allways returns null. - @return null - */ - public UDPEncapsulation getUdpEncapsulation(){ - return null; - } - - /** - Allways returns true. - */ - public boolean checkRequest(ProxyMessage msg){ - return true; - } - - /** - Allways returns true. - */ - public boolean checkRequest(java.net.DatagramPacket dp, boolean out){ - return true; - } - - /** - Does nothing. - */ - public void endSession(){ - } - - /** - Convinience routine for selecting SOCKSv5 authentication. - <p> - This method reads in authentication methods that client supports, - checks wether it supports given method. If it does, the notification - method is written back to client, that this method have been chosen - for authentication. If given method was not found, authentication - failure message is send to client ([5,FF]). - @param in Input stream, version byte should be removed from the stream - before calling this method. - @param out Output stream. - @param methodId Method which should be selected. - @return true if methodId was found, false otherwise. - */ - static public boolean selectSocks5Authentication(InputStream in, - OutputStream out, - int methodId) - throws IOException{ - - int num_methods = in.read(); - if (num_methods <= 0) return false; - byte method_ids[] = new byte[num_methods]; - byte response[] = new byte[2]; - boolean found = false; - - response[0] = (byte) 5; //SOCKS version - response[1] = (byte) 0xFF; //Not found, we are pessimistic - - int bread = 0; //bytes read so far - while(bread < num_methods) - bread += in.read(method_ids,bread,num_methods-bread); - - for(int i=0;i<num_methods;++i) - if(method_ids[i] == methodId){ - found = true; - response[1] = (byte) methodId; - break; - } - - out.write(response); - return found; - } -}
--- a/src/net/sourceforge/jsocks/server/UserPasswordAuthenticator.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -package net.sourceforge.jsocks.server; - -import net.sourceforge.jsocks.ProxyMessage; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; - -/** - This class implements SOCKS5 User/Password authentication scheme as - defined in rfc1929,the server side of it. -*/ -public class UserPasswordAuthenticator extends ServerAuthenticatorNone{ - - static final int METHOD_ID = 2; - - UserValidation validator; - - /** - Construct a new UserPasswordAuthentication object, with given - UserVlaidation scheme. - - @param v UserValidation to use for validating users. - */ - public UserPasswordAuthenticator(UserValidation validator){ - this.validator = validator; - } - - public ServerAuthenticator startSession(Socket s) throws IOException{ - InputStream in = s.getInputStream(); - OutputStream out = s.getOutputStream(); - - if(in.read() != 5) return null; //Drop non version 5 messages. - - if(!selectSocks5Authentication(in,out,METHOD_ID)) - return null; - if(!doUserPasswordAuthentication(s,in,out)) - return null; - - return new ServerAuthenticatorNone(in,out); - } - - -//Private Methods -////////////////// - - private boolean doUserPasswordAuthentication(Socket s, - InputStream in, - OutputStream out) - throws IOException{ - int version = in.read(); - if(version != 1) return false; - int ulen = in.read(); - if(ulen < 0) return false; - byte[] user = new byte[ulen]; - in.read(user); - int plen = in.read(); - if(plen < 0) return false; - byte[] password = new byte[plen]; - in.read(password); - - if(validator.isUserValid(new String(user), new String(password),s)){ - //System.out.println("user valid"); - out.write(new byte[]{1,0}); - }else{ - //System.out.println("user invalid"); - out.write(new byte[]{1,1}); - return false; - } - - return true; - } -}
--- a/src/net/sourceforge/jsocks/server/UserValidation.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -package net.sourceforge.jsocks.server; - -/** - Interface which provides for user validation, based on user name - password and where it connects from. -*/ -public interface UserValidation{ - /** - Implementations of this interface are expected to use some or all - of the information provided plus any information they can extract - from other sources to decide wether given user should be allowed - access to SOCKS server, or whatever you use it for. - - @return true to indicate user is valid, false otherwise. - @param username User whom implementation should validate. - @param password Password this user provided. - @param connection Socket which user used to connect to the server. - */ - boolean isUserValid(String username,String password, - java.net.Socket connection); -}
--- a/src/org/apache/harmony/niochar/charset/additional/IBM437.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,467 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.harmony.niochar.charset.additional; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; - -/* TODO: support direct byte buffers -import org.apache.harmony.nio.AddressUtil; -import org.apache.harmony.niochar.CharsetProviderImpl; -*/ - -public class IBM437 extends Charset { - - public IBM437(String csName, String[] aliases) { - super(csName, aliases); - } - - public boolean contains(Charset cs) { - return cs.name().equalsIgnoreCase("IBM367") || cs.name().equalsIgnoreCase("IBM437") || cs.name().equalsIgnoreCase("US-ASCII") ; - } - - public CharsetDecoder newDecoder() { - return new Decoder(this); - } - - public CharsetEncoder newEncoder() { - return new Encoder(this); - } - - private static final class Decoder extends CharsetDecoder { - private Decoder(Charset cs) { - super(cs, 1, 1); - } - - private native int nDecode(char[] array, int arrPosition, int remaining, long outAddr, int absolutePos); - - - protected CoderResult decodeLoop(ByteBuffer bb, CharBuffer cb) { - int cbRemaining = cb.remaining(); - - /* TODO: support direct byte buffers - if(CharsetProviderImpl.hasLoadedNatives() && bb.isDirect() && bb.hasRemaining() && cb.hasArray()){ - int toProceed = bb.remaining(); - int cbPos = cb.position(); - int bbPos = bb.position(); - boolean throwOverflow = false; - if( cbRemaining < toProceed ) { - toProceed = cbRemaining; - throwOverflow = true; - } - int res = nDecode(cb.array(), cb.arrayOffset()+cbPos, toProceed, AddressUtil.getDirectBufferAddress(bb), bbPos); - bb.position(bbPos+res); - cb.position(cbPos+res); - if(throwOverflow) return CoderResult.OVERFLOW; - }else{ - */ - if (bb.hasArray() && cb.hasArray()) { - int rem = bb.remaining(); - rem = cbRemaining >= rem ? rem : cbRemaining; - byte[] bArr = bb.array(); - char[] cArr = cb.array(); - int bStart = bb.position(); - int cStart = cb.position(); - int i; - - for (i = bStart; i < bStart + rem; i++) { - char in = (char)(bArr[i] & 0xFF); - - if (in >= 26) { - int index = (int)in - 26; - cArr[cStart++] = (char)arr[index]; - } - else { - cArr[cStart++] = (char)(in & 0xFF); - } - } - - bb.position(i); - cb.position(cStart); - - if (rem == cbRemaining && bb.hasRemaining()) return CoderResult.OVERFLOW; - } - else { - while (bb.hasRemaining()) { - if (cbRemaining == 0) return CoderResult.OVERFLOW; - - char in = (char)(bb.get() & 0xFF); - - if (in >= 26) { - int index = (int)in - 26; - cb.put(arr[index]); - } - else { - cb.put((char)(in & 0xFF)); - } - - cbRemaining--; - } - - /* - } - */ - } - - return CoderResult.UNDERFLOW; - } - - final static char[] arr = { - 0x001C, 0x001B, 0x007F, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x001A, - 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x03BC, 0x03C4, - 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, - 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 - }; - } - - private static final class Encoder extends CharsetEncoder { - private Encoder(Charset cs) { - super(cs, 1, 1); - } - - private native void nEncode(long outAddr, int absolutePos, char[] array, int arrPosition, int[] res); - - protected CoderResult encodeLoop(CharBuffer cb, ByteBuffer bb) { - int bbRemaining = bb.remaining(); - - /* TODO: support direct byte buffers - if(CharsetProviderImpl.hasLoadedNatives() && bb.isDirect() && cb.hasRemaining() && cb.hasArray()){ - int toProceed = cb.remaining(); - int cbPos = cb.position(); - int bbPos = bb.position(); - boolean throwOverflow = false; - if( bbRemaining < toProceed ) { - toProceed = bbRemaining; - throwOverflow = true; - } - int[] res = {toProceed, 0}; - nEncode(AddressUtil.getDirectBufferAddress(bb), bbPos, cb.array(), cb.arrayOffset()+cbPos, res); - if( res[0] <= 0 ) { - bb.position(bbPos-res[0]); - cb.position(cbPos-res[0]); - if(res[1]!=0) { - if(res[1] < 0) - return CoderResult.malformedForLength(-res[1]); - else - return CoderResult.unmappableForLength(res[1]); - } - }else{ - bb.position(bbPos+res[0]); - cb.position(cbPos+res[0]); - if(throwOverflow) return CoderResult.OVERFLOW; - } - }else{ - */ - if (bb.hasArray() && cb.hasArray()) { - byte[] byteArr = bb.array(); - char[] charArr = cb.array(); - int rem = cb.remaining(); - int byteArrStart = bb.position(); - rem = bbRemaining <= rem ? bbRemaining : rem; - int x; - - for (x = cb.position(); x < cb.position() + rem; x++) { - char c = charArr[x]; - - if (c > (char)0x25A0) { - if (c >= 0xD800 && c <= 0xDFFF) { - if (x + 1 < cb.limit()) { - char c1 = charArr[x + 1]; - - if (c1 >= 0xD800 && c1 <= 0xDFFF) { - cb.position(x); bb.position(byteArrStart); - return CoderResult.unmappableForLength(2); - } - } - else { - cb.position(x); bb.position(byteArrStart); - return CoderResult.UNDERFLOW; - } - - cb.position(x); bb.position(byteArrStart); - return CoderResult.malformedForLength(1); - } - - cb.position(x); bb.position(byteArrStart); - return CoderResult.unmappableForLength(1); - } - else { - if (c < 0x1A) { - byteArr[byteArrStart++] = (byte)c; - } - else { - int index = (int)c >> 8; - index = encodeIndex[index]; - - if (index < 0) { - cb.position(x); bb.position(byteArrStart); - return CoderResult.unmappableForLength(1); - } - - index <<= 8; - index += (int)c & 0xFF; - - if ((byte)arr[index] != 0) { - byteArr[byteArrStart++] = (byte)arr[index]; - } - else { - cb.position(x); bb.position(byteArrStart); - return CoderResult.unmappableForLength(1); - } - } - } - } - - cb.position(x); - bb.position(byteArrStart); - - if (rem == bbRemaining && cb.hasRemaining()) { - return CoderResult.OVERFLOW; - } - } - else { - while (cb.hasRemaining()) { - if (bbRemaining == 0) return CoderResult.OVERFLOW; - - char c = cb.get(); - - if (c > (char)0x25A0) { - if (c >= 0xD800 && c <= 0xDFFF) { - if (cb.hasRemaining()) { - char c1 = cb.get(); - - if (c1 >= 0xD800 && c1 <= 0xDFFF) { - cb.position(cb.position() - 2); - return CoderResult.unmappableForLength(2); - } - else { - cb.position(cb.position() - 1); - } - } - else { - cb.position(cb.position() - 1); - return CoderResult.UNDERFLOW; - } - - cb.position(cb.position() - 1); - return CoderResult.malformedForLength(1); - } - - cb.position(cb.position() - 1); - return CoderResult.unmappableForLength(1); - } - else { - if (c < 0x1A) { - bb.put((byte)c); - } - else { - int index = (int)c >> 8; - index = encodeIndex[index]; - - if (index < 0) { - cb.position(cb.position() - 1); - return CoderResult.unmappableForLength(1); - } - - index <<= 8; - index += (int)c & 0xFF; - - if ((byte)arr[index] != 0) { - bb.put((byte)arr[index]); - } - else { - cb.position(cb.position() - 1); - return CoderResult.unmappableForLength(1); - } - } - - bbRemaining--; - } - } - - /* TODO: support direct byte buffers - } - */ - } - - return CoderResult.UNDERFLOW; - } - - final static char arr[] = { - - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x7F, 0x1B, 0x1A, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x1C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xAD, 0x9B, 0x9C, 0x00, 0x9D, 0x00, 0x00, 0x00, 0x00, 0xA6, 0xAE, 0xAA, 0x00, 0x00, 0x00, - 0xF8, 0xF1, 0xFD, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0xA7, 0xAF, 0xAC, 0xAB, 0x00, 0xA8, - 0x00, 0x00, 0x00, 0x00, 0x8E, 0x8F, 0x92, 0x80, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0xE1, - 0x85, 0xA0, 0x83, 0x00, 0x84, 0x86, 0x91, 0x87, 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, - 0x00, 0xA4, 0x95, 0xA2, 0x93, 0x00, 0x94, 0xF6, 0x00, 0x97, 0xA3, 0x96, 0x81, 0x00, 0x00, 0x98, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0xE8, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE0, 0x00, 0x00, 0xEB, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, - 0xE3, 0x00, 0x00, 0xE5, 0xE7, 0x00, 0xED, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xFB, 0x00, 0x00, 0x00, 0xEC, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF0, 0x00, 0x00, 0xF3, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF4, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0xC4, 0x00, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x00, 0x00, - 0xBF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xCD, 0xBA, 0xD5, 0xD6, 0xC9, 0xB8, 0xB7, 0xBB, 0xD4, 0xD3, 0xC8, 0xBE, 0xBD, 0xBC, 0xC6, 0xC7, - 0xCC, 0xB5, 0xB6, 0xB9, 0xD1, 0xD2, 0xCB, 0xCF, 0xD0, 0xCA, 0xD8, 0xD7, 0xCE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xDF, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, - 0xDE, 0xB0, 0xB1, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - final static int[] encodeIndex = { - 0, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 3, -1, 4, 5, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }; - } -}
--- a/src/org/keyczar/jce/EcCore.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,678 +0,0 @@ -/* - * Copyright 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package org.keyczar.jce; - -import java.math.BigInteger; -import java.security.spec.ECFieldFp; -import java.security.spec.ECParameterSpec; - -/** - * This class implements the basic EC operations such as point addition and - * doubling and point multiplication. Only NSA Suite B / NIST curves are - * supported. - * - * Todo: - * - Add (more) comments - Performance optimizations - Cleanup ASN.1 code, - * possibly replace with own impl - ... - * - * References: - * - * [1] Software Implementation of the NIST Elliptic Curves Over Prime Fields, M. - * Brown et al. [2] Efficient elliptic curve exponentiation using mixed - * coordinates, H. Cohen et al. [3] SEC 1: Elliptic Curve Cryptography. [4] - * Guide to Elliptic Curve Cryptography, D. Hankerson et al., Springer. - * - * @author martclau@gmail.com - * - */ -// BEGIN connectbot-changed -public final class EcCore { -// END connectbot-changed -// BEGIN connectbot-removed -// private static final long serialVersionUID = -1376116429660095993L; -// -// private static final String INFO = "Google Keyczar (EC key/parameter generation; EC signing)"; -// -// public static final String NAME = "GooKey"; -// -// @SuppressWarnings("unchecked") -// public EcCore() { -// super(NAME, 0.1, INFO); -// AccessController.doPrivileged(new PrivilegedAction<Object>() { -// @Override -// public Object run() { -// put("Signature.SHA1withECDSA", "org.keyczar.jce.EcSignatureImpl$SHA1"); -// put("Alg.Alias.Signature.ECDSA", "SHA1withDSA"); -// put("Signature.SHA256withECDSA", -// "org.keyczar.jce.EcSignatureImpl$SHA256"); -// put("Signature.SHA384withECDSA", -// "org.keyczar.jce.EcSignatureImpl$SHA384"); -// put("Signature.SHA512withECDSA", -// "org.keyczar.jce.EcSignatureImpl$SHA512"); -// put("KeyPairGenerator.EC", "org.keyczar.jce.EcKeyPairGeneratorImpl"); -// put("KeyFactory.EC", "org.keyczar.jce.EcKeyFactoryImpl"); -// put("Signature.SHA1withECDSA KeySize", "521"); -// put("Signature.SHA1withECDSA ImplementedIn", "Software"); -// put("Signature.SHA256withECDSA KeySize", "521"); -// put("Signature.SHA256withECDSA ImplementedIn", "Software"); -// put("Signature.SHA384withECDSA KeySize", "521"); -// put("Signature.SHA384withECDSA ImplementedIn", "Software"); -// put("Signature.SHA512withECDSA KeySize", "521"); -// put("Signature.SHA512withECDSA ImplementedIn", "Software"); -// put("KeyPairGenerator.EC ImplementedIn", "Software"); -// put("KeyFactory.EC ImplementedIn", "Software"); -// return null; -// } -// }); -// } -// -// private static final ECParameterSpec P192 = new ECParameterSpec( -// new EllipticCurve( -// new ECFieldFp(new BigInteger( -// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16)), -// new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", 16), -// new BigInteger("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", 16)), -// new ECPoint( -// new BigInteger("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", 16), -// new BigInteger("07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", 16)), -// new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 16), 1); -// -// private static final ECParameterSpec P224 = new ECParameterSpec( -// new EllipticCurve(new ECFieldFp(new BigInteger( -// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", 16)), -// new BigInteger( -// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", 16), -// new BigInteger( -// "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", 16)), -// new ECPoint(new BigInteger( -// "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", 16), -// new BigInteger( -// "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", 16)), -// new BigInteger( -// "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 16), 1); -// -// private static final ECParameterSpec P256 = new ECParameterSpec( -// new EllipticCurve(new ECFieldFp(new BigInteger( -// "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", -// 16)), new BigInteger( -// "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", -// 16), new BigInteger( -// "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", -// 16)), new ECPoint(new BigInteger( -// "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", -// 16), new BigInteger( -// "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", -// 16)), new BigInteger( -// "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", -// 16), 1); -// -// private static final ECParameterSpec P384 = new ECParameterSpec( -// new EllipticCurve( -// new ECFieldFp( -// new BigInteger( -// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", -// 16)), -// new BigInteger( -// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", -// 16), -// new BigInteger( -// "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", -// 16)), -// new ECPoint( -// new BigInteger( -// "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", -// 16), -// new BigInteger( -// "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", -// 16)), -// new BigInteger( -// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", -// 16), 1); -// -// private static final ECParameterSpec P521 = new ECParameterSpec( -// new EllipticCurve( -// new ECFieldFp( -// new BigInteger( -// "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", -// 16)), -// new BigInteger( -// "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", -// 16), -// new BigInteger( -// "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", -// 16)), -// new ECPoint( -// new BigInteger( -// "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", -// 16), -// new BigInteger( -// "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", -// 16)), -// new BigInteger( -// "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", -// 16), 1); -// -// public static final String EC_PARAMS_P192_OID = "1.2.840.10045.3.1.1"; -// public static final String EC_PARAMS_P224_OID = "1.3.132.0.33"; -// public static final String EC_PARAMS_P256_OID = "1.2.840.10045.3.1.7"; -// public static final String EC_PARAMS_P384_OID = "1.3.132.0.34"; -// public static final String EC_PARAMS_P521_OID = "1.3.132.0.35"; -// -// private static Map<String, ECParameterSpec> oidMap = new HashMap<String, ECParameterSpec>(); -// private static Map<ECParameterSpec, String> paramsMap = new HashMap<ECParameterSpec, String>(); -// private static Map<ECParameterSpec, String> friendlyNameMap = new HashMap<ECParameterSpec, String>(); -// -// static { -// oidMap.put(EC_PARAMS_P192_OID, P192); -// oidMap.put(EC_PARAMS_P224_OID, P224); -// oidMap.put(EC_PARAMS_P256_OID, P256); -// oidMap.put(EC_PARAMS_P384_OID, P384); -// oidMap.put(EC_PARAMS_P521_OID, P521); -// paramsMap.put(P192, EC_PARAMS_P192_OID); -// paramsMap.put(P224, EC_PARAMS_P224_OID); -// paramsMap.put(P256, EC_PARAMS_P256_OID); -// paramsMap.put(P384, EC_PARAMS_P384_OID); -// paramsMap.put(P521, EC_PARAMS_P521_OID); -// friendlyNameMap.put(P192, "P-192"); -// friendlyNameMap.put(P224, "P-224"); -// friendlyNameMap.put(P256, "P-256"); -// friendlyNameMap.put(P384, "P-384"); -// friendlyNameMap.put(P521, "P-521"); -// } -// -// public static ECParameterSpec getParams(String oid) { -// ECParameterSpec params; -// if ((params = oidMap.get(oid)) != null) return params; -// throw new IllegalArgumentException("Unsupported EC parameters: " + oid); -// } -// -// public static String getOID(ECParameterSpec params) { -// String oid; -// if ((oid = paramsMap.get(params)) != null) return oid; -// throw new IllegalArgumentException("Unsupport EC parameters"); -// } -// -// public static String getFriendlyName(ECParameterSpec params) { -// String name; -// if ((name = friendlyNameMap.get(params)) != null) return name; -// throw new IllegalArgumentException("Unsupport EC parameters"); -// } -// -// private static final BigInteger ZERO = BigInteger.ZERO; -// private static final BigInteger ONE = BigInteger.ONE; -// private static final BigInteger TWO = BigInteger.valueOf(2); -// END connectbot-removed - private static final BigInteger THREE = BigInteger.valueOf(3); -// BEGIN connectbot-removed -// private static final BigInteger FOUR = BigInteger.valueOf(4); -// private static final BigInteger EIGHT = BigInteger.valueOf(8); -// END connectbot-removed - - private static BigInteger[] doublePointA(BigInteger[] P, - ECParameterSpec params) { - final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); - final BigInteger a = params.getCurve().getA(); - - if (P[0] == null || P[1] == null) return P; - - BigInteger d = (P[0].pow(2).multiply(THREE).add(a)).multiply(P[1] - .shiftLeft(1).modInverse(p)); - BigInteger[] R = new BigInteger[2]; - R[0] = d.pow(2).subtract(P[0].shiftLeft(1)).mod(p); - R[1] = d.multiply(P[0].subtract(R[0])).subtract(P[1]).mod(p); - return R; - } - - private static BigInteger[] addPointsA(BigInteger[] P1, BigInteger[] P2, - ECParameterSpec params) { - final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); - - if (P2[0] == null || P2[1] == null) return P1; - - if (P1[0] == null || P1[1] == null) return P2; - - BigInteger d = (P2[1].subtract(P1[1])).multiply((P2[0].subtract(P1[0])) - .modInverse(p)); - BigInteger[] R = new BigInteger[2]; - R[0] = d.pow(2).subtract(P1[0]).subtract(P2[0]).mod(p); - R[1] = d.multiply(P1[0].subtract(R[0])).subtract(P1[1]).mod(p); - return R; - } - - public static BigInteger[] multiplyPointA(BigInteger[] P, BigInteger k, - ECParameterSpec params) { - BigInteger[] Q = new BigInteger[] {null, null}; - - for (int i = k.bitLength() - 1; i >= 0; i--) { - Q = doublePointA(Q, params); - - if (k.testBit(i)) Q = addPointsA(Q, P, params); - } - - return Q; - } - -// BEGIN connectbot-removed -// private static BigInteger[] doublePointJ(BigInteger[] P, -// ECParameterSpec params) { -// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); -// BigInteger A, B, C, D; -// -// if (P[2].signum() == 0) // point at inf -// return P; -// -// A = FOUR.multiply(P[0]).multiply(P[1].pow(2)).mod(p); -// B = EIGHT.multiply(P[1].pow(4)).mod(p); -// C = THREE.multiply(P[0].subtract(P[2].pow(2))).multiply( -// P[0].add(P[2].pow(2))).mod(p); -// D = C.pow(2).subtract(A.add(A)).mod(p); -// -// return new BigInteger[] { -// D, C.multiply(A.subtract(D)).subtract(B).mod(p), -// TWO.multiply(P[1]).multiply(P[2]).mod(p)}; -// } -// -// private static BigInteger[] addPointsJA(BigInteger[] P1, BigInteger[] P2, -// ECParameterSpec params) { -// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); -// BigInteger A, B, C, D; -// BigInteger X3; -// -// if (P1[2].signum() == 0) // point at inf -// return new BigInteger[] {P2[0], P2[1], ONE}; -// -// A = P2[0].multiply(P1[2].pow(2)).mod(p); -// B = P2[1].multiply(P1[2].pow(3)).mod(p); -// C = A.subtract(P1[0]).mod(p); -// D = B.subtract(P1[1]).mod(p); -// -// X3 = D.pow(2) -// .subtract(C.pow(3).add(TWO.multiply(P1[0]).multiply(C.pow(2)))).mod(p); -// return new BigInteger[] { -// X3, -// D.multiply(P1[0].multiply(C.pow(2)).subtract(X3)).subtract( -// P1[1].multiply(C.pow(3))).mod(p), P1[2].multiply(C).mod(p)}; -// } -// -// // Binary NAF method for point multiplication -// public static BigInteger[] multiplyPoint(BigInteger[] P, BigInteger k, -// ECParameterSpec params) { -// BigInteger h = THREE.multiply(k); -// -// BigInteger[] Pneg = new BigInteger[] {P[0], P[1].negate()}; -// BigInteger[] R = new BigInteger[] {P[0], P[1], ONE}; -// -// int bitLen = h.bitLength(); -// for (int i = bitLen - 2; i > 0; --i) { -// R = doublePointJ(R, params); -// if (h.testBit(i)) R = addPointsJA(R, P, params); -// if (k.testBit(i)) R = addPointsJA(R, Pneg, params); -// } -// -// // // <DEBUG> -// // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; -// // toAffine(SS, params); -// // BigInteger[] RR = multiplyPointA(P, k, params); -// // if (!SS[0].equals(RR[0]) || !SS[1].equals(RR[1])) -// // throw new RuntimeException("Internal mult error"); -// // // </DEBUG> -// -// return R; -// } - -// // Simultaneous multiple point multiplication, also known as Shamir's trick -// static BigInteger[] multiplyPoints(BigInteger[] P, BigInteger k, -// BigInteger[] Q, BigInteger l, ECParameterSpec params) { -// BigInteger[] PQ = addPointsA(P, Q, params); -// BigInteger[] R = new BigInteger[] {null, null, ZERO}; -// -// int max = Math.max(k.bitLength(), l.bitLength()); -// for (int i = max - 1; i >= 0; --i) { -// R = doublePointJ(R, params); -// if (k.testBit(i)) { -// if (l.testBit(i)) -// R = addPointsJA(R, PQ, params); -// else -// R = addPointsJA(R, P, params); -// } else if (l.testBit(i)) R = addPointsJA(R, Q, params); -// } -// -// // // <DEBUG> -// // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; -// // toAffine(SS, params); -// // BigInteger[] AA = multiplyPointA(P, k, params); -// // BigInteger[] BB = multiplyPointA(Q, l, params); -// // BigInteger[] AB = addPointsA(AA, BB, params); -// // if (!SS[0].equals(AB[0]) || !SS[1].equals(AB[1])) -// // throw new RuntimeException("Internal mult error"); -// // // </DEBUG> -// -// return R; -// } -// -// // SEC 1, 2.3.5 -// static byte[] fieldElemToBytes(BigInteger a, ECParameterSpec params) { -// int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; -// byte[] bytes = a.toByteArray(); -// if (len < bytes.length) { -// byte[] tmp = new byte[len]; -// System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length); -// return tmp; -// } else if (len > bytes.length) { -// byte[] tmp = new byte[len]; -// System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length); -// return tmp; -// } -// return bytes; -// } -// -// static int fieldElemToBytes(BigInteger a, ECParameterSpec params, -// byte[] data, int off) { -// int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; -// byte[] bytes = a.toByteArray(); -// if (len < bytes.length) { -// System.arraycopy(bytes, bytes.length - len, data, off, len); -// return len; -// } else if (len > bytes.length) { -// System.arraycopy(bytes, 0, data, len - bytes.length + off, bytes.length); -// return len; -// } -// System.arraycopy(bytes, 0, data, off, bytes.length); -// return bytes.length; -// } -// -// // SEC 1, 2.3.3 -// static byte[] ecPointToBytes(ECPoint a, ECParameterSpec params) { -// byte[] fe1 = fieldElemToBytes(a.getAffineX(), params); -// byte[] fe2 = fieldElemToBytes(a.getAffineY(), params); -// byte[] bytes = new byte[1 + fe1.length + fe2.length]; -// bytes[0] = 0x04; -// System.arraycopy(fe1, 0, bytes, 1, fe1.length); -// System.arraycopy(fe2, 0, bytes, 1 + fe1.length, fe2.length); -// return bytes; -// } -// -// // SEC 1, 2.3.4 -// static ECPoint bytesToECPoint(byte[] bytes, ECParameterSpec params) { -// switch (bytes[0]) { -// case 0x00: // point at inf -// throw new IllegalArgumentException( -// "Point at infinity is not a valid argument"); -// case 0x02: // point compression -// case 0x03: -// throw new UnsupportedOperationException( -// "Point compression is not supported"); -// case 0x04: -// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); -// byte[] fe = new byte[(p.bitLength() + 7) / 8]; -// System.arraycopy(bytes, 1, fe, 0, fe.length); -// BigInteger x = new BigInteger(1, fe); -// System.arraycopy(bytes, 1 + fe.length, fe, 0, fe.length); -// return new ECPoint(x, new BigInteger(1, fe)); -// default: -// throw new IllegalArgumentException("Invalid point encoding"); -// } -// } -// -// // Convert Jacobian point to affine -// static void toAffine(BigInteger[] P, ECParameterSpec params) { -// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); -// P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); -// P[1] = P[1].multiply(P[2].pow(3).modInverse(p)).mod(p); -// } -// -// static void toAffineX(BigInteger[] P, ECParameterSpec params) { -// final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); -// P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); -// } -// -// static BigInteger[] internalPoint(ECPoint P) { -// return new BigInteger[] {P.getAffineX(), P.getAffineY()}; -// } -// -// // private static void printPerf(String msg, long start, long stop) { -// // String unit = "ms"; -// // long diff = stop - start; -// // if (diff > 1000) { -// // diff /= 1000; -// // unit = "s"; -// // } -// // System.out.printf("%s: %d %s\n", msg, diff, unit); -// // } -// -// public static void main(String[] args) throws Exception { -// -// Security.insertProviderAt(new EcCore(), 0); -// -// // ---- -// // Test primitives -// // ---- -// -// // GooKey EC private key, 256 bit -// // Private value: -// // a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2 -// // Parameters: P-256 (1.2.840.10045.3.1.7) -// // GooKey EC public key, 256 bit -// // Public value (x coordinate): -// // 86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c -// // Public value (y coordinate): -// // ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6 -// // Parameters: P-256 (1.2.840.10045.3.1.7) -// // GooKey EC private key, 256 bit -// // Private value: -// // b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022 -// // Parameters: P-256 (1.2.840.10045.3.1.7) -// // GooKey EC public key, 256 bit -// // Public value (x coordinate): -// // 61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1 -// // Public value (y coordinate): -// // 3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705 -// // Parameters: P-256 (1.2.840.10045.3.1.7) -// -// // P = kG -// BigInteger k = new BigInteger( -// "a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2", 16); -// BigInteger[] P = new BigInteger[] { -// new BigInteger( -// "86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c", -// 16), -// new BigInteger( -// "ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6", -// 16), ONE}; -// -// // Q = lG -// BigInteger l = new BigInteger( -// "b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022", 16); -// BigInteger[] Q = new BigInteger[] { -// new BigInteger( -// "61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1", -// 16), -// new BigInteger( -// "3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705", -// 16), ONE}; -// -// // Known answer for P+Q -// BigInteger[] kat1 = new BigInteger[] { -// new BigInteger( -// "bc7adb05bca2460bbfeb4e0f88b61c384ea88ed3fd56017938ac2582513d4220", -// 16), -// new BigInteger( -// "a640a43df2e9df39eec11445b7e3f7835b743ef1ac4a83cecb570a060b3f1c6c", -// 16)}; -// -// BigInteger[] R = addPointsA(P, Q, P256); -// if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) -// throw new RuntimeException("kat1 failed"); -// -// R = addPointsJA(P, Q, P256); -// toAffine(R, P256); -// if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) -// throw new RuntimeException("kat1 failed"); -// -// -// // Known answer for Q+Q -// BigInteger[] kat2 = new BigInteger[] { -// new BigInteger( -// "c79d7f9100c14a70f0bb9bdce59654abf99e10d1ac5afc1a0f1b6bc650d6429b", -// 16), -// new BigInteger( -// "6856814e47adce42bc0d7c3bef308c6c737c418ed093effb31e21f53c7735c97", -// 16)}; -// -// R = doublePointA(P, P256); -// if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) -// throw new RuntimeException("kat2 failed"); -// -// R = doublePointJ(P, P256); -// toAffine(R, P256); -// if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) -// throw new RuntimeException("kat2 failed"); -// -// // Known answer for kP -// BigInteger[] kat3 = new BigInteger[] { -// new BigInteger( -// "97a82a834b9e6b50660ae30d43dac9b200276e8bcd2ed6a6593048de09276d1a", -// 16), -// new BigInteger( -// "30a9590a01066d8ef54a910afcc8648dbc7400c01750af423ce95547f2154d56", -// 16)}; -// -// R = multiplyPointA(P, k, P256); -// if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) -// throw new RuntimeException("kat3 failed"); -// -// R = multiplyPoint(P, k, P256); -// toAffine(R, P256); -// if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) -// throw new RuntimeException("kat3 failed"); -// -// // Known answer for kP+lQ -// BigInteger[] kat4 = new BigInteger[] { -// new BigInteger( -// "6fd51be5cf3d6a6bcb62594bbe41ccf549b37d8fefff6e293a5bea0836efcfc6", -// 16), -// new BigInteger( -// "9bc21a930137aa3814908974c431e4545a05dce61321253c337f3883129c42ca", -// 16)}; -// -// BigInteger[] RR = multiplyPointA(Q, l, P256); -// R = addPointsA(R, RR, P256); -// if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) -// throw new RuntimeException("kat4 failed"); -// -// R = multiplyPoints(P, k, Q, l, P256); -// toAffine(R, P256); -// if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) -// throw new RuntimeException("kat4 failed"); -// -// // ---- -// // Test ECDSA in various combinations -// // ---- -// -// Provider gooProv = Security.getProvider("GooKey"); -// Provider nssProv = Security.getProvider("SunPKCS11-NSS"); -// -// // Number of iterations: trust me, this is a (stress) good test -// // and does provoke bugs in a fuzzing way. -// int iter = 50; -// -// // Iterate over all key lengths and signature schemes. -// int[] keyLengths = {192, 224, 256, 384, 521}; -// String[] ecdsas = { -// "SHA1withECDSA", "SHA256withECDSA", "SHA384withECDSA", -// "SHA512withECDSA"}; -// for (int s = 0; s < ecdsas.length; s++) { -// System.out.println("Signature scheme " + ecdsas[s]); -// for (int i = 0; i < keyLengths.length; i++) { -// System.out.print("Testing P-" + keyLengths[i] + ": "); -// for (int n = 0; n < iter; n++) { -// System.out.print("."); -// -// KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", gooProv); -// kpGen.initialize(keyLengths[i]); -// KeyPair ecKeyPair = kpGen.generateKeyPair(); -// -// ECPrivateKey ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); -// byte[] tmp = ecPrivKey.getEncoded(); -// KeyFactory keyFab = KeyFactory.getInstance("EC", gooProv); -// keyFab.generatePrivate(new PKCS8EncodedKeySpec(tmp)); -// ECPrivateKeySpec ecPrivSpec = new ECPrivateKeySpec(ecPrivKey.getS(), -// ecPrivKey.getParams()); -// keyFab.generatePrivate(ecPrivSpec); -// -// ECPublicKey ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); -// tmp = ecPubKey.getEncoded(); // dont modify tmp now - is used below -// keyFab.generatePublic(new X509EncodedKeySpec(tmp)); -// ECPublicKeySpec ecPubSpec = new ECPublicKeySpec(ecPubKey.getW(), -// ecPubKey.getParams()); -// keyFab.generatePublic(ecPubSpec); -// -// Signature ecdsa = Signature.getInstance(ecdsas[s], gooProv); -// ecdsa.initSign(ecPrivKey); -// ecdsa.update(tmp); -// byte[] sig = ecdsa.sign(); -// ecdsa.initVerify(ecPubKey); -// ecdsa.update(tmp); -// if (!ecdsa.verify(sig)) -// throw new RuntimeException("Signature not verified: " -// + keyLengths[i]); -// -// // Cross verify using NSS if present -// if (nssProv != null) { -// keyFab = KeyFactory.getInstance("EC", nssProv); -// -// // For some reason NSS doesnt seem to work for P-192 and P-224?! -// if (keyLengths[i] == 192 || keyLengths[i] == 224) continue; -// -// ECPrivateKey nssPrivKey = (ECPrivateKey) keyFab -// .generatePrivate(new PKCS8EncodedKeySpec(ecPrivKey.getEncoded())); -// ECPublicKey nssPubKey = (ECPublicKey) keyFab -// .generatePublic(new X509EncodedKeySpec(ecPubKey.getEncoded())); -// -// ecdsa = Signature.getInstance(ecdsas[s], nssProv); -// ecdsa.initVerify(nssPubKey); -// ecdsa.update(tmp); -// if (!ecdsa.verify(sig)) -// throw new RuntimeException("Signature not verified 2: " -// + keyLengths[i]); -// -// ecdsa.initSign(nssPrivKey); -// ecdsa.update(tmp); -// sig = ecdsa.sign(); -// ecdsa = Signature.getInstance(ecdsas[s], gooProv); -// ecdsa.initVerify(ecPubKey); -// ecdsa.update(tmp); -// if (!ecdsa.verify(sig)) -// throw new RuntimeException("Signature not verified 3: " -// + keyLengths[i]); -// } -// } -// System.out.println(" done"); -// } -// } -// -// // Test Keyczar integration -// // Signer ecdsaSigner = new Signer("c:\\temp\\eckeyset"); -// // String tbs = "Sign this"; -// // String sig = ecdsaSigner.sign(tbs); -// // if (ecdsaSigner.verify(sig, tbs)) -// // System.out.println("Keyczar EC OK"); -// // else -// // System.out.println("Keyczar EC not OK"); -// } -//END connectbot-removed -}
--- a/src/org/openintents/intents/FileManagerIntents.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2008 OpenIntents.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openintents.intents; - -// Version Dec 9, 2008 - - -/** - * Provides OpenIntents actions, extras, and categories used by providers. - * <p>These specifiers extend the standard Android specifiers.</p> - */ -public final class FileManagerIntents { - - /** - * Activity Action: Pick a file through the file manager, or let user - * specify a custom file name. - * Data is the current file name or file name suggestion. - * Returns a new file name as file URI in data. - * - * <p>Constant Value: "org.openintents.action.PICK_FILE"</p> - */ - public static final String ACTION_PICK_FILE = "org.openintents.action.PICK_FILE"; - - /** - * Activity Action: Pick a directory through the file manager, or let user - * specify a custom file name. - * Data is the current directory name or directory name suggestion. - * Returns a new directory name as file URI in data. - * - * <p>Constant Value: "org.openintents.action.PICK_DIRECTORY"</p> - */ - public static final String ACTION_PICK_DIRECTORY = "org.openintents.action.PICK_DIRECTORY"; - - /** - * The title to display. - * - * <p>This is shown in the title bar of the file manager.</p> - * - * <p>Constant Value: "org.openintents.extra.TITLE"</p> - */ - public static final String EXTRA_TITLE = "org.openintents.extra.TITLE"; - - /** - * The text on the button to display. - * - * <p>Depending on the use, it makes sense to set this to "Open" or "Save".</p> - * - * <p>Constant Value: "org.openintents.extra.BUTTON_TEXT"</p> - */ - public static final String EXTRA_BUTTON_TEXT = "org.openintents.extra.BUTTON_TEXT"; - -}
--- a/src/org/tn5250j/TN5250jConstants.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,590 +0,0 @@ -/* - * @(#)TN5250jConstants.java - * Copyright: Copyright (c) 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ - -package org.tn5250j; -import java.util.HashMap; - -public class TN5250jConstants { - - // Version information - public static final String tn5250jRelease = "0"; - public static final String tn5250jVersion = ".7"; - public static final String tn5250jSubVer = ".4"; - - public static final String VERSION_INFO = tn5250jRelease + tn5250jVersion + tn5250jSubVer; - - // STATE - static final int STATE_DISCONNECTED = 0; - static final int STATE_CONNECTED = 1; - static final int STATE_REMOVE = 2; - - // SESSION Level key value pairs - public static final String SESSION_HOST = "SESSION_HOST"; - public static final String SESSION_HOST_PORT = "SESSION_HOST_PORT"; - public static final String SESSION_CONFIG_RESOURCE = "SESSION_CONFIG_RESOURCE"; - public static final String SESSION_TYPE = "SESSION_HOST_TYPE"; - public static final String SESSION_TN_ENHANCED = "SESSION_TN_ENHANCED"; - public static final String SESSION_SCREEN_SIZE = "SESSION_SCREEN_SIZE"; - public static final String SESSION_CODE_PAGE = "SESSION_CODE_PAGE"; - public static final String SESSION_PROXY_HOST = "SESSION_PROXY_HOST"; - public static final String SESSION_PROXY_PORT = "SESSION_PROXY_PORT"; - public static final String SESSION_USE_GUI = "SESSION_USE_GUI"; - public static final String SESSION_DEVICE_NAME = "SESSION_DEVICE_NAME"; - public static final String SESSION_NAMES_REFS = "SESSION_NAMES_REFS"; - public static final String SESSION_LOCALE = "SESSION_LOCALE"; - public static final String SESSION_CONFIG_FILE = "SESSION_CONFIG_FILE"; - public static final String SESSION_TERM_NAME_SYSTEM = "SESSION_TERM_NAME_SYSTEM"; - public static final String SESSION_TERM_NAME = "SESSION_TERM_NAME"; - public static final String SESSION_IS_APPLET = "SESSION_IS_APPLET"; - public static final String SESSION_HEART_BEAT = "SESSION_KEEP_ALIVE_ENABLED"; - -// public static final String GUI_MDI_TYPE = "GUI_MDI_TYPE"; - public static final String GUI_FRAME_WIDTH = "GUI_FRAME_WIDTH"; - public static final String GUI_FRAME_HEIGHT = "GUI_FRAME_HEIGHT"; - public static final String GUI_NO_TAB = "GUI_NO_TAB"; - public static final String NO_CHECK_RUNNING = "NO_CHECK_RUNNING"; - public static final String START_MONITOR_THREAD = "START_MONITOR_THREAD"; - -// public static final String SSL_TYPE = "TN5250J_SSL_TYPE"; - public static final String SSL_TYPE = "-sslType"; - public static final String SSL_TYPE_NONE = "NONE"; - public static final String SSL_TYPE_SSLv2 = "SSLv2"; - public static final String SSL_TYPE_SSLv3 = "SSLv3"; - public static final String SSL_TYPE_TLS = "TLS"; - - public static final String[] SSL_TYPES = {SSL_TYPE_NONE, - SSL_TYPE_SSLv2, - SSL_TYPE_SSLv3, - SSL_TYPE_TLS - }; - - // Session JUMP Directions - static final int JUMP_PREVIOUS = 0; - static final int JUMP_NEXT = 1; - -// // OS_OHIO_SESSION_TYPE type of sessions -// public static final String OS_OHIO_SESSION_TYPE_5250_STR = "2"; - - // SCREEN_SIZE Size of screen string - public static final String SCREEN_SIZE_24X80_STR = "0"; - public static final String SCREEN_SIZE_27X132_STR = "1"; - - // SCREEN_SIZE Size of screen int - public static final int SCREEN_SIZE_24X80 = 0; - public static final int SCREEN_SIZE_27X132 = 1; - - public static final int NUM_PARMS = 20; - - // mnemonic value constants - public static final int BACK_SPACE = 1001; - public static final int BACK_TAB = 1002; - public static final int UP = 1003; - public static final int DOWN = 1004; - public static final int LEFT = 1005; - public static final int RIGHT = 1006; - public static final int DELETE = 1007; - public static final int TAB = 1008; - public static final int EOF = 1009; - public static final int ERASE_EOF = 1010; - public static final int ERASE_FIELD = 1011; - public static final int INSERT = 1012; - public static final int HOME = 1013; - public static final int KEYPAD_0 = 1014; - public static final int KEYPAD_1 = 1015; - public static final int KEYPAD_2 = 1016; - public static final int KEYPAD_3 = 1017; - public static final int KEYPAD_4 = 1018; - public static final int KEYPAD_5 = 1019; - public static final int KEYPAD_6 = 1020; - public static final int KEYPAD_7 = 1021; - public static final int KEYPAD_8 = 1022; - public static final int KEYPAD_9 = 1023; - public static final int KEYPAD_PERIOD = 1024; - public static final int KEYPAD_COMMA = 1025; - public static final int KEYPAD_MINUS = 1026; - public static final int FIELD_EXIT = 1027; - public static final int FIELD_PLUS = 1028; - public static final int FIELD_MINUS = 1029; - public static final int BOF = 1030; - public static final int SYSREQ = 1031; - public static final int RESET = 1032; - public static final int NEXTWORD = 1033; - public static final int PREVWORD = 1034; - public static final int COPY = 1035; - public static final int PASTE = 1036; - public static final int ATTN = 1037; - public static final int MARK_UP = 1038; - public static final int MARK_DOWN = 1039; - public static final int MARK_LEFT = 1040; - public static final int MARK_RIGHT = 1041; - public static final int DUP_FIELD = 1042; - public static final int NEW_LINE = 1043; - public static final int JUMP_NEXT_SESS = 5000; - public static final int JUMP_PREV_SESS = 5001; - public static final int OPEN_NEW = 5002; - public static final int TOGGLE_CONNECTION = 5003; - public static final int HOTSPOTS = 5004; - public static final int GUI = 5005; - public static final int DSP_MSGS = 5006; - public static final int DSP_ATTRIBUTES = 5007; - public static final int PRINT_SCREEN = 5008; - public static final int CURSOR = 5009; - public static final int DEBUG = 5010; - public static final int CLOSE = 5011; - public static final int TRANSFER = 5012; - public static final int E_MAIL = 5013; - public static final int RUN_SCRIPT = 5014; - public static final int SPOOL_FILE = 5015; - public static final int QUICK_MAIL = 5016; - public static final int OPEN_SAME = 5017; - public static final int FAST_CURSOR_DOWN = 5018; - public static final int FAST_CURSOR_UP = 5019; - public static final int FAST_CURSOR_RIGHT = 5020; - public static final int FAST_CURSOR_LEFT = 5021; - - // PF Keys - public static final int PF1 = 0x31; - public static final int PF2 = 0x32; - public static final int PF3 = 0x33; - public static final int PF4 = 0x34; - public static final int PF5 = 0x35; - public static final int PF6 = 0x36; - public static final int PF7 = 0x37; - public static final int PF8 = 0x38; - public static final int PF9 = 0x39; - public static final int PF10 = 0x3A; - public static final int PF11 = 0x3B; - public static final int PF12 = 0x3C; - public static final int PF13 = 0xB1; - public static final int PF14 = 0xB2; - public static final int PF15 = 0xB3; - public static final int PF16 = 0xB4; - public static final int PF17 = 0xB5; - public static final int PF18 = 0xB6; - public static final int PF19 = 0xB7; - public static final int PF20 = 0xB8; - public static final int PF21 = 0xB9; - public static final int PF22 = 0xBA; - public static final int PF23 = 0xBB; - public static final int PF24 = 0xBC; - - public static final HashMap<String, Integer> mnemonicMap = new HashMap<String, Integer>(); - static { - mnemonicMap.put("[backspace]", 1001); - mnemonicMap.put("[backtab]", 1002); - mnemonicMap.put("[up]", 1003); - mnemonicMap.put("[down]", 1004); - mnemonicMap.put("[left]", 1005); - mnemonicMap.put("[right]", 1006); - mnemonicMap.put("[delete]", 1007); - mnemonicMap.put("[tab]", 1008); - mnemonicMap.put("[eof]", 1009); - mnemonicMap.put("[eraseeof]", 1010); - mnemonicMap.put("[erasefld]", 1011); - mnemonicMap.put("[insert]", 1012); - mnemonicMap.put("[home]", 1013); - mnemonicMap.put("[keypad0]", 1014); - mnemonicMap.put("[keypad1]", 1015); - mnemonicMap.put("[keypad2]", 1016); - mnemonicMap.put("[keypad3]", 1017); - mnemonicMap.put("[keypad4]", 1018); - mnemonicMap.put("[keypad5]", 1019); - mnemonicMap.put("[keypad6]", 1020); - mnemonicMap.put("[keypad7]", 1021); - mnemonicMap.put("[keypad8]", 1022); - mnemonicMap.put("[keypad9]", 1023); - mnemonicMap.put("[keypad.]", 1024); - mnemonicMap.put("[keypad,]", 1025); - mnemonicMap.put("[keypad-]", 1026); - mnemonicMap.put("[fldext]", 1027); - mnemonicMap.put("[field+]", 1028); - mnemonicMap.put("[field-]", 1029); - mnemonicMap.put("[bof]", 1030); - mnemonicMap.put("[enter]", 0xF1); - mnemonicMap.put("[pf1]", 0x31); - mnemonicMap.put("[pf2]", 0x32); - mnemonicMap.put("[pf3]", 0x33); - mnemonicMap.put("[pf4]", 0x34); - mnemonicMap.put("[pf5]", 0x35); - mnemonicMap.put("[pf6]", 0x36); - mnemonicMap.put("[pf7]", 0x37); - mnemonicMap.put("[pf8]", 0x38); - mnemonicMap.put("[pf9]", 0x39); - mnemonicMap.put("[pf10]", 0x3A); - mnemonicMap.put("[pf11]", 0x3B); - mnemonicMap.put("[pf12]", 0x3C); - mnemonicMap.put("[pf13]", 0xB1); - mnemonicMap.put("[pf14]", 0xB2); - mnemonicMap.put("[pf15]", 0xB3); - mnemonicMap.put("[pf16]", 0xB4); - mnemonicMap.put("[pf17]", 0xB5); - mnemonicMap.put("[pf18]", 0xB6); - mnemonicMap.put("[pf19]", 0xB7); - mnemonicMap.put("[pf20]", 0xB8); - mnemonicMap.put("[pf21]", 0xB9); - mnemonicMap.put("[pf22]", 0xBA); - mnemonicMap.put("[pf23]", 0xBB); - mnemonicMap.put("[pf24]", 0xBC); - mnemonicMap.put("[clear]", 0xBD); - mnemonicMap.put("[help]", 0xF3); - mnemonicMap.put("[pgup]", 0xF4); - mnemonicMap.put("[pgdown]", 0xF5); - mnemonicMap.put("[rollleft]", 0xD9); - mnemonicMap.put("[rollright]", 0xDA); - mnemonicMap.put("[hostprint]", 0xF6); - mnemonicMap.put("[pa1]", 0x6C); - mnemonicMap.put("[pa2]", 0x6E); - mnemonicMap.put("[pa3]", 0x6B); - mnemonicMap.put("[sysreq]", 1031); - mnemonicMap.put("[reset]", 1032); - mnemonicMap.put("[nextword]", 1033); - mnemonicMap.put("[prevword]", 1034); - mnemonicMap.put("[copy]", 1035); - mnemonicMap.put("[paste]", 1036); - mnemonicMap.put("[attn]", 1037); - mnemonicMap.put("[markup]", 1038); - mnemonicMap.put("[markdown]", 1039); - mnemonicMap.put("[markleft]", 1040); - mnemonicMap.put("[markright]", 1041); - mnemonicMap.put("[dupfield]", 1042); - mnemonicMap.put("[newline]", 1043); - mnemonicMap.put("[jumpnext]", 5000); - mnemonicMap.put("[jumpprev]", 5001); - mnemonicMap.put("[opennew]", 5002); - mnemonicMap.put("[togcon]", 5003); - mnemonicMap.put("[hotspots]", 5004); - mnemonicMap.put("[gui]", 5005); - mnemonicMap.put("[dspmsgs]", 5006); - mnemonicMap.put("[dspattr]", 5007); - mnemonicMap.put("[print]", 5008); - mnemonicMap.put("[cursor]", 5009); - mnemonicMap.put("[debug]", 5010); - mnemonicMap.put("[close]", 5011); - mnemonicMap.put("[transfer]", 5012); - mnemonicMap.put("[e-mail]", 5013); - mnemonicMap.put("[runscript]", 5014); - mnemonicMap.put("[spoolfile]", 5015); - mnemonicMap.put("[quick-mail]", 5016); - mnemonicMap.put("[open-same]", 5017); - mnemonicMap.put("[fastcursordown]", 5018); - mnemonicMap.put("[fastcursorup]", 5019); - mnemonicMap.put("[fastcursorright]", 5020); - mnemonicMap.put("[fastcursorleft]", 5021); - }; - - public static final String MNEMONIC_CLEAR = "[clear]"; - public static final String MNEMONIC_ENTER = "[enter]"; - public static final String MNEMONIC_HELP = "[help]"; - public static final String MNEMONIC_PAGE_DOWN = "[pgdown]"; - public static final String MNEMONIC_PAGE_UP = "[pgup]"; - public static final String MNEMONIC_PRINT = "[hostprint]"; - public static final String MNEMONIC_PF1 = "[pf1]"; - public static final String MNEMONIC_PF2 = "[pf2]"; - public static final String MNEMONIC_PF3 = "[pf3]"; - public static final String MNEMONIC_PF4 = "[pf4]"; - public static final String MNEMONIC_PF5 = "[pf5]"; - public static final String MNEMONIC_PF6 = "[pf6]"; - public static final String MNEMONIC_PF7 = "[pf7]"; - public static final String MNEMONIC_PF8 = "[pf8]"; - public static final String MNEMONIC_PF9 = "[pf9]"; - public static final String MNEMONIC_PF10 = "[pf10]"; - public static final String MNEMONIC_PF11 = "[pf11]"; - public static final String MNEMONIC_PF12 = "[pf12]"; - public static final String MNEMONIC_PF13 = "[pf13]"; - public static final String MNEMONIC_PF14 = "[pf14]"; - public static final String MNEMONIC_PF15 = "[pf15]"; - public static final String MNEMONIC_PF16 = "[pf16]"; - public static final String MNEMONIC_PF17 = "[pf17]"; - public static final String MNEMONIC_PF18 = "[pf18]"; - public static final String MNEMONIC_PF19 = "[pf19]"; - public static final String MNEMONIC_PF20 = "[pf20]"; - public static final String MNEMONIC_PF21 = "[pf21]"; - public static final String MNEMONIC_PF22 = "[pf22]"; - public static final String MNEMONIC_PF23 = "[pf23]"; - public static final String MNEMONIC_PF24 = "[pf24]"; - public static final String MNEMONIC_BACK_SPACE = "[backspace]"; - public static final String MNEMONIC_BACK_TAB = "[backtab]"; - public static final String MNEMONIC_UP = "[up]"; - public static final String MNEMONIC_DOWN = "[down]"; - public static final String MNEMONIC_LEFT = "[left]"; - public static final String MNEMONIC_RIGHT = "[right]"; - public static final String MNEMONIC_DELETE = "[delete]"; - public static final String MNEMONIC_TAB = "[tab]"; - public static final String MNEMONIC_END_OF_FIELD = "[eof]"; - public static final String MNEMONIC_ERASE_EOF = "[eraseeof]"; - public static final String MNEMONIC_ERASE_FIELD = "[erasefld]"; - public static final String MNEMONIC_INSERT = "[insert]"; - public static final String MNEMONIC_HOME = "[home]"; - public static final String MNEMONIC_KEYPAD0 = "[keypad0]"; - public static final String MNEMONIC_KEYPAD1 = "[keypad1]"; - public static final String MNEMONIC_KEYPAD2 = "[keypad2]"; - public static final String MNEMONIC_KEYPAD3 = "[keypad3]"; - public static final String MNEMONIC_KEYPAD4 = "[keypad4]"; - public static final String MNEMONIC_KEYPAD5 = "[keypad5]"; - public static final String MNEMONIC_KEYPAD6 = "[keypad6]"; - public static final String MNEMONIC_KEYPAD7 = "[keypad7]"; - public static final String MNEMONIC_KEYPAD8 = "[keypad8]"; - public static final String MNEMONIC_KEYPAD9 = "[keypad9]"; - public static final String MNEMONIC_KEYPAD_PERIOD = "[keypad.]"; - public static final String MNEMONIC_KEYPAD_COMMA = "[keypad,]"; - public static final String MNEMONIC_KEYPAD_MINUS = "[keypad-]"; - public static final String MNEMONIC_FIELD_EXIT = "[fldext]"; - public static final String MNEMONIC_FIELD_PLUS = "[field+]"; - public static final String MNEMONIC_FIELD_MINUS = "[field-]"; - public static final String MNEMONIC_BEGIN_OF_FIELD = "[bof]"; - public static final String MNEMONIC_PA1 = "[pa1]"; - public static final String MNEMONIC_PA2 = "[pa2]"; - public static final String MNEMONIC_PA3 = "[pa3]"; - public static final String MNEMONIC_SYSREQ = "[sysreq]"; - public static final String MNEMONIC_RESET = "[reset]"; - public static final String MNEMONIC_NEXTWORD = "[nextword]"; - public static final String MNEMONIC_PREVWORD = "[prevword]"; - public static final String MNEMONIC_ATTN = "[attn]"; - public static final String MNEMONIC_MARK_LEFT = "[markleft]"; - public static final String MNEMONIC_MARK_RIGHT = "[markright]"; - public static final String MNEMONIC_MARK_UP = "[markup]"; - public static final String MNEMONIC_MARK_DOWN = "[markdown]"; - public static final String MNEMONIC_DUP_FIELD = "[dupfield]"; - public static final String MNEMONIC_NEW_LINE = "[newline]"; - public static final String MNEMONIC_JUMP_NEXT = "[jumpnext]"; - public static final String MNEMONIC_JUMP_PREV = "[jumpprev]"; - public static final String MNEMONIC_OPEN_NEW = "[opennew]"; - public static final String MNEMONIC_TOGGLE_CONNECTION = "[togcon]"; - public static final String MNEMONIC_HOTSPOTS = "[hotspots]"; - public static final String MNEMONIC_GUI = "[gui]"; - public static final String MNEMONIC_DISP_MESSAGES = "[dspmsgs]"; - public static final String MNEMONIC_DISP_ATTRIBUTES = "[dspattr]"; - public static final String MNEMONIC_PRINT_SCREEN = "[print]"; - public static final String MNEMONIC_CURSOR = "[cursor]"; - public static final String MNEMONIC_DEBUG = "[debug]"; - public static final String MNEMONIC_CLOSE = "[close]"; - public static final String MNEMONIC_E_MAIL = "[e-mail]"; - public static final String MNEMONIC_COPY = "[copy]"; - public static final String MNEMONIC_PASTE = "[paste]"; - public static final String MNEMONIC_FILE_TRANSFER = "[transfer]"; - public static final String MNEMONIC_RUN_SCRIPT = "[runscript]"; - public static final String MNEMONIC_SPOOL_FILE = "[spoolfile]"; - public static final String MNEMONIC_QUICK_MAIL = "[quick-mail]"; - public static final String MNEMONIC_OPEN_SAME = "[open-same]"; - public static final String MNEMONIC_FAST_CURSOR_DOWN = "[fastcursordown]"; - public static final String MNEMONIC_FAST_CURSOR_UP = "[fastcursorup]"; - public static final String MNEMONIC_FAST_CURSOR_RIGHT = "[fastcursorright]"; - public static final String MNEMONIC_FAST_CURSOR_LEFT = "[fastcursorleft]"; - - // AID-Generating Keys - public static final int AID_CLEAR = 0xBD; - public static final int AID_ENTER = 0xF1; - public static final int AID_HELP = 0xF3; - public static final int AID_ROLL_UP = 0xF4; - public static final int AID_ROLL_DOWN = 0xF5; - public static final int AID_ROLL_LEFT = 0xD9; - public static final int AID_ROLL_RIGHT = 0xDA; - public static final int AID_PRINT = 0xF6; - public static final int AID_PF1 = 0x31; - public static final int AID_PF2 = 0x32; - public static final int AID_PF3 = 0x33; - public static final int AID_PF4 = 0x34; - public static final int AID_PF5 = 0x35; - public static final int AID_PF6 = 0x36; - public static final int AID_PF7 = 0x37; - public static final int AID_PF8 = 0x38; - public static final int AID_PF9 = 0x39; - public static final int AID_PF10 = 0x3A; - public static final int AID_PF11 = 0x3B; - public static final int AID_PF12 = 0x3C; - public static final int AID_PF13 = 0xB1; - public static final int AID_PF14 = 0xB2; - public static final int AID_PF15 = 0xB3; - public static final int AID_PF16 = 0xB4; - public static final int AID_PF17 = 0xB5; - public static final int AID_PF18 = 0xB6; - public static final int AID_PF19 = 0xB7; - public static final int AID_PF20 = 0xB8; - public static final int AID_PF21 = 0xB9; - public static final int AID_PF22 = 0xBA; - public static final int AID_PF23 = 0xBB; - public static final int AID_PF24 = 0xBC; - - // negative response categories - public static final int NR_REQUEST_REJECT = 0x08; - public static final int NR_REQUEST_ERROR = 0x10; - public static final int NR_STATE_ERROR = 0x20; - public static final int NR_USAGE_ERROR = 0x40; - public static final int NR_PATH_ERROR = 0x80; - - // commands - public static final byte CMD_WRITE_TO_DISPLAY = 0x11; // 17 - public static final byte CMD_CLEAR_UNIT = 0x40; // 64 - public static final byte CMD_CLEAR_UNIT_ALTERNATE = 0x20; // 32 - public static final byte CMD_CLEAR_FORMAT_TABLE = 0x50; // 80 - public static final byte CMD_READ_INPUT_FIELDS = 0x42; // 66 - public static final byte CMD_READ_MDT_FIELDS = 0x52; // 82 - public static final byte CMD_READ_MDT_IMMEDIATE_ALT = (byte)0x83; // 131 -// public static final byte CMD_READ_MDT_FIELDS_ALT = (byte)0x82; // 130 -// public static final byte CMD_READ_IMMEDIATE = 0x72; // 114 - public static final byte CMD_READ_SCREEN_IMMEDIATE = 0x62; // 98 - public static final byte CMD_WRITE_STRUCTURED_FIELD = (byte)243; // (byte)0xF3 -13 - public static final byte CMD_SAVE_SCREEN = 0x02; // 02 - public static final byte CMD_RESTORE_SCREEN = 0x12; // 18 - public static final byte CMD_WRITE_ERROR_CODE = 0x21; // 33 - public static final byte CMD_WRITE_ERROR_CODE_TO_WINDOW = 0x22; // 34 - public static final byte CMD_ROLL = 0x23; // 35 - public static final byte CMD_READ_SCREEN_TO_PRINT = (byte)0x66; // 102 - - // PLANES - public static final int PLANE_TEXT = 1; - public static final int PLANE_COLOR = 2; - public static final int PLANE_FIELD = 3; - public static final int PLANE_EXTENDED = 4; - public static final int PLANE_EXTENDED_GRAPHIC = 5; - public static final int PLANE_EXTENDED_FIELD = 6; - public static final int PLANE_ATTR = 7; - public static final int PLANE_IS_ATTR_PLACE = 8; - - // COLOR_BG - public static final char COLOR_BG_BLACK = 0; - public static final char COLOR_BG_BLUE = 1; - public static final char COLOR_BG_GREEN = 2; - public static final char COLOR_BG_CYAN = 3; - public static final char COLOR_BG_RED = 4; - public static final char COLOR_BG_MAGENTA = 5; - public static final char COLOR_BG_YELLOW = 6; - public static final char COLOR_BG_WHITE = 7; - - // COLOR_FG - public static final char COLOR_FG_BLACK = 0; - public static final char COLOR_FG_BLUE = 1; - public static final char COLOR_FG_GREEN = 2; - public static final char COLOR_FG_CYAN = 3; - public static final char COLOR_FG_RED = 4; - public static final char COLOR_FG_MAGENTA = 5; - public static final char COLOR_FG_YELLOW = 6; - public static final char COLOR_FG_WHITE = 7; - public static final char COLOR_FG_GRAY = 8; - public static final char COLOR_FG_LIGHT_BLUE = 9; - public static final char COLOR_FG_LIGHT_GREEN = 0xA; - public static final char COLOR_FG_LIGHT_CYAN = 0xB; - public static final char COLOR_FG_LIGHT_RED = 0xC; - public static final char COLOR_FG_LIGHT_MAGENTA = 0xD; - public static final char COLOR_FG_BROWN = 0xE; - public static final char COLOR_FG_WHITE_HIGH = 0xF; - - public static final int EXTENDED_5250_REVERSE = 0x10; - public static final int EXTENDED_5250_UNDERLINE = 0x08; - public static final int EXTENDED_5250_BLINK = 0x04; - public static final int EXTENDED_5250_COL_SEP = 0x02; - public static final int EXTENDED_5250_NON_DSP = 0x01; - - public static final char ATTR_32 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_GREEN & 0xff); - public static final char ATTR_33 = (COLOR_BG_GREEN << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_34 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_WHITE & 0xff); - public static final char ATTR_35 = (COLOR_BG_WHITE << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_36 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_GREEN & 0xff); - public static final char ATTR_37 = (COLOR_BG_GREEN << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_38 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_WHITE & 0xff); - public static final char ATTR_40 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_RED & 0xff); - public static final char ATTR_41 = (COLOR_BG_RED << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_42 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_RED & 0xff); - public static final char ATTR_43 = (COLOR_BG_RED << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - - public static final char ATTR_44 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_RED & 0xff); - public static final char ATTR_45 = (COLOR_BG_RED << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_46 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_RED & 0xff); - - public static final char ATTR_48 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_CYAN & 0xff); - public static final char ATTR_49 = (COLOR_BG_CYAN << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_50 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_YELLOW & 0xff); - - public static final char ATTR_51 = (COLOR_BG_YELLOW << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_52 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_CYAN & 0xff); - public static final char ATTR_53 = (COLOR_BG_CYAN << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_54 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_YELLOW & 0xff); - public static final char ATTR_56 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_MAGENTA & 0xff); - public static final char ATTR_57 = (COLOR_BG_MAGENTA << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_58 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_BLUE & 0xff); - public static final char ATTR_59 = (COLOR_BG_BLUE << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_60 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_MAGENTA & 0xff); - public static final char ATTR_61 = (COLOR_BG_MAGENTA << 8 & 0xff00) | - (COLOR_FG_BLACK & 0xff); - public static final char ATTR_62 = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_BLUE & 0xff); - - public static final int NO_GUI = 0; - public static final int UPPER_LEFT = 1; - public static final int UPPER = 2; - public static final int UPPER_RIGHT = 3; - public static final int GUI_LEFT = 4; - public static final int GUI_RIGHT = 5; - public static final int LOWER_LEFT = 6; - public static final int BOTTOM = 7; - public static final int LOWER_RIGHT = 8; - public static final int FIELD_LEFT = 9; - public static final int FIELD_RIGHT = 10; - public static final int FIELD_MIDDLE = 11; - public static final int FIELD_ONE = 12; - public static final int BUTTON_LEFT = 13; - public static final int BUTTON_RIGHT = 14; - public static final int BUTTON_MIDDLE = 15; - public static final int BUTTON_ONE = 16; - public static final int BUTTON_LEFT_UP = 17; - public static final int BUTTON_RIGHT_UP = 18; - public static final int BUTTON_MIDDLE_UP = 19; - public static final int BUTTON_ONE_UP = 20; - public static final int BUTTON_LEFT_DN = 21; - public static final int BUTTON_RIGHT_DN = 22; - public static final int BUTTON_MIDDLE_DN = 23; - public static final int BUTTON_ONE_DN = 24; - public static final int BUTTON_LEFT_EB = 25; - public static final int BUTTON_RIGHT_EB = 26; - public static final int BUTTON_MIDDLE_EB = 27; - public static final int BUTTON_SB_UP = 28; - public static final int BUTTON_SB_DN = 29; - public static final int BUTTON_SB_GUIDE = 30; - public static final int BUTTON_SB_THUMB = 31; - public static final int BUTTON_LAST = 31; - -}
--- a/src/org/tn5250j/encoding/AbstractCodePage.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/** - * Title: CodePage.java - * Copyright: Copyright (c) 2001, 2002, 2003 - * Company: - * @author Kenneth J. Pouncey - * rewritten by LDC, WVL, Luc - * @version 0.4 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding; - -/** - * - * This class controls the translation from EBCDIC to ASCII and ASCII to EBCDIC - * - */ -public abstract class AbstractCodePage implements ICodePage { - - protected AbstractCodePage(String encoding) { - this.encoding = encoding; - } - - public String getEncoding() { - return encoding; - } - - protected String encoding; -}
--- a/src/org/tn5250j/encoding/BuiltInCodePageFactory.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2012 - * Company: - * @author: master_jaf - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding; - -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -import org.tn5250j.encoding.builtin.CCSID1025; -import org.tn5250j.encoding.builtin.CCSID1026; -import org.tn5250j.encoding.builtin.CCSID1112; -import org.tn5250j.encoding.builtin.CCSID1140; -import org.tn5250j.encoding.builtin.CCSID1141; -import org.tn5250j.encoding.builtin.CCSID1147; -import org.tn5250j.encoding.builtin.CCSID1148; -import org.tn5250j.encoding.builtin.CCSID273; -import org.tn5250j.encoding.builtin.CCSID277; -import org.tn5250j.encoding.builtin.CCSID278; -import org.tn5250j.encoding.builtin.CCSID280; -import org.tn5250j.encoding.builtin.CCSID284; -import org.tn5250j.encoding.builtin.CCSID285; -import org.tn5250j.encoding.builtin.CCSID297; -import org.tn5250j.encoding.builtin.CCSID37; -import org.tn5250j.encoding.builtin.CCSID424; -import org.tn5250j.encoding.builtin.CCSID500; -import org.tn5250j.encoding.builtin.CCSID870; -import org.tn5250j.encoding.builtin.CCSID871; -import org.tn5250j.encoding.builtin.CCSID875; -import org.tn5250j.encoding.builtin.ICodepageConverter; -import android.util.Log; - - -/** - * Methods for built-in code page support. - */ -class BuiltInCodePageFactory { - private static final String TAG = "BuiltInCodePageFactory"; - private static BuiltInCodePageFactory singleton; - - private final List<Class<?>> clazzes = new ArrayList<Class<?>>(); - - - private BuiltInCodePageFactory() { - register(); - } - - public static synchronized final BuiltInCodePageFactory getInstance() { - if (singleton == null) { - singleton = new BuiltInCodePageFactory(); - } - - return singleton; - } - - private void register() { - clazzes.add(CCSID37.class); - clazzes.add(CCSID273.class); - clazzes.add(CCSID277.class); - clazzes.add(CCSID278.class); - clazzes.add(CCSID280.class); - clazzes.add(CCSID284.class); - clazzes.add(CCSID285.class); - clazzes.add(CCSID297.class); - clazzes.add(CCSID424.class); - clazzes.add(CCSID500.class); - clazzes.add(CCSID870.class); - clazzes.add(CCSID871.class); - clazzes.add(CCSID875.class); - clazzes.add(CCSID1025.class); - clazzes.add(CCSID1026.class); - clazzes.add(CCSID1112.class); - clazzes.add(CCSID1140.class); - clazzes.add(CCSID1141.class); - clazzes.add(CCSID1147.class); - clazzes.add(CCSID1148.class); - } - - /** - * @return unsorted list of available code pages - */ - public String[] getAvailableCodePages() { - HashSet<String> cpset = new HashSet<String>(); - - for (Class<?> clazz : clazzes) { - final ICodepageConverter converter = getConverterFromClassName(clazz); - - if (converter != null) { - cpset.add(converter.getName()); - } - } - - return cpset.toArray(new String[cpset.size()]); - } - - /** - * @param encoding - * @return an {@link ICodePage} object OR null, of not found - */ - public ICodePage getCodePage(String encoding) { - for (Class<?> clazz : clazzes) { - final ICodepageConverter converter = getConverterFromClassName(clazz); - - if (converter != null && converter.getName().equals(encoding)) { - return converter; - } - } - - return null; - } - - /** - * Lazy loading converters takes time, - * but doesn't happen so often and saves memory. - * - * @param clazz {@link ICodepageConverter} - * @return - */ - private ICodepageConverter getConverterFromClassName(Class<?> clazz) { - try { - final Constructor<?> constructor = clazz.getConstructor(new Class[0]); - final ICodepageConverter converter = (ICodepageConverter) constructor.newInstance(); - converter.init(); - return converter; - } - catch (Exception e) { - Log.e(TAG, "Couldn't load code page converter class:" + clazz.getCanonicalName(), e); - return null; - } - } - -}
--- a/src/org/tn5250j/encoding/CharMappings.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/** - * Title: CharMappings.java - * Copyright: Copyright (c) 2001,2002,2003 - * Company: - * @author Kenneth J. Pouncey - * rewritten by LDC, WVL, Luc - * @version 0.4 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - -/** - * Character Mappings for EBCDIC to ASCII and ASCII to EBCDIC translations - */ -public class CharMappings { - - public static final String DFT_ENC = "37"; - public static final int NATIVE_CP = 0; - public static final int TOOLBOX_CP = 1; - - private static final HashMap<String, ICodePage> map = new HashMap<String, ICodePage>(); - - public static String[] getAvailableCodePages() { - Set<String> cpset = new HashSet<String>(); // no double entries - - for (String cp : BuiltInCodePageFactory.getInstance().getAvailableCodePages()) { - cpset.add(cp); - } - - for (String cp : ToolboxCodePageFactory.getInstance().getAvailableCodePages()) { - cpset.add(cp); - } - - String[] cparray = cpset.toArray(new String[cpset.size()]); - Arrays.sort(cparray); - return cparray; - } - - public static ICodePage getCodePage(String encoding) { - if (map.containsKey(encoding)) { - return map.get(encoding); - } - - ICodePage cp = BuiltInCodePageFactory.getInstance().getCodePage(encoding); - - if (cp != null) { - map.put(encoding, cp); - return cp; - } - - cp = ToolboxCodePageFactory.getInstance().getCodePage(encoding); - - if (cp != null) { - map.put(encoding, cp); - return cp; - } - - cp = JavaCodePageFactory.getCodePage(encoding); - - if (cp != null) { - map.put(encoding, cp); - return cp; - } - - // unsupported codepage ==> return default - return BuiltInCodePageFactory.getInstance().getCodePage(DFT_ENC); - } - -}
--- a/src/org/tn5250j/encoding/ICodePage.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -package org.tn5250j.encoding; - -public interface ICodePage { - - /** - * Convert a single byte (or maybe more bytes which representing one character) to a Unicode character. - * - * @param index - * @return - */ - public abstract char ebcdic2uni(int index); - - /** - * Convert a Unicode character in it's byte representation. - * Therefore, only 8bit codepages are supported. - * - * @param index - * @return - */ - public abstract byte uni2ebcdic(char index); - -}
--- a/src/org/tn5250j/encoding/JavaCodePageFactory.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/** - * Title: JavaCodePage - * Copyright: Copyright (c) 2001, 2002, 2003 - * Company: - * @author LDC, WVL, Luc, master_jaf - * @version 0.4 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; - -/* package */ class JavaCodePageFactory extends AbstractCodePage { - - private final CharsetEncoder encoder; - private final CharsetDecoder decoder; - - /* package */ JavaCodePageFactory(String encoding, CharsetEncoder encoder, CharsetDecoder decoder) { - super(encoding); - this.encoder = encoder; - this.decoder = decoder; - } - - /* (non-Javadoc) - * @see org.tn5250j.encoding.CodePage#ebcdic2uni(int) - */ - public char ebcdic2uni(int codepoint) { - try { - final ByteBuffer in = ByteBuffer.wrap(new byte[] { (byte) codepoint }); - final CharBuffer out = this.decoder.decode(in); - return out.get(0); - } - catch (Exception cce) { - return ' '; - } - } - - /* (non-Javadoc) - * @see org.tn5250j.encoding.CodePage#uni2ebcdic(char) - */ - public byte uni2ebcdic(char character) { - try { - final CharBuffer in = CharBuffer.wrap(new char[] {character}); - final ByteBuffer out = this.encoder.encode(in); - return out.get(0); - } - catch (Exception cce) { - return 0x0; - } - } - - /** - * @param encoding - * @return A new {@link CodePage} object OR null, if not available. - */ - /* package */ static ICodePage getCodePage(final String encoding) { - CharsetDecoder dec = null; - CharsetEncoder enc = null; - - try { - final Charset cs = java.nio.charset.Charset.forName(encoding); - dec = cs.newDecoder(); - enc = cs.newEncoder(); - } - catch (Exception e) { - enc = null; - dec = null; - } - - if ((enc != null) && (dec != null)) { - return new JavaCodePageFactory(encoding, enc, dec); - } - - return null; - } - -} \ No newline at end of file
--- a/src/org/tn5250j/encoding/ToolboxCodePageFactory.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/** - * Title: ToolboxCodePage - * Copyright: Copyright (c) 2001, 2002, 2003 - * Company: - * @author Kenneth J. Pouncey - * rewritten by LDC, WVL, Luc - * @version 0.4 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -import android.util.Log; - - -class ToolboxCodePageFactory { - private static final String TAG = "ToolboxCodePageFactory"; - private final static String[] CODEPAGES = { "Big5", "Cp037", "Cp273", "Cp277", "Cp278", - "Cp280", "Cp284", "Cp285", "Cp297", "Cp420", "Cp424", "Cp437", - "Cp500", "Cp737", "Cp775", "Cp838", "Cp850", "Cp852", "Cp855", - "Cp856", "Cp857", "Cp858", "Cp860", "Cp861", "Cp862", "Cp863", - "Cp864", "Cp865", "Cp866", "Cp868", "Cp869", "Cp870", - "Cp871", "Cp874", "Cp875", "Cp918", "Cp921", "Cp922", - "Cp923", // IBM Latin-9. - "Cp930", "Cp933", "Cp935", "Cp937", "Cp939", "Cp942", "Cp943", - "Cp948", "Cp949", "Cp950", "Cp964", "Cp970", "Cp1006", "Cp1025", - "Cp1026", "Cp1046", "Cp1097", "Cp1098", "Cp1112", "Cp1122", - "Cp1123", "Cp1124", "Cp1140", "Cp1141", "Cp1142", "Cp1143", - "Cp1144", "Cp1145", "Cp1146", "Cp1147", "Cp1148", "Cp1149", - "Cp1252", "Cp1250", "Cp1251", "Cp1253", "Cp1254", "Cp1255", - "Cp1256", "Cp1257", "Cp1258", "Cp1381", "Cp1383", "Cp33722" - }; - - private static final String CONVERTER_NAME = "com.ibm.as400.access.CharConverter"; - private static final String TOBYTES_NAME = "stringToByteArray"; - private static final String TOSTRING_NAME = "byteArrayToString"; - - private static ToolboxCodePageFactory singleton; - - - - private ToolboxCodePageFactory() { - /* private for singleton */ - } - - public static synchronized ToolboxCodePageFactory getInstance() { - if (singleton == null) { - singleton = new ToolboxCodePageFactory(); - } - - return singleton; - } - - /** - * @return - */ - public String[] getAvailableCodePages() { - try { - final ClassLoader loader = getClassLoader(); - Class.forName(CONVERTER_NAME, false, loader); - return CODEPAGES; - } - catch (Exception e) { - Log.i(TAG, "Couldn't locate JT400 Toolbox in classpath. Charset converters can't be used."); - return new String[0]; - } - } - - /** - * @param encoding - * @return - */ - public ICodePage getCodePage(String encoding) { - try { - ClassLoader loader = getClassLoader(); - Class<?> conv_class = Class.forName(CONVERTER_NAME, true, loader); - Constructor<?> conv_constructor = conv_class.getConstructor(new Class[] { String.class }); - Method toBytes_method = conv_class.getMethod(TOBYTES_NAME, new Class[] { String.class }); - Method toString_method = conv_class.getMethod(TOSTRING_NAME, new Class[] { byte[].class }); - Object convobj = conv_constructor.newInstance(new Object[] { encoding }); - return new ToolboxConverterProxy(convobj, toBytes_method, toString_method); - } - catch (Exception e) { - Log.w(TAG, "Can't load charset converter from JT400 Toolbox for code page " + encoding, e); - return null; - } - } - - private static final ClassLoader getClassLoader() { - ClassLoader loader = ToolboxCodePageFactory.class.getClassLoader(); - - if (loader == null) { - loader = ClassLoader.getSystemClassLoader(); - } - - return loader; - } - - private static class ToolboxConverterProxy implements ICodePage { - - private final Object converter; - private final Method tobytesMethod; - private final Method tostringMethod; - - private ToolboxConverterProxy(Object converterObject, Method tobytesMethod, Method tostringMethod) { - super(); - this.converter = converterObject; - this.tobytesMethod = tobytesMethod; - this.tostringMethod = tostringMethod; - } - - public char ebcdic2uni(int index) { - Object result; - - try { - result = tostringMethod.invoke(converter, new Object[] { new byte[] { (byte)(index & 0xFF) } }); - } - catch (Throwable t) { - result = null; - } - - if (result == null) - return 0x00; - - return ((String) result).charAt(0); - } - - public byte uni2ebcdic(char index) { - Object result; - - try { - result = tobytesMethod.invoke(converter, new Object[] { new String(new char[] { index }) }); - } - catch (Throwable t) { - result = null; - } - - if (result == null) - return 0x00; - - return ((byte[]) result)[0]; - } - } - -} \ No newline at end of file
--- a/src/org/tn5250j/encoding/builtin/CCSID1025.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 1025<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1025.jsp - */ -public final class CCSID1025 extends CodepageConverterAdapter { - - public final static String NAME = "1025"; - public final static String DESCR = "Cyrillic Multilingual"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u0452', - '\u0453', '\u0451', '\u0454', '\u0455', '\u0456', '\u0457', - '\u0458', '[', '.', '<', '(', '+', '!', '&', '\u0459', '\u045A', - '\u045B', '\u045C', '\u045E', '\u045F', '\u042A', '\u2116', - '\u0402', ']', '$', '*', ')', ';', '^', '-', '/', '\u0403', - '\u0401', '\u0404', '\u0405', '\u0406', '\u0407', '\u0408', - '\u0409', '|', ',', '%', '_', '>', '?', '\u040A', '\u040B', - '\u040C', '\u00AD', '\u040E', '\u040F', '\u044E', '\u0430', - '\u0431', '`', ':', '#', '@', '\'', '=', '"', '\u0446', 'a', 'b', - 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u0434', '\u0435', '\u0444', - '\u0433', '\u0445', '\u0438', '\u0439', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', '\u043A', '\u043B', '\u043C', '\u043D', - '\u043E', '\u043F', '\u044F', '~', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '\u0440', '\u0441', '\u0442', '\u0443', '\u0436', - '\u0432', '\u044C', '\u044B', '\u0437', '\u0448', '\u044D', - '\u0449', '\u0447', '\u044A', '\u042E', '\u0410', '\u0411', - '\u0426', '\u0414', '\u0415', '\u0424', '\u0413', '{', 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u0425', '\u0418', '\u0419', - '\u041A', '\u041B', '\u041C', '}', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', '\u041D', '\u041E', '\u041F', '\u042F', '\u0420', - '\u0421', '\\', '\u00A7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - '\u0422', '\u0423', '\u0416', '\u0412', '\u042C', '\u042B', '0', - '1', '2', '3', '4', '5', '6', '7', '8', '9', '\u0417', '\u0428', - '\u042D', '\u0429', '\u0427', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID1026.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 1026<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1026.jsp - */ -public final class CCSID1026 extends CodepageConverterAdapter { - - public final static String NAME = "1026"; - public final static String DESCR = "Turkey Latin 5"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '{', '\u00F1', - '\u00C7', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', - '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', - '\u00DF', '\u011E', '\u0130', '*', ')', ';', '^', '-', '/', - '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', '[', - '\u00D1', '\u015F', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', - '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', - '\u00CC', '\u0131', ':', '\u00D6', '\u015E', '\'', '=', '\u00DC', - '\u00D8', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', - '\u00BB', '}', '`', '\u00A6', '\u00B1', '\u00B0', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', - '\u00B8', '\u00C6', '\u00A4', '\u00B5', '\u00F6', 's', 't', 'u', - 'v', 'w', 'x', 'y', 'z', '\u00A1', '\u00BF', ']', '$', '@', - '\u00AE', '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', - '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', - '\u00AF', '\u00A8', '\u00B4', '\u00D7', '\u00E7', 'A', 'B', 'C', - 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '~', '\u00F2', - '\u00F3', '\u00F5', '\u011F', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', '\u00B9', '\u00FB', '\\', '\u00F9', '\u00FA', '\u00FF', - '\u00FC', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - '\u00B2', '\u00D4', '#', '\u00D2', '\u00D3', '\u00D5', '0', '1', - '2', '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '"', - '\u00D9', '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID1112.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 1112<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1112.jsp - */ -public final class CCSID1112 extends CodepageConverterAdapter { - - public final static String NAME = "1112"; - public final static String DESCR = "Baltic, Multilingual"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u0161', - '\u00E4', '\u0105', '\u012F', '\u016B', '\u00E5', '\u0113', - '\u017E', '\u00A2', '.', '<', '(', '+', '|', '&', '\u00E9', - '\u0119', '\u0117', '\u010D', '\u0173', '\u201E', '\u201C', - '\u0123', '\u00DF', '!', '$', '*', ')', ';', '\u00AC', '-', '/', - '\u0160', '\u00C4', '\u0104', '\u012E', '\u016A', '\u00C5', - '\u0112', '\u017D', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', - '\u00C9', '\u0118', '\u0116', '\u010C', '\u0172', '\u012A', - '\u013B', '\u0122', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', - '\u0101', '\u017C', '\u0144', '\u00B1', '\u00B0', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', '\u0156', '\u0157', '\u00E6', - '\u0137', '\u00C6', '\u00A4', '\u00B5', '~', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '\u201D', '\u017A', '\u0100', '\u017B', - '\u0143', '\u00AE', '^', '\u00A3', '\u012B', '\u00B7', '\u00A9', - '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '[', ']', - '\u0179', '\u0136', '\u013C', '\u00D7', '{', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u014D', '\u00F6', '\u0146', - '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', - 'R', '\u00B9', '\u0107', '\u00FC', '\u0142', '\u015B', '\u2019', - '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u014C', '\u00D6', '\u0145', '\u00D3', '\u00D5', '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u0106', '\u00DC', - '\u0141', '\u015A', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID1140.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 1140<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1140.jsp - */ -public final class CCSID1140 extends CodepageConverterAdapter { - - public final static String NAME = "1140"; - public final static String DESCR = "ECECP: USA, Canada, Netherlands, Portugal, Brazil, Australia, New Zealand"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', - '\u00F1', '\u00A2', '.', '<', '(', '+', '|', '&', '\u00E9', - '\u00EA', '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', - '\u00EC', '\u00DF', '!', '$', '*', ')', ';', '\u00AC', '-', '/', - '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', - '\u00C7', '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', - '\u00C9', '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', - '\u00CF', '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', - '\u00F0', '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', - '\u00B8', '\u00C6', '\u20AC', '\u00B5', '~', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', - '\u00DE', '\u00AE', '^', '\u00A3', '\u00A5', '\u00B7', '\u00A9', - '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '[', ']', - '\u00AF', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', - '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', - 'R', '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', - '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', - '\u00D9', '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID1141.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 1141<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1141.jsp - */ -public final class CCSID1141 extends CodepageConverterAdapter { - - public final static String NAME = "1141"; - public final static String DESCR = "ECECP: Austria, Germany"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '{', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', '\u00F1', - '\u00C4', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', - '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '~', - '\u00DC', '$', '*', ')', ';', '^', '-', '/', '\u00C2', '[', - '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', - '\u00F6', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', - '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '`', - ':', '#', '\u00A7', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', - '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', - '\u20AC', '\u00B5', '\u00DF', 's', 't', 'u', 'v', 'w', 'x', 'y', - 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', - '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '@', '\u00B6', - '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', - '\u00B4', '\u00D7', '\u00E4', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '\u00AD', '\u00F4', '\u00A6', '\u00F2', '\u00F3', - '\u00F5', '\u00FC', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - '\u00B9', '\u00FB', '}', '\u00F9', '\u00FA', '\u00FF', '\u00D6', - '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '\\', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', ']', '\u00D9', - '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID1147.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 1147<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1147.jsp - */ -public final class CCSID1147 extends CodepageConverterAdapter { - - public final static String NAME = "1147"; - public final static String DESCR = "ECECP: France"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '@', '\u00E1', '\u00E3', '\u00E5', '\\', '\u00F1', - '\u00B0', '.', '<', '(', '+', '!', '&', '{', '\u00EA', '\u00EB', - '}', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '\u00DF', '\u00A7', - '$', '*', ')', ';', '^', '-', '/', '\u00C2', '\u00C4', '\u00C0', - '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', '\u00F9', ',', - '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', '\u00CB', - '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00B5', ':', - '\u00A3', '\u00E0', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', - '\u00FE', '\u00B1', '[', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', - 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', '\u20AC', - '`', '\u00A8', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\u00A1', - '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', '\u00A2', '#', - '\u00A5', '\u00B7', '\u00A9', ']', '\u00B6', '\u00BC', '\u00BD', - '\u00BE', '\u00AC', '|', '\u00AF', '~', '\u00B4', '\u00D7', - '\u00E9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', - '\u00F4', '\u00F6', '\u00F2', '\u00F3', '\u00F5', '\u00E8', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', '\u00B9', '\u00FB', - '\u00FC', '\u00A6', '\u00FA', '\u00FF', '\u00E7', '\u00F7', 'S', - 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', '\u00D4', '\u00D6', - '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', '4', '5', '6', - '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', '\u00D9', '\u00DA', - '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID1148.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 1148<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid1148.jsp - */ -public final class CCSID1148 extends CodepageConverterAdapter { - - public final static String NAME = "1148"; - public final static String DESCR = "ECECP: International 1"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', - '\u00F1', '[', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', - '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', - '\u00DF', ']', '$', '*', ')', ';', '^', '-', '/', '\u00C2', - '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', - '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', - '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', - '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', 'a', 'b', - 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', - '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', - '\u00C6', '\u20AC', '\u00B5', '~', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', - '\u00AE', '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', - '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', - '\u00AF', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', - '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', - 'R', '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', - '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', - '\u00D9', '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID273.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 273<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid273.jsp - */ -public final class CCSID273 extends CodepageConverterAdapter { - - public final static String NAME = "273"; - public final static String DESCR = "CECP: Austria, Germany"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '{', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', '\u00F1', - '\u00C4', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', - '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '~', - '\u00DC', '$', '*', ')', ';', '^', '-', '/', '\u00C2', '[', - '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', - '\u00F6', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', - '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '`', - ':', '#', '\u00A7', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', - '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', - '\u00A4', '\u00B5', '\u00DF', 's', 't', 'u', 'v', 'w', 'x', 'y', - 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', - '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '@', '\u00B6', - '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', - '\u00B4', '\u00D7', '\u00E4', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '\u00AD', '\u00F4', '\u00A6', '\u00F2', '\u00F3', - '\u00F5', '\u00FC', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - '\u00B9', '\u00FB', '}', '\u00F9', '\u00FA', '\u00FF', '\u00D6', - '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '\\', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', ']', '\u00D9', - '\u00DA', '\u009F', - }; - - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID277.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 277<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid277.jsp - */ -public final class CCSID277 extends CodepageConverterAdapter { - - public final static String NAME = "277"; - public final static String DESCR = "CECP: Denmark, Norway"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u00E0', '\u00E1', '\u00E3', '}', '\u00E7', '\u00F1', - '#', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', '\u00EB', - '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '\u00DF', - '\u00A4', '\u00C5', '*', ')', ';', '^', '-', '/', '\u00C2', - '\u00C4', '\u00C0', '\u00C1', '\u00C3', '$', '\u00C7', '\u00D1', - '\u00F8', ',', '%', '_', '>', '?', '\u00A6', '\u00C9', '\u00CA', - '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '`', - ':', '\u00C6', '\u00D8', '\'', '=', '"', '@', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', - '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', '\u00AA', '\u00BA', '{', '\u00B8', '[', ']', '\u00B5', - '\u00FC', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\u00A1', - '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', '\u00A2', - '\u00A3', '\u00A5', '\u00B7', '\u00A9', '\u00A7', '\u00B6', - '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', - '\u00B4', '\u00D7', '\u00E6', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', '\u00F3', - '\u00F5', '\u00E5', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - '\u00B9', '\u00FB', '~', '\u00F9', '\u00FA', '\u00FF', '\\', - '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', - '\u00D9', '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID278.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 278<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid278.jsp - */ -public final class CCSID278 extends CodepageConverterAdapter { - - public final static String NAME = "278"; - public final static String DESCR = "CECP: Finland, Sweden"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '{', '\u00E0', '\u00E1', '\u00E3', '}', '\u00E7', '\u00F1', - '\u00A7', '.', '<', '(', '+', '!', '&', '`', '\u00EA', '\u00EB', - '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '\u00DF', - '\u00A4', '\u00C5', '*', ')', ';', '^', '-', '/', '\u00C2', '#', - '\u00C0', '\u00C1', '\u00C3', '$', '\u00C7', '\u00D1', '\u00F6', - ',', '%', '_', '>', '?', '\u00F8', '\\', '\u00CA', '\u00CB', - '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00E9', ':', - '\u00C4', '\u00D6', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', - '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', ']', - '\u00B5', '\u00FC', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', - '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '[', '\u00B6', - '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', - '\u00B4', '\u00D7', '\u00E4', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '\u00AD', '\u00F4', '\u00A6', '\u00F2', '\u00F3', - '\u00F5', '\u00E5', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - '\u00B9', '\u00FB', '~', '\u00F9', '\u00FA', '\u00FF', '\u00C9', - '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '@', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', - '\u00D9', '\u00DA', '\u009F' - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID280.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 280<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid280.jsp - */ -public final class CCSID280 extends CodepageConverterAdapter { - - public final static String NAME = "280"; - public final static String DESCR = "CECP: Italy"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '{', '\u00E1', '\u00E3', '\u00E5', '\\', '\u00F1', - '\u00B0', '.', '<', '(', '+', '!', '&', ']', '\u00EA', '\u00EB', - '}', '\u00ED', '\u00EE', '\u00EF', '~', '\u00DF', '\u00E9', '$', - '*', ')', ';', '^', '-', '/', '\u00C2', '\u00C4', '\u00C0', - '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', '\u00F2', ',', - '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', '\u00CB', - '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00F9', ':', - '\u00A3', '\u00A7', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', - '\u00FE', '\u00B1', '[', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', - 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', '\u00A4', - '\u00B5', '\u00EC', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', - '\u00A2', '#', '\u00A5', '\u00B7', '\u00A9', '@', '\u00B6', - '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', '\u00A8', - '\u00B4', '\u00D7', '\u00E0', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00A6', '\u00F3', - '\u00F5', '\u00E8', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - '\u00B9', '\u00FB', '\u00FC', '`', '\u00FA', '\u00FF', '\u00E7', - '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', - '\u00D9', '\u00DA', '\u009F' - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID284.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 284<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid284.jsp - */ -public final class CCSID284 extends CodepageConverterAdapter { - - public final static String NAME = "284"; - public final static String DESCR = "CECP: Spain, Latin America (Spanish)"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', - '\u00A6', '[', '.', '<', '(', '+', '|', '&', '\u00E9', '\u00EA', - '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', - '\u00DF', ']', '$', '*', ')', ';', '\u00AC', '-', '/', '\u00C2', - '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', '#', - '\u00F1', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', - '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '`', - ':', '\u00D1', '@', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', - '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', - '\u00A4', '\u00B5', '\u00A8', 's', 't', 'u', 'v', 'w', 'x', 'y', - 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', - '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '\u00A7', - '\u00B6', '\u00BC', '\u00BD', '\u00BE', '^', '!', '\u00AF', '~', - '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', '\u00F3', '\u00F5', - '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', '\u00B9', - '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', '\\', '\u00F7', - 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', '\u00D4', - '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', '4', - '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', '\u00D9', - '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID285.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 285<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid285.jsp - */ -public final class CCSID285 extends CodepageConverterAdapter { - - public final static String NAME = "285"; - public final static String DESCR = "CECP: United Kingdom"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', - '\u00F1', '$', '.', '<', '(', '+', '|', '&', '\u00E9', '\u00EA', - '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', - '\u00DF', '!', '\u00A3', '*', ')', ';', '\u00AC', '-', '/', - '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', - '\u00C7', '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', - '\u00C9', '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', - '\u00CF', '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', - '\u00F0', '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', - '\u00B8', '\u00C6', '\u00A4', '\u00B5', '\u00AF', 's', 't', 'u', - 'v', 'w', 'x', 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', - '\u00DE', '\u00AE', '\u00A2', '[', '\u00A5', '\u00B7', '\u00A9', - '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '^', ']', '~', - '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', 'E', 'F', - 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', '\u00F3', - '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', '\\', - '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', - '\u00D9', '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID297.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 297<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid297.jsp - */ -public final class CCSID297 extends CodepageConverterAdapter { - - public final static String NAME = "297"; - public final static String DESCR = "CECP: France"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '@', '\u00E1', '\u00E3', '\u00E5', '\\', '\u00F1', - '\u00B0', '.', '<', '(', '+', '!', '&', '{', '\u00EA', '\u00EB', - '}', '\u00ED', '\u00EE', '\u00EF', '\u00EC', '\u00DF', '\u00A7', - '$', '*', ')', ';', '^', '-', '/', '\u00C2', '\u00C4', '\u00C0', - '\u00C1', '\u00C3', '\u00C5', '\u00C7', '\u00D1', '\u00F9', ',', - '%', '_', '>', '?', '\u00F8', '\u00C9', '\u00CA', '\u00CB', - '\u00C8', '\u00CD', '\u00CE', '\u00CF', '\u00CC', '\u00B5', ':', - '\u00A3', '\u00E0', '\'', '=', '"', '\u00D8', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', '\u00FD', - '\u00FE', '\u00B1', '[', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', - 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', '\u00C6', '\u00A4', - '`', '\u00A8', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\u00A1', - '\u00BF', '\u00D0', '\u00DD', '\u00DE', '\u00AE', '\u00A2', '#', - '\u00A5', '\u00B7', '\u00A9', ']', '\u00B6', '\u00BC', '\u00BD', - '\u00BE', '\u00AC', '|', '\u00AF', '~', '\u00B4', '\u00D7', - '\u00E9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', - '\u00F4', '\u00F6', '\u00F2', '\u00F3', '\u00F5', '\u00E8', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', '\u00B9', '\u00FB', - '\u00FC', '\u00A6', '\u00FA', '\u00FF', '\u00E7', '\u00F7', 'S', - 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', '\u00D4', '\u00D6', - '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', '3', '4', '5', '6', - '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', '\u00D9', '\u00DA', - '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID37.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 37<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid37.jsp - */ -public final class CCSID37 extends CodepageConverterAdapter { - - public final static String NAME = "37"; - public final static String DESCR = "CECP: USA, Canada (ESA*), Netherlands, Portugal, Brazil, Australia, New Zealand"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', - '\u00F1', '\u00A2', '.', '<', '(', '+', '|', '&', '\u00E9', - '\u00EA', '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', - '\u00EC', '\u00DF', '!', '$', '*', ')', ';', '\u00AC', '-', '/', - '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', - '\u00C7', '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', - '\u00C9', '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', - '\u00CF', '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', - '\u00F0', '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', - '\u00B8', '\u00C6', '\u00A4', '\u00B5', '~', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', - '\u00DE', '\u00AE', '^', '\u00A3', '\u00A5', '\u00B7', '\u00A9', - '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '[', ']', - '\u00AF', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', - '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', - 'R', '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', - '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', - '\u00D9', '\u00DA', '\u009F', - }; - - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } - -}
--- a/src/org/tn5250j/encoding/builtin/CCSID424.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 424<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid424.jsp - */ -public final class CCSID424 extends CodepageConverterAdapter { - - public final static String NAME = "424"; - public final static String DESCR = "Hebrew"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u05D0', '\u05D1', - '\u05D2', '\u05D3', '\u05D4', '\u05D5', '\u05D6', '\u05D7', - '\u05D8', '\u00A2', '.', '<', '(', '+', '|', '&', '\u05D9', - '\u05DA', '\u05DB', '\u05DC', '\u05DD', '\u05DE', '\u05DF', - '\u05E0', '\u05E1', '!', '$', '*', ')', ';', '\u00AC', '-', '/', - '\u05E2', '\u05E3', '\u05E4', '\u05E5', '\u05E6', '\u05E7', - '\u05E8', '\u05E9', '\u00A6', ',', '%', '_', '>', '?', '\u001A', - '\u05EA', '\u001A', '\u001A', '\u00A0', '\u001A', '\u001A', - '\u001A', '\u2017', '`', ':', '#', '@', '\'', '=', '"', '\u001A', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', - '\u001A', '\u001A', '\u001A', '\u00B1', '\u00B0', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', '\u001A', '\u001A', '\u20AC', - '\u00B8', '\u20AA', '\u00A4', '\u00B5', '~', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '\u001A', '\u001A', '\u001A', '\u001A', - '\u001A', '\u00AE', '^', '\u00A3', '\u00A5', '\u2022', '\u00A9', - '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '[', ']', - '\u203E', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u001A', '\u001A', '\u001A', - '\u001A', '\u001A', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', - 'R', '\u00B9', '\u202D', '\u202E', '\u202C', '\u001A', '\u001A', - '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u001A', '\u001A', '\u001A', '\u001A', '\u001A', '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u202A', '\u202B', - '\u200E', '\u200F', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID500.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 500<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid500.jsp - */ -public final class CCSID500 extends CodepageConverterAdapter { - - public final static String NAME = "500"; - public final static String DESCR = "CECP: Belgium, Canada (AS/400*), Switzerland, International Latin-1"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', - '\u00F1', '[', '.', '<', '(', '+', '!', '&', '\u00E9', '\u00EA', - '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', '\u00EC', - '\u00DF', ']', '$', '*', ')', ';', '^', '-', '/', '\u00C2', - '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', '\u00C7', - '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', '\u00C9', - '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF', - '\u00CC', '`', ':', '#', '@', '\'', '=', '"', '\u00D8', 'a', 'b', - 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', '\u00BB', '\u00F0', - '\u00FD', '\u00FE', '\u00B1', '\u00B0', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '\u00E6', '\u00B8', - '\u00C6', '\u00A4', '\u00B5', '~', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '\u00A1', '\u00BF', '\u00D0', '\u00DD', '\u00DE', - '\u00AE', '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', - '\u00A7', '\u00B6', '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', - '\u00AF', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', '\u00F2', - '\u00F3', '\u00F5', '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', - 'R', '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', - '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\u00B2', - '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5', '0', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', '\u00DC', - '\u00D9', '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID870.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 870<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid870.jsp - */ -public final class CCSID870 extends CodepageConverterAdapter { - - public final static String NAME = "870"; - public final static String DESCR = "Latin 2 - EBCDIC Multilingual"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u0163', '\u00E1', '\u0103', '\u010D', '\u00E7', - '\u0107', '[', '.', '<', '(', '+', '!', '&', '\u00E9', '\u0119', - '\u00EB', '\u016F', '\u00ED', '\u00EE', '\u013E', '\u013A', - '\u00DF', ']', '$', '*', ')', ';', '^', '-', '/', '\u00C2', - '\u00C4', '\u02DD', '\u00C1', '\u0102', '\u010C', '\u00C7', - '\u0106', '|', ',', '%', '_', '>', '?', '\u02C7', '\u00C9', - '\u0118', '\u00CB', '\u016E', '\u00CD', '\u00CE', '\u013D', - '\u0139', '`', ':', '#', '@', '\'', '=', '"', '\u02D8', 'a', 'b', - 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u015B', '\u0148', '\u0111', - '\u00FD', '\u0159', '\u015F', '\u00B0', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', '\u0142', '\u0144', '\u0161', '\u00B8', - '\u02DB', '\u00A4', '\u0105', '~', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '\u015A', '\u0147', '\u0110', '\u00DD', '\u0158', - '\u015E', '\u02D9', '\u0104', '\u017C', '\u0162', '\u017B', - '\u00A7', '\u017E', '\u017A', '\u017D', '\u0179', '\u0141', - '\u0143', '\u0160', '\u00A8', '\u00B4', '\u00D7', '{', 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u00F4', '\u00F6', - '\u0155', '\u00F3', '\u0151', '}', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', '\u011A', '\u0171', '\u00FC', '\u0165', '\u00FA', - '\u011B', '\\', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - '\u010F', '\u00D4', '\u00D6', '\u0154', '\u00D3', '\u0150', '0', - '1', '2', '3', '4', '5', '6', '7', '8', '9', '\u010E', '\u0170', - '\u00DC', '\u0164', '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID871.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 871<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid871.jsp - */ -public final class CCSID871 extends CodepageConverterAdapter { - - public final static String NAME = "871"; - public final static String DESCR = "CECP: Iceland"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u00A0', '\u00E2', - '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5', '\u00E7', - '\u00F1', '\u00DE', '.', '<', '(', '+', '!', '&', '\u00E9', - '\u00EA', '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF', - '\u00EC', '\u00DF', '\u00C6', '$', '*', ')', ';', '\u00D6', '-', - '/', '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5', - '\u00C7', '\u00D1', '\u00A6', ',', '%', '_', '>', '?', '\u00F8', - '\u00C9', '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', - '\u00CF', '\u00CC', '\u00F0', ':', '#', '\u00D0', '\'', '=', '"', - '\u00D8', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u00AB', - '\u00BB', '`', '\u00FD', '{', '\u00B1', '\u00B0', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', '\u00AA', '\u00BA', '}', '\u00B8', - ']', '\u00A4', '\u00B5', '\u00F6', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '\u00A1', '\u00BF', '@', '\u00DD', '[', '\u00AE', - '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '\u00A7', - '\u00B6', '\u00BC', '\u00BD', '\u00BE', '\u00AC', '|', '\u00AF', - '\u00A8', '\\', '\u00D7', '\u00FE', 'A', 'B', 'C', 'D', 'E', 'F', - 'G', 'H', 'I', '\u00AD', '\u00F4', '~', '\u00F2', '\u00F3', - '\u00F5', '\u00E6', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF', - '\u00B4', '\u00F7', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - '\u00B2', '\u00D4', '^', '\u00D2', '\u00D3', '\u00D5', '0', '1', - '2', '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00DB', - '\u00DC', '\u00D9', '\u00DA', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CCSID875.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * Alternative (extended) implementation of a codepage converter CCSID 875<->Unicode. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -/** - * @author master_jaf - * @see http://www-01.ibm.com/software/globalization/ccsid/ccsid875.jsp - */ -public final class CCSID875 extends CodepageConverterAdapter { - - public final static String NAME = "875"; - public final static String DESCR = "Greek"; - - /* - * Char maps manually extracted from JTOpen v6.4. Because char maps can't be - * covered by any license, this should legal. - */ - private static final char[] codepage = { '\u0000', '\u0001', '\u0002', - '\u0003', '\u009C', '\t', '\u0086', '\u007F', '\u0097', '\u008D', - '\u008E', '\u000B', '\f', '\r', '\u000E', '\u000F', '\u0010', - '\u0011', '\u0012', '\u0013', '\u009D', '\u0085', '\u0008', - '\u0087', '\u0018', '\u0019', '\u0092', '\u008F', '\u001C', - '\u001D', '\u001E', '\u001F', '\u0080', '\u0081', '\u0082', - '\u0083', '\u0084', '\n', '\u0017', '\u001B', '\u0088', '\u0089', - '\u008A', '\u008B', '\u008C', '\u0005', '\u0006', '\u0007', - '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', - '\u0096', '\u0004', '\u0098', '\u0099', '\u009A', '\u009B', - '\u0014', '\u0015', '\u009E', '\u001A', ' ', '\u0391', '\u0392', - '\u0393', '\u0394', '\u0395', '\u0396', '\u0397', '\u0398', - '\u0399', '[', '.', '<', '(', '+', '!', '&', '\u039A', '\u039B', - '\u039C', '\u039D', '\u039E', '\u039F', '\u03A0', '\u03A1', - '\u03A3', ']', '$', '*', ')', ';', '^', '-', '/', '\u03A4', - '\u03A5', '\u03A6', '\u03A7', '\u03A8', '\u03A9', '\u03AA', - '\u03AB', '|', ',', '%', '_', '>', '?', '\u00A8', '\u0386', - '\u0388', '\u0389', '\u00A0', '\u038A', '\u038C', '\u038E', - '\u038F', '`', ':', '#', '@', '\'', '=', '"', '\u0385', 'a', 'b', - 'c', 'd', 'e', 'f', 'g', 'h', 'i', '\u03B1', '\u03B2', '\u03B3', - '\u03B4', '\u03B5', '\u03B6', '\u00B0', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', '\u03B7', '\u03B8', '\u03B9', '\u03BA', - '\u03BB', '\u03BC', '\u00B4', '~', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '\u03BD', '\u03BE', '\u03BF', '\u03C0', '\u03C1', - '\u03C3', '\u00A3', '\u03AC', '\u03AD', '\u03AE', '\u03CA', - '\u03AF', '\u03CC', '\u03CD', '\u03CB', '\u03CE', '\u03C2', - '\u03C4', '\u03C5', '\u03C6', '\u03C7', '\u03C8', '{', 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\u00AD', '\u03C9', '\u0390', - '\u03B0', '\u2018', '\u2015', '}', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', '\u00B1', '\u00BD', '\u001A', '\u0387', '\u2019', - '\u00A6', '\\', '\u001A', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - '\u00B2', '\u00A7', '\u001A', '\u001A', '\u00AB', '\u00AC', '0', - '1', '2', '3', '4', '5', '6', '7', '8', '9', '\u00B3', '\u00A9', - '\u001A', '\u001A', '\u00BB', '\u009F', - }; - - public String getName() { - return NAME; - } - - public String getDescription() { - return DESCR; - } - - public String getEncoding() { - return NAME; - } - - @Override - protected char[] getCodePage() { - return codepage; - } -}
--- a/src/org/tn5250j/encoding/builtin/CodepageConverterAdapter.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/** - * $Id$ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.encoding.builtin; - -import java.util.Arrays; - -/** - * Adapter class for converters using 8bit codepages. - * - * @author master_jaf - */ -public abstract class CodepageConverterAdapter implements ICodepageConverter { - - private char[] codepage = null; - private int[] reverse_codepage = null; - - /* (non-Javadoc) - * @see org.tn5250j.cp.ICodepageConverter#init() - */ - public ICodepageConverter init() { - codepage = getCodePage(); - int size = 0; - - for (int i = 0; i < codepage.length; i++) { - size = Math.max(size, codepage[i]); - } - - assert(size + 1) < 1024 * 1024; // some kind of maximum size limiter. - reverse_codepage = new int[size + 1]; - Arrays.fill(reverse_codepage, '?'); - - for (int i = 0; i < codepage.length; i++) { - reverse_codepage[codepage[i]] = i; - } - - return this; - } - - /* (non-Javadoc) - * @see org.tn5250j.cp.ICodepageConverter#uni2ebcdic(char) - */ - public byte uni2ebcdic(char index) { - assert index < reverse_codepage.length; - return (byte)reverse_codepage[index]; - } - - /* (non-Javadoc) - * @see org.tn5250j.cp.ICodepageConverter#ebcdic2uni(int) - */ - public char ebcdic2uni(int index) { - index = index & 0xFF; - assert index < 256; - return codepage[index]; - } - - /** - * @return The oringal 8bit codepage. - */ - protected abstract char[] getCodePage(); - -}
--- a/src/org/tn5250j/encoding/builtin/ICodepageConverter.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -package org.tn5250j.encoding.builtin; - -import org.tn5250j.encoding.ICodePage; - -/** - * Interface for classes which do the translation from - * EBCDIC bytes to Unicode characters and vice versa. - * - */ -public interface ICodepageConverter extends ICodePage { - - /** - * Returns an name/ID for this converter. - * Example '273' or 'CP1252'. This name should be unique, - * cause it's used in user settungs and so on. - * - * @return - */ - public abstract String getName(); - - /** - * Returns a short description for this converter. - * For Example '273 - German, EBCDIC' - * - * @return - */ - public abstract String getDescription(); - - /** - * Does special initialization stuff for this converter. - */ - public abstract ICodepageConverter init(); - -} \ No newline at end of file
--- a/src/org/tn5250j/event/ScreenOIAListener.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/** - * - * <p>Title: ScreenOIAListener</p> - * <p>Description: Main interface to draw the graphical image of the screen</p> - * <p>Copyright: Copyright (c) 2000 - 2002</p> - * <p> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * </p> - * @author Kenneth J. Pouncey - * @version 0.5 - */ - -package org.tn5250j.event; - -import org.tn5250j.framework.tn5250.ScreenOIA; - -public interface ScreenOIAListener { - - public static final int OIA_CHANGED_INSERT_MODE = 0; - public static final int OIA_CHANGED_KEYS_BUFFERED = 1; - public static final int OIA_CHANGED_KEYBOARD_LOCKED = 2; - public static final int OIA_CHANGED_MESSAGELIGHT = 3; - public static final int OIA_CHANGED_SCRIPT = 4; - public static final int OIA_CHANGED_BELL = 5; - public static final int OIA_CHANGED_CLEAR_SCREEN = 6; - public static final int OIA_CHANGED_INPUTINHIBITED = 7; - public static final int OIA_CHANGED_CURSOR = 8; - - - public void onOIAChanged(ScreenOIA oia, int change); - -}
--- a/src/org/tn5250j/framework/tn5250/DataStreamProducer.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,372 +0,0 @@ -package org.tn5250j.framework.tn5250; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.SocketException; -import java.util.concurrent.BlockingQueue; -import java.util.Timer; -import java.util.TimerTask; - -import org.tn5250j.encoding.ICodePage; - -import android.util.Log; - - -public class DataStreamProducer implements Runnable { - private static final String TAG = "DataStreamProducer"; - private tnvt vt; - private BufferedInputStream bin; - private ByteArrayOutputStream baosin; - private Thread me; - private byte[] saveStream; - private final BlockingQueue<Object> dsq; - private byte[] abyte2; - private FileOutputStream fw; - private BufferedOutputStream dw; - private boolean dumpBytes = false; - private ICodePage codePage; - - - - public DataStreamProducer(tnvt vt, BufferedInputStream bin, BlockingQueue<Object> queue, byte[] init) { - this.bin = bin; - this.vt = vt; - baosin = new ByteArrayOutputStream(); - dsq = queue; - abyte2 = init; - } - - public void setInputStream(ByteArrayOutputStream is) { - baosin = is; - } - - public final void run() { - boolean done = false; - me = Thread.currentThread(); - // load the first response screen - loadStream(abyte2, 0); - - while (!done) { - try { - byte[] abyte0 = readIncoming(); - - // WVL - LDC : 17/05/2004 : Device name negotiations send TIMING MARK - // Restructured to the readIncoming() method to return null - // on TIMING MARK. Don't process in that case (abyte0 == null)! - if (abyte0 != null) { - // WVL - LDC : 16/07/2003 : TR.000345 - // When the socket has been closed, the reading returns - // no bytes (an empty byte arrray). - // But the loadStream fails on this, so we check it here! - if (abyte0.length > 0) { - loadStream(abyte0, 0); - } - // WVL - LDC : 16/07/2003 : TR.000345 - // Returning no bytes means the input buffer has - // reached end-of-stream, so we do a disconnect! - else { - done = true; - vt.disconnect(); - } - } - } - catch (SocketException se) { - Log.w(TAG, " DataStreamProducer thread interrupted and stopping " + se.getMessage()); - done = true; - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - - if (me.isInterrupted()) - done = true; - } - catch (Exception ex) { - Log.w(TAG, ex.getMessage()); - - if (me.isInterrupted()) - done = true; - } - } - } - - private final void loadStream(byte abyte0[], int i) { - int j = 0; - int size = 0; - - if (saveStream == null) { - j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff; - size = abyte0.length; - } - else { - size = saveStream.length + abyte0.length; - byte[] inter = new byte[size]; - System.arraycopy(saveStream, 0, inter, 0, saveStream.length); - System.arraycopy(abyte0, 0, inter, saveStream.length, abyte0.length); - abyte0 = new byte[size]; - System.arraycopy(inter, 0, abyte0, 0, size); - saveStream = null; - inter = null; - j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff; - Log.d(TAG, "partial stream found"); - } - - if (j > size) { - saveStream = new byte[abyte0.length]; - System.arraycopy(abyte0, 0, saveStream, 0, abyte0.length); - Log.d(TAG, "partial stream saved"); - } - else { - byte abyte1[]; - - try { - abyte1 = new byte[j + 2]; - System.arraycopy(abyte0, i, abyte1, 0, j + 2); - dsq.put(abyte1); - - if (abyte0.length > abyte1.length + i) - loadStream(abyte0, i + j + 2); - } - catch (Exception ex) { - Log.w(TAG, "load stream error " + ex.getMessage()); - // ex.printStackTrace(); - // dump(abyte0); - } - } - } - - public final byte[] readIncoming() - throws IOException { - boolean done = false; - boolean negotiate = false; - baosin.reset(); - int j = -1; - int i = 0; - Timer timer = new Timer("data.stream", true); - TimerTask task = null; - - while (!done) { - if (bin.available() == 0) { - task = new TimerTask() { - public void run() { - try { - dsq.put(new Integer(0)); // trigger buffer.testChanged() - } - catch (Exception ex) { - Log.w(TAG, "readIncoming error " + ex.getMessage()); - } - } - }; - timer.schedule(task, 10); // 10 ms delay - } - - i = bin.read(); - - if (task != null) { - task.cancel(); - task = null; - } - - // WVL - LDC : 16/07/2003 : TR.000345 - // The inStream return -1 when end-of-stream is reached. This - // happens e.g. when the connection is closed from the AS/400. - // So we stop in this case! - // ==> an empty byte array is returned from this method. - if (i == -1) { // nothing read! - done = true; - vt.disconnect(); - continue; - } - - // We use the values instead of the static values IAC and EOR - // because they are defined as bytes. - // - // The > if(i != 255 || j != 255) < is a hack for the double FF FF's - // that are being returned. I do not know why this is like this and - // can not find any documentation for it. It is also being returned - // on my Client Access tcp dump as well so they are handling it. - // - // my5250 - // 0000: 00 50 DA 44 C8 45 42 00 00 00 00 24 08 00 45 00 .P.D.EB....$..E. - // 0010: 04 2A BC F9 00 00 40 06 D0 27 C1 A8 33 04 C1 A8 .*....@..'..3... - // 0020: 33 58 00 17 04 18 6F A2 83 CB 00 1E D1 BA 50 18 3X....o.......P. - // 0030: 20 00 8A 9A 00 00 03 FF FF 12 A0 00 00 04 00 00 ............... - // --------------------------- || || ------------------------------------- - // 0040: 03 04 40 04 11 00 20 01 07 00 00 00 18 00 00 10 ..@... ......... - - if (j == 255 && i == 255) { - j = -1; - continue; - } - - baosin.write(i); - - // check for end of record EOR and IAC - FFEF - if (j == 255 && i == 239) - done = true; - - // This is to check for the TELNET TIMING MARK OPTION - // rfc860 explains this in more detail. When we receive it - // we will negotiate with the server by sending a WONT'T TIMING-MARK - // This will let the server know that we processed the information - // and are just waiting for the user to enter some data so keep the - // socket alive. This is more or less a AYT (ARE YOU THERE) or not. - if (i == 253 && j == 255) { - done = true; - negotiate = true; - } - - j = i; - } - - // after the initial negotiation we might get other options such as - // timing marks ?????????????? do we ???????????? look at telnet spec - // yes we do. rfc860 explains about timing marks. - // WVL - LDC : 17/05/2004 : Device name negotiations send TIMING MARK - // to existing device! - // Handled incorrectly: we cannot continue processing the TIMING MARK DO - // after we have handled it in the vt.negotiate() - // We should not return the bytes; - // ==> restructured to return null after negotiation! - // Impacts the run method! Added the null check. - byte[] rBytes = baosin.toByteArray(); - - if (dumpBytes) { - dump(rBytes); - } - - if (negotiate) { - if (bin.available() == 0) { - task = new TimerTask() { - public void run() { - try { - dsq.put(new Integer(0)); // trigger buffer.testChanged() - } - catch (Exception ex) { - Log.w(TAG, "readIncoming error " + ex.getMessage()); - } - } - }; - timer.schedule(task, 10); // 10 ms delay - } - - // get the negotiation option - baosin.write(bin.read()); - - if (task != null) { - task.cancel(); - task = null; - } - - vt.negotiate(rBytes); - return null; - } - - return rBytes; - } - - protected final void toggleDebug(ICodePage cp) { - if (codePage == null) - codePage = cp; - - dumpBytes = !dumpBytes; - - if (dumpBytes) { - try { - if (fw == null) { - fw = new FileOutputStream("log.txt"); - dw = new BufferedOutputStream(fw); - } - } - catch (FileNotFoundException fnfe) { - Log.w(TAG, fnfe.getMessage()); - } - } - else { - try { - if (dw != null) - dw.close(); - - if (fw != null) - fw.close(); - - dw = null; - fw = null; - codePage = null; - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - } - } - - Log.i(TAG, "Data Stream output is now " + dumpBytes); - } - - public void dump(byte[] abyte0) { - try { - Log.i(TAG, "\n Buffer Dump of data from AS400: "); - dw.write("\r\n Buffer Dump of data from AS400: ".getBytes()); - StringBuffer h = new StringBuffer(); - - for (int x = 0; x < abyte0.length; x++) { - if (x % 16 == 0) { - System.out.println(" " + h.toString()); - dw.write((" " + h.toString() + "\r\n").getBytes()); - h.setLength(0); - h.append("+0000"); - h.setLength(5 - Integer.toHexString(x).length()); - h.append(Integer.toHexString(x).toUpperCase()); - System.out.print(h.toString()); - dw.write(h.toString().getBytes()); - h.setLength(0); - } - - char ac = codePage.ebcdic2uni(abyte0[x]); - - if (ac < ' ') - h.append('.'); - else - h.append(ac); - - if (x % 4 == 0) { - System.out.print(" "); - dw.write((" ").getBytes()); - } - - if (Integer.toHexString(abyte0[x] & 0xff).length() == 1) { - System.out.print("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()); - dw.write(("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes()); - } - else { - System.out.print(Integer.toHexString(abyte0[x] & 0xff).toUpperCase()); - dw.write((Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes()); - } - } - - System.out.println(); - dw.write("\r\n".getBytes()); - dw.flush(); - } - catch (EOFException _ex) { } - catch (Exception _ex) { - Log.w(TAG, "Cannot dump from host\n\r"); - } - } - -// public void dumpBytes() { -// byte shit[] = bk.buffer; -// for (int i = 0;i < shit.length;i++) -// System.out.println(i + ">" + shit[i] + "< - ascii - >" + getASCIIChar(shit[i]) + "<"); -// } -// -// public void dumpHexBytes(byte[] abyte) { -// byte shit[] = abyte; -// for (int i = 0;i < shit.length;i++) -// System.out.println(i + ">" + shit[i] + "< hex >" + Integer.toHexString((shit[i] & 0xff))); -// } - -}
--- a/src/org/tn5250j/framework/tn5250/KbdTypesCodePages.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -package org.tn5250j.framework.tn5250; - -/** - * IBM i 7.1 Information Center > Programmierung > i5/OS globalization > Globalization reference information > Keyboard reference information - * - * @see <a href="http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=/nls/rbagsnatlangkeybrdtype.htm">National language keyboard types and SBCS code pages</a> - */ -public enum KbdTypesCodePages { - - ALI("Albanian", "ALI", "697", "500", "500"), - CLB("Arabic", "CLB", "235", "420", "420"), - AGB("Austrian/ German", "AGB", "697", "273", "273"), - AGE("Austrian/ German", "AGB", "695", "1141", "1141"), - AGI("Austrian/German (MNCS)", "AGI", "697", "500", "500"), - BLI("Belgian MNCS", "BLI", "697", "500", "500"), - BRB("Brazilian Portuguese", "BRB", "697", "37", "37"), - BGB("Bulgarian", "BGB", "1150", "1025", "1025"), - CAB("Canadian French", "CAB", "341", "260", "65535"), - CAI("Canadian French MNCS", "CAI", "697", "500", "500"), -// YGI("Croatian","YGI","959","870","870"), - CYB("Cyrillic", "CYB", "960", "880", "880"), - CSB("Czech", "CSB", "959", "870", "870"), - DMB("Danish", "DMB", "697", "277", "277"), - DMI("Danish MNCS", "DMI", "697", "500", "500"), - FNB("Finnish/Swedish", "FNB", "697", "278", "278"), - FNI("Finnish/Swedish MNCS", "FNI", "697", "500", "500"), - FAB("French (Azerty)", "FAB", "697", "297", "297"), - FAI("French (Azerty) MNCS", "FAI", "697", "500", "500"), - FQB("French (Qwerty)", "FQB", "697", "297", "297"), - FQI("French (Qwerty) MNCS", "FQI", "697", "500", "500"), - GNB("Greek (See note 2.)", "GNB", "925", "875", "875"), - NCB("Hebrew", "NCB", "941", "424", "424"), - HNB("Hungarian", "HNB", "959", "870", "870"), - ICB("Icelandic", "ICB", "697", "871", "871"), - ICI("Icelandic MNCS", "ICI", "697", "500", "500"), - INB("International", "INB", "697", "500", "500"), - INBX("International-X", "INB", "697", "500", "500-ch"), -// INB("International MNCS","INB","697","500","500"), - IRB("Farsi (Iran)", "IRB", "1219", "1097", "1097"), - ITB("Italian", "ITB", "697", "280", "280"), - ITI("Italian MNCS", "ITI", "697", "500", "500"), - JEB("Japanese-English", "JEB", "697", "281", "65535"), - JEI("Japanese- English MNCS", "JEI", "697", "500", "500"), - JKB("Japanese Kanji and Katakana", "JKB", "1172", "290", "5026"), -// JUB("Japanese Kanji and US English","JUB","697","37","See note 3."), - KAB("Japanese Katakana", "KAB", "332", "290", "290"), - JPB("Japanese Latin Extended", "JPB", "1172", "1027", "1027"), - KOB("Korean", "KOB", "1173", "833", "833"), - ROB("Latin 2", "ROB", "959", "870", "870"), - MKB("Macedonian", "MKB", "1150", "1025", "1025"), - NEB("Dutch (Netherlands)", "NEB", "697", "37", "37"), - NEI("Dutch (Netherlands) MNCS", "NEI", "697", "500", "500"), - NWB("Norwegian", "NWB", "697", "277", "277"), - NWI("Norwegian MNCS", "NWI", "697", "500", "500"), - PLB("Polish", "PLB", "959", "870", "870"), - PLBX("Polish 870-pl", "PLB", "959", "870", "870-pl"), // Workaround, to catch up Java codepage '870-pl' - PRB("Portuguese", "PRB", "697", "37", "37"), - PRI("Portuguese MNCS", "PRI", "697", "500", "500"), - RMB("Romanian", "RMB", "959", "870", "870"), - RUB("Russian", "RUB", "1150", "1025", "1025"), - SQB("Serbian, Cyrillic", "SQB", "1150", "1025", "1025"), - YGI("Serbian, Latin", "YGI", "959", "870", "870"), - RCB("Simplified Chinese", "RCB", "1174", "836", "836"), - SKB("Slovakian", "SKB", "959", "870", "870"), - SKBX("Slovakian 870-sk", "SKB", "959", "870", "870-sk"), // Workaround, to catch up Java codepage '870-sk' -// YGI("Slovenian","YGI","959","870","870"), - SPB("Spanish", "SPB", "697", "284", "284"), - SPI("Spanish MNCS", "SPI", "697", "500", "500"), - SSB("Spanish Speaking", "SSB", "697", "284", "284"), - SSI("Spanish Speaking MNCS", "SSI", "697", "500", "500"), - SWB("Swedish", "SWB", "697", "278", "278"), - SWI("Swedish MNCS", "SWI", "697", "500", "500"), - SFI("French (Switzerland) MNCS", "SFI", "697", "500", "500"), - SGI("German (Switzerland) MNCS", "SGI", "697", "500", "500"), - THB("Thai", "THB", "1176", "838", "838"), - TAB("Traditional Chinese", "TAB", "1175", "37", "937"), - TKB("Turkish (Qwerty)", "TKB", "1152", "1026", "1026"), - TRB("Turkish (F)", "TRB", "1152", "1026", "1026"), - UKB("English (United Kingdom)", "UKB", "697", "285", "285"), - UKI("English (United Kingdom) MNCS", "UKI", "697", "500", "500"), - USB("English (United States and Canada)", "USB", "697", "37", "37"), - USI("English (United States and Canada) MNCS", "USI", "697", "500", "500"); - - public final String description; - public final String kbdType; - public final String charset; - public final String codepage; - public final String ccsid; - - /** - * @param description - * @param kbdType - * @param charset - * @param codepage - * @param ccsid - */ - private KbdTypesCodePages(String description, String kbdType, String charset, String codepage, String ccsid) { - this.description = description; - this.kbdType = kbdType; - this.charset = charset; - this.codepage = codepage; - this.ccsid = ccsid; - } - - @Override - public String toString() { - return "[description=" + description + ", kbdType=" + kbdType - + ", charset=" + charset + ", codepage=" + codepage - + ", ccsid=" + ccsid + "]"; - } - -}
--- a/src/org/tn5250j/framework/tn5250/KeyStrokenizer.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * @(#)KeyStrokenizer.java - * Copyright: Copyright (c) 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ - -package org.tn5250j.framework.tn5250; - -import android.util.Log; - - - -public class KeyStrokenizer { - private static final String TAG = "KeyStrokenizer"; - private StringBuffer keyStrokes; - private StringBuffer sb; - private int index; - private int length; - - - - public KeyStrokenizer() { - sb = new StringBuffer(); - setKeyStrokes(null); - } - - public void setKeyStrokes(String strokes) { - if (strokes != null) { - keyStrokes.setLength(0); - Log.d(TAG, "set " + strokes); - length = strokes.length(); - } - else { - keyStrokes = new StringBuffer(); - length = 0; - } - - keyStrokes.append(strokes); - index = 0; - } - - public boolean hasMoreKeyStrokes() { - return length > index; - } - - public String nextKeyStroke() { - String s = ""; - boolean gotOne = false; - - if (length > index) { - sb.setLength(0); - char c = keyStrokes.charAt(index); - - switch (c) { - case '[': - sb.append(c); - index++; - - // we need to throw an error here - if (index >= length) { - Log.w(TAG, " mnemonic key was incomplete :1 " + - "at position " + index + " len " + length); - } - else { - c = keyStrokes.charAt(index); - - if (c == '[') - index++; - else { - while (!gotOne) { - if (c == ']') { // did we find an ending - sb.append(c); - index++; - gotOne = true; - } - else { - sb.append(c); - index++; - - // we need to throw an error here because we did not - // find an ending for the potential mnemonic - if (index >= length) { - Log.w(TAG, - " mnemonic key was incomplete ending not found :2 " + - "at position " + index); - } - - c = keyStrokes.charAt(index); - } - } - } - } - - break; - - case ']': - index++; - - if (index >= length) { - Log.w(TAG, - " mnemonic key was incomplete ending not found :3 " + - "at position " + index); - sb.append(c); - index++; - } - else { - c = keyStrokes.charAt(index); - - if (c == ']') { - sb.append(c); - index++; - } - else { - Log.w(TAG, - " mnemonic key was incomplete beginning not found :4 " + - "at position " + index); - } - } - - break; - - default: - sb.append(c); - index++; - break; - } - - if (sb != null) { - s = new String(sb); - } - } - - Log.d(TAG, "next " + keyStrokes); - return s; - } - - public String getUnprocessedKeyStroked() { - if (index >= length) { - return null; - } - - return keyStrokes.substring(index); - } - -} \ No newline at end of file
--- a/src/org/tn5250j/framework/tn5250/Rect.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/** - * $Id: Rect.java 1092 2011-01-16 20:27:56Z master_jaf $ - * - * Title: tn5250J - * Copyright: Copyright (c) 2001,2009 - * Company: - * @author: master_jaf - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.framework.tn5250; - - -/** - * Simplified rectangle class. Very much similar like java.awt.Rectangle, - * but we want to decouple the packages ... - */ -public class Rect { - - /* default */ int x; - /* default */ int y; - /* default */ int height; - /* default */ int width; - - /** - * @param rect - */ - public void setBounds(Rect rect) { - setBounds(rect.x, rect.y, rect.width, rect.height); - } - - /** - * @param x the new X coordinate for the upper-left corner of this rectangle - * @param y the new Y coordinate for the upper-left corner of this rectangle - * @param width the new width for this rectangle - * @param height the new height for this rectangle - */ - public void setBounds(int x, int y, int width, int height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - -}
--- a/src/org/tn5250j/framework/tn5250/Screen5250.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3738 +0,0 @@ -/* - * Title: Screen5250.java - * Copyright: Copyright (c) 2001 - 2004 - * Company: - * @author Kenneth J. Pouncey - * @version 0.5 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.framework.tn5250; - -import static org.tn5250j.TN5250jConstants.*; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.Vector; - -import org.tn5250j.TN5250jConstants; - -import android.util.Log; -import de.mud.terminal.VDUBuffer; -import de.mud.terminal.vt320; -import com.five_ten_sg.connectbot.service.FontSizeChangedListener; - - -public class Screen5250 implements FontSizeChangedListener { - private static final String TAG = "Screen5250"; - private ScreenFields screenFields; - private int lastAttr; - private int lastPos; - private int lenScreen; - private KeyStrokenizer strokenizer; - private tnvt sessionVT; - private vt320 buffer; // used to draw the screen - private int numRows = 0; - private int numCols = 0; - protected static final int initAttr = 32; - protected static final char initChar = 0; - public boolean cursorActive = false; - public boolean cursorShown = false; - protected boolean insertMode = false; - private boolean keyProcessed = false; - private Rect dirtyScreen = new Rect(); - - public int homePos = 0; - public int saveHomePos = 0; - private String bufferedKeys; - public boolean pendingInsert = false; - - public final static byte STATUS_SYSTEM = 1; - public final static byte STATUS_ERROR_CODE = 2; - public final static byte STATUS_VALUE_ON = 1; - public final static byte STATUS_VALUE_OFF = 2; - - private StringBuffer hsMore = new StringBuffer("More..."); - private StringBuffer hsBottom = new StringBuffer("Bottom"); - - // error codes to be sent to the host on an error - private final static int ERR_CURSOR_PROTECTED = 0x05; - private final static int ERR_INVALID_SIGN = 0x11; - private final static int ERR_NO_ROOM_INSERT = 0x12; - private final static int ERR_NUMERIC_ONLY = 0x09; - private final static int ERR_DUP_KEY_NOT_ALLOWED = 0x19; - private final static int ERR_NUMERIC_09 = 0x10; - private final static int ERR_FIELD_MINUS = 0x16; - private final static int ERR_FIELD_EXIT_INVALID = 0x18; - private final static int ERR_ENTER_NO_ALLOWED = 0x20; - private final static int ERR_MANDATORY_ENTER = 0x21; - - private boolean guiInterface = false; - private boolean resetRequired = false; - private boolean backspaceError = true; - private boolean feError; - - // Operator Information Area - private ScreenOIA oia; - - // screen planes - protected ScreenPlanes planes; - - - - public Screen5250() { - try { - jbInit(); - } - catch (Exception ex) { - Log.w(TAG, "In constructor: ", ex); - } - } - - void jbInit() throws Exception { - lastAttr = 32; - // default number of rows and columns - numRows = 24; - numCols = 80; - setCursor(1, 1); // set initial cursor position - oia = new ScreenOIA(this); - oia.setKeyBoardLocked(true); - lenScreen = numRows * numCols; - planes = new ScreenPlanes(this, numRows); - screenFields = new ScreenFields(this); - strokenizer = new KeyStrokenizer(); - } - - protected ScreenPlanes getPlanes() { - return planes; - } - - public final ScreenOIA getOIA() { - return oia; - } - - protected final void setRowsCols(int rows, int cols) { - int oldRows = numRows; - int oldCols = numCols; - // default number of rows and columns - numRows = rows; - numCols = cols; - lenScreen = numRows * numCols; - planes.setSize(rows); - - // If they are not the same then we need to inform the listeners that - // the size changed. - if (oldRows != numRows || oldCols != numCols) - fireScreenSizeChanged(); - } - - - public boolean isCursorActive() { - return cursorActive; - } - - public boolean isCursorShown() { - return cursorShown; - } - - public void setUseGUIInterface(boolean gui) { - guiInterface = gui; - } - - public void toggleGUIInterface() { - guiInterface = !guiInterface; - } - - public void setResetRequired(boolean reset) { - resetRequired = reset; - } - - public void setBackspaceError(boolean onError) { - backspaceError = onError; - } - - /** - * Copy & Paste support - * - * @see {@link #pasteText(String, boolean)} - * @see {@link #copyTextField(int)} - */ - public final String copyText(Rect area) { - StringBuilder sb = new StringBuilder(); - Rect workR = new Rect(); - workR.setBounds(area); - Log.d(TAG, "Copying " + workR); - // loop through all the screen characters to send them to the clip board - int m = workR.x; - int i = 0; - int t = 0; - - while (workR.height-- > 0) { - t = workR.width; - i = workR.y; - - while (t-- > 0) { - // only copy printable characters (in this case >= ' ') - char c = planes.getChar(getPos(m - 1, i - 1)); - - if (c >= ' ' && (planes.screenExtended[getPos(m - 1, i - 1)] & EXTENDED_5250_NON_DSP) - == 0) - sb.append(c); - else - sb.append(' '); - - i++; - } - - sb.append('\n'); - m++; - } - - return sb.toString(); - } - - /** - * Copy & Paste support - * - * @param content - * @see {@link #copyText(Rectangle)} - */ - public final void pasteText(String content, boolean special) { - Log.d(TAG, "Pasting, special:" + special); - setCursorActive(false); - StringBuilder sb = new StringBuilder(content); - StringBuilder pd = new StringBuilder(); - // character counters within the string to be pasted. - int nextChar = 0; - int nChars = sb.length(); - int lr = getRow(lastPos); - int lc = getCol(lastPos); - resetDirty(lastPos); - int cpos = lastPos; - int length = getScreenLength(); - char c = 0; - boolean setIt; - // save our current place within the FFT. - screenFields.saveCurrentField(); - - for (int x = nextChar; x < nChars; x++) { - c = sb.charAt(x); - - if ((c == '\n') || (c == '\r')) { - Log.i(TAG, "pasted cr-lf>" + pd + "<"); - pd.setLength(0); - // if we read in a cr lf in the data stream we need to go - // to the starting column of the next row and start from there - cpos = getPos(getRow(cpos) + 1, lc); - - // If we go paste the end of the screen then let's start over from - // the beginning of the screen space. - if (cpos > length) - cpos = 0; - } - else { - // we will default to set the character always. - setIt = true; - - // If we are in a special paste scenario then we check for valid - // characters to paste. - if (special && (!Character.isLetter(c) && !Character.isDigit(c))) - setIt = false; - - // we will only push a character to the screen space if we are in - // a field - if (isInField(cpos) && setIt) { - planes.setChar(cpos, c); - setDirty(cpos); - screenFields.setCurrentFieldMDT(); - } - - // If we placed a character then we go to the next position. - if (setIt) - cpos++; - - // we will append the information to our debug buffer. - pd.append(c); - } - } - - // if we have anything else not logged then log it out. - if (pd.length() > 0) - Log.i(TAG, "pasted >" + pd + "<"); - - // restore out position within the FFT. - screenFields.restoreCurrentField(); - updateDirty(); - // restore our cursor position. - setCursor(lr + 1, lc + 1); - setCursorActive(true); - } - - /** - * Copy & Paste support - * - * @param position - * @return - * @see {@link #copyText(int)} - */ - public final String copyTextField(int position) { - screenFields.saveCurrentField(); - isInField(position); - String result = screenFields.getCurrentFieldText(); - screenFields.restoreCurrentField(); - return result; - } - - /** - * - * Copy & Paste end code - * - */ - - /** - * Sum them - * - * @param which - * formatting option to use - * @return vector string of numberic values - */ - public final Vector<Double> sumThem(boolean which, Rect area) { - StringBuilder sb = new StringBuilder(); - Rect workR = new Rect(); - workR.setBounds(area); - // gui.rubberband.reset(); - // gui.repaint(); - Log.d(TAG, "Summing"); - // obtain the decimal format for parsing - DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); - DecimalFormatSymbols dfs = df.getDecimalFormatSymbols(); - - if (which) { - dfs.setDecimalSeparator('.'); - dfs.setGroupingSeparator(','); - } - else { - dfs.setDecimalSeparator(','); - dfs.setGroupingSeparator('.'); - } - - df.setDecimalFormatSymbols(dfs); - Vector<Double> sumVector = new Vector<Double>(); - // loop through all the screen characters to send them to the clip board - int m = workR.x; - int i = 0; - int t = 0; - double sum = 0.0; - - while (workR.height-- > 0) { - t = workR.width; - i = workR.y; - - while (t-- > 0) { - // only copy printable numeric characters (in this case >= ' ') - // char c = screen[getPos(m - 1, i - 1)].getChar(); - char c = planes.getChar(getPos(m - 1, i - 1)); - // if (((c >= '0' && c <= '9') || c == '.' || c == ',' || c == '-') - // && !screen[getPos(m - 1, i - 1)].nonDisplay) { - - // TODO: update me here to implement the nonDisplay check as well - if (((c >= '0' && c <= '9') || c == '.' || c == ',' || c == '-')) { - sb.append(c); - } - - i++; - } - - if (sb.length() > 0) { - if (sb.charAt(sb.length() - 1) == '-') { - sb.insert(0, '-'); - sb.deleteCharAt(sb.length() - 1); - } - - try { - Number n = df.parse(sb.toString()); - // System.out.println(s + " " + n.doubleValue()); - sumVector.add(new Double(n.doubleValue())); - sum += n.doubleValue(); - } - catch (ParseException pe) { - Log.w(TAG, pe.getMessage() + " at " - + pe.getErrorOffset()); - } - } - - sb.setLength(0); - m++; - } - - Log.d(TAG, "" + sum); - return sumVector; - } - - public void setVT(tnvt v) { - sessionVT = v; - } - - public void setBuffer(vt320 buffer) { - this.buffer = buffer; - } - - /** - * converts mnemonic string values into aid integers - * - * @see #sendKeys - * @param mnem string mnemonic value - * @return key value of Mnemonic - */ - private int getMnemonicValue(String mnem) { - if (mnemonicMap.containsKey(mnem)) return mnemonicMap.get(mnem); - - return 0; - } - - protected void setPrehelpState(boolean setErrorCode, boolean lockKeyboard, - boolean unlockIfLocked) { - if (oia.isKeyBoardLocked() && unlockIfLocked) - oia.setKeyBoardLocked(false); - else - oia.setKeyBoardLocked(lockKeyboard); - - bufferedKeys = null; - oia.setKeysBuffered(false); - } - - /** - * Activate the cursor on screen - * - * @param activate - */ - public void setCursorActive(boolean activate) { - // System.out.println("cursor active " + updateCursorLoc + " " + - // cursorActive + " " + activate); - if (cursorActive && !activate) { - setCursorOff(); - cursorActive = activate; - } - else { - if (!cursorActive && activate) { - cursorActive = activate; - setCursorOn(); - } - } - } - - /** - * Set the cursor on - */ - public void setCursorOn() { - cursorShown = true; - updateCursorLoc(); - } - - /** - * Set the cursor off - */ - public void setCursorOff() { - cursorShown = false; - updateCursorLoc(); - // System.out.println("cursor off " + updateCursorLoc + " " + - // cursorActive); - } - - /** - * - */ - private void updateCursorLoc() { - if (cursorActive) { - fireCursorChanged(); - } - } - - /** - * The sendKeys method sends a string of keys to the virtual screen. This - * method acts as if keystrokes were being typed from the keyboard. The - * keystrokes will be sent to the location given. The string being passed - * can also contain mnemonic values such as [enter] enter key,[tab] tab key, - * [pf1] pf1 etc... - * - * These will be processed as if you had pressed these keys from the - * keyboard. All the valid special key values are contained in the MNEMONIC - * enumeration: - * - * <table BORDER COLS=2 WIDTH="50%" > - * - * <tr> - * <td>MNEMONIC_CLEAR</td> - * <td>[clear]</td> - * </tr> - * <tr> - * <td>MNEMONIC_ENTER</td> - * <td>[enter]</td> - * </tr> - * <tr> - * <td>MNEMONIC_HELP</td> - * <td>[help]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PAGE_DOWN</td> - * <td>[pgdown]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PAGE_UP</td> - * <td>[pgup]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PRINT</td> - * <td>[print]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF1</td> - * <td>[pf1]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF2</td> - * <td>[pf2]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF3</td> - * <td>[pf3]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF4</td> - * <td>[pf4]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF5</td> - * <td>[pf5]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF6</td> - * <td>[pf6]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF7</td> - * <td>[pf7]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF8</td> - * <td>[pf8]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF9</td> - * <td>[pf9]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF10</td> - * <td>[pf10]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF11</td> - * <td>[pf11]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF12</td> - * <td>[pf12]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF13</td> - * <td>[pf13]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF14</td> - * <td>[pf14]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF15</td> - * <td>[pf15]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF16</td> - * <td>[pf16]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF17</td> - * <td>[pf17]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF18</td> - * <td>[pf18]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF19</td> - * <td>[pf19]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF20</td> - * <td>[pf20]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF21</td> - * <td>[pf21]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF22</td> - * <td>[pf22]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF23</td> - * <td>[pf23]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PF24</td> - * <td>[pf24]</td> - * </tr> - * <tr> - * <td>MNEMONIC_BACK_SPACE</td> - * <td>[backspace]</td> - * </tr> - * <tr> - * <td>MNEMONIC_BACK_TAB</td> - * <td>[backtab]</td> - * </tr> - * <tr> - * <td>MNEMONIC_UP</td> - * <td>[up]</td> - * </tr> - * <tr> - * <td>MNEMONIC_DOWN</td> - * <td>[down]</td> - * </tr> - * <tr> - * <td>MNEMONIC_LEFT</td> - * <td>[left]</td> - * </tr> - * <tr> - * <td>MNEMONIC_RIGHT</td> - * <td>[right]</td> - * </tr> - * <tr> - * <td>MNEMONIC_DELETE</td> - * <td>[delete]</td> - * </tr> - * <tr> - * <td>MNEMONIC_TAB</td> - * <td>"[tab]</td> - * </tr> - * <tr> - * <td>MNEMONIC_END_OF_FIELD</td> - * <td>[eof]</td> - * </tr> - * <tr> - * <td>MNEMONIC_ERASE_EOF</td> - * <td>[eraseeof]</td> - * </tr> - * <tr> - * <td>MNEMONIC_ERASE_FIELD</td> - * <td>[erasefld]</td> - * </tr> - * <tr> - * <td>MNEMONIC_INSERT</td> - * <td>[insert]</td> - * </tr> - * <tr> - * <td>MNEMONIC_HOME</td> - * <td>[home]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD0</td> - * <td>[keypad0]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD1</td> - * <td>[keypad1]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD2</td> - * <td>[keypad2]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD3</td> - * <td>[keypad3]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD4</td> - * <td>[keypad4]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD5</td> - * <td>[keypad5]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD6</td> - * <td>[keypad6]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD7</td> - * <td>[keypad7]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD8</td> - * <td>[keypad8]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD9</td> - * <td>[keypad9]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD_PERIOD</td> - * <td>[keypad.]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD_COMMA</td> - * <td>[keypad,]</td> - * </tr> - * <tr> - * <td>MNEMONIC_KEYPAD_MINUS</td> - * <td>[keypad-]</td> - * </tr> - * <tr> - * <td>MNEMONIC_FIELD_EXIT</td> - * <td>[fldext]</td> - * </tr> - * <tr> - * <td>MNEMONIC_FIELD_PLUS</td> - * <td>[field+]</td> - * </tr> - * <tr> - * <td>MNEMONIC_FIELD_MINUS</td> - * <td>[field-]</td> - * </tr> - * <tr> - * <td>MNEMONIC_BEGIN_OF_FIELD</td> - * <td>[bof]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PA1</td> - * <td>[pa1]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PA2</td> - * <td>[pa2]</td> - * </tr> - * <tr> - * <td>MNEMONIC_PA3</td> - * <td>[pa3]</td> - * </tr> - * <tr> - * <td>MNEMONIC_SYSREQ</td> - * <td>[sysreq]</td> - * </tr> - * <tr> - * <td>MNEMONIC_RESET</td> - * <td>[reset]</td> - * </tr> - * <tr> - * <td>MNEMONIC_ATTN</td> - * <td>[attn]</td> - * </tr> - * <tr> - * <td>MNEMONIC_MARK_LEFT</td> - * <td>[markleft]</td> - * </tr> - * <tr> - * <td>MNEMONIC_MARK_RIGHT</td> - * <td>[markright]</td> - * </tr> - * <tr> - * <td>MNEMONIC_MARK_UP</td> - * <td>[markup]</td> - * </tr> - * <tr> - * <td>MNEMONIC_MARK_DOWN</td> - * <td>[markdown]</td> - * </tr> - * - * </table> - * - * @param text - * The string of characters to be sent - * - * @see #sendAid - * - */ - - public synchronized void sendKeys(String text) { - if (isStatusErrorCode() && !resetRequired) { - setCursorActive(false); - simulateMnemonic(getMnemonicValue("[reset]")); - setCursorActive(true); - } - - if (oia.isKeyBoardLocked()) { - if (text.equals("[reset]") || text.equals("[sysreq]") - || text.equals("[attn]")) { - setCursorActive(false); - simulateMnemonic(getMnemonicValue(text)); - setCursorActive(true); - } - else { - if (isStatusErrorCode()) { - sessionVT.signalBell(); - return; - } - - oia.setKeysBuffered(true); - - if (bufferedKeys == null) bufferedKeys = text; - else bufferedKeys += text; - - return; - } - } - else { - if (oia.isKeysBuffered()) { - if (bufferedKeys != null) { - text = bufferedKeys + text; - } - - oia.setKeysBuffered(false); - bufferedKeys = null; - } - - isInField(); - - if (text.length() == 1 && !text.equals("[") && !text.equals("]")) { - setCursorActive(false); - simulateKeyStroke(text.charAt(0)); - setCursorActive(true); - } - else { - strokenizer.setKeyStrokes(text); - String s; - boolean done = false; - // setCursorOff2(); - setCursorActive(false); - - while (!done) { - if (strokenizer.hasMoreKeyStrokes()) { - isInField(); - s = strokenizer.nextKeyStroke(); - - if (s.length() == 1) { - simulateKeyStroke(s.charAt(0)); - } - else { - simulateMnemonic(getMnemonicValue(s)); - } - - if (oia.isKeyBoardLocked()) { - bufferedKeys = strokenizer - .getUnprocessedKeyStroked(); - - if (bufferedKeys != null) { - oia.setKeysBuffered(true); - } - - done = true; - } - } - else { - done = true; - } - } - - setCursorActive(true); - } - } - } - - /** - * The sendAid method sends an "aid" keystroke to the virtual screen. These - * aid keys can be thought of as special keystrokes, like the Enter key, - * PF1-24 keys or the Page Up key. All the valid special key values are - * contained in the AID_ enumeration: - * - * @param aidKey - * The aid key to be sent to the host - * - * @see #sendKeys - * @see TN5250jConstants#AID_CLEAR - * @see #AID_ENTER - * @see #AID_HELP - * @see #AID_ROLL_UP - * @see #AID_ROLL_DOWN - * @see #AID_ROLL_LEFT - * @see #AID_ROLL_RIGHT - * @see #AID_PRINT - * @see #AID_PF1 - * @see #AID_PF2 - * @see #AID_PF3 - * @see #AID_PF4 - * @see #AID_PF5 - * @see #AID_PF6 - * @see #AID_PF7 - * @see #AID_PF8 - * @see #AID_PF9 - * @see #AID_PF10 - * @see #AID_PF11 - * @see #AID_PF12 - * @see #AID_PF13 - * @see #AID_PF14 - * @see #AID_PF15 - * @see #AID_PF16 - * @see #AID_PF17 - * @see #AID_PF18 - * @see #AID_PF19 - * @see #AID_PF20 - * @see #AID_PF21 - * @see #AID_PF22 - * @see #AID_PF23 - * @see #AID_PF24 - */ - public void sendAid(int aidKey) { - sessionVT.sendAidKey(aidKey); - } - - /** - * Restores the error line and sets the error mode off. - * - */ - protected void resetError() { - restoreErrorLine(); - setStatus(STATUS_ERROR_CODE, STATUS_VALUE_OFF, ""); - } - - protected boolean simulateMnemonic(int mnem) { - boolean simulated = false; - - switch (mnem) { - case AID_CLEAR: - case AID_ENTER: - case AID_PF1: - case AID_PF2: - case AID_PF3: - case AID_PF4: - case AID_PF5: - case AID_PF6: - case AID_PF7: - case AID_PF8: - case AID_PF9: - case AID_PF10: - case AID_PF11: - case AID_PF12: - case AID_PF13: - case AID_PF14: - case AID_PF15: - case AID_PF16: - case AID_PF17: - case AID_PF18: - case AID_PF19: - case AID_PF20: - case AID_PF21: - case AID_PF22: - case AID_PF23: - case AID_PF24: - case AID_ROLL_DOWN: - case AID_ROLL_UP: - case AID_ROLL_LEFT: - case AID_ROLL_RIGHT: - if (!screenFields.isCanSendAid()) { - displayError(ERR_ENTER_NO_ALLOWED); - } - else - sendAid(mnem); - - simulated = true; - break; - - case AID_HELP: - sessionVT.sendHelpRequest(); - simulated = true; - break; - - case AID_PRINT: - sessionVT.hostPrint(1); - simulated = true; - break; - - case BACK_SPACE: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - if (screenFields.getCurrentField().startPos() == lastPos) { - if (backspaceError) - displayError(ERR_CURSOR_PROTECTED); - else { - gotoFieldPrev(); - goto_XY(screenFields.getCurrentField().endPos()); - updateDirty(); - } - } - else { - screenFields.getCurrentField().getKeyPos(lastPos); - screenFields.getCurrentField().changePos(-1); - resetDirty(screenFields.getCurrentField().getCurrentPos()); - shiftLeft(screenFields.getCurrentField().getCurrentPos()); - updateDirty(); - screenFields.setCurrentFieldMDT(); - simulated = true; - } - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - break; - - case BACK_TAB: - if (screenFields.getCurrentField() != null - && screenFields.isCurrentFieldHighlightedEntry()) { - resetDirty(screenFields.getCurrentField().startPos); - gotoFieldPrev(); - updateDirty(); - } - else - gotoFieldPrev(); - - if (screenFields.isCurrentFieldContinued()) { - do { - gotoFieldPrev(); - } - while (screenFields.isCurrentFieldContinuedMiddle() - || screenFields.isCurrentFieldContinuedLast()); - } - - isInField(); - simulated = true; - break; - - case UP: - case MARK_UP: - process_XY(lastPos - numCols); - simulated = true; - break; - - case DOWN: - case MARK_DOWN: - process_XY(lastPos + numCols); - simulated = true; - break; - - case LEFT: - case MARK_LEFT: - process_XY(lastPos - 1); - simulated = true; - break; - - case RIGHT: - case MARK_RIGHT: - process_XY(lastPos + 1); - simulated = true; - break; - - case NEXTWORD: - gotoNextWord(); - simulated = true; - break; - - case PREVWORD: - gotoPrevWord(); - simulated = true; - break; - - case DELETE: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - resetDirty(lastPos); - screenFields.getCurrentField().getKeyPos(lastPos); - shiftLeft(screenFields.getCurrentFieldPos()); - screenFields.setCurrentFieldMDT(); - updateDirty(); - simulated = true; - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - break; - - case TAB: - if (screenFields.getCurrentField() != null - && !screenFields.isCurrentFieldContinued()) { - if (screenFields.isCurrentFieldHighlightedEntry()) { - resetDirty(screenFields.getCurrentField().startPos); - gotoFieldNext(); - updateDirty(); - } - else - gotoFieldNext(); - } - else { - do { - gotoFieldNext(); - } - while (screenFields.getCurrentField() != null - && (screenFields.isCurrentFieldContinuedMiddle() || screenFields - .isCurrentFieldContinuedLast())); - } - - isInField(); - simulated = true; - break; - - case EOF: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - int where = endOfField(screenFields.getCurrentField() - .startPos(), true); - - if (where > 0) { - setCursor((where / numCols) + 1, (where % numCols) + 1); - } - - simulated = true; - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - resetDirty(lastPos); - break; - - case ERASE_EOF: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - int where = lastPos; - resetDirty(lastPos); - - if (fieldExit()) { - screenFields.setCurrentFieldMDT(); - - if (!screenFields.isCurrentFieldContinued()) { - gotoFieldNext(); - } - else { - do { - gotoFieldNext(); - - if (screenFields.isCurrentFieldContinued()) - fieldExit(); - } - while (screenFields.isCurrentFieldContinuedMiddle() - || screenFields.isCurrentFieldContinuedLast()); - } - } - - updateDirty(); - goto_XY(where); - simulated = true; - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - break; - - case ERASE_FIELD: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - int where = lastPos; - lastPos = screenFields.getCurrentField().startPos(); - resetDirty(lastPos); - - if (fieldExit()) { - screenFields.setCurrentFieldMDT(); - - if (!screenFields.isCurrentFieldContinued()) { - gotoFieldNext(); - } - else { - do { - gotoFieldNext(); - - if (screenFields.isCurrentFieldContinued()) - fieldExit(); - } - while (screenFields.isCurrentFieldContinuedMiddle() - || screenFields.isCurrentFieldContinuedLast()); - } - } - - updateDirty(); - goto_XY(where); - simulated = true; - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - break; - - case INSERT: - // we toggle it - oia.setInsertMode(oia.isInsertMode() ? false : true); - break; - - case HOME: - - // position to the home position set - if (lastPos + numCols + 1 != homePos) { - goto_XY(homePos - numCols - 1); - isInField(); - } - else - gotoField(1); - - break; - - case KEYPAD_0: - simulated = simulateKeyStroke('0'); - break; - - case KEYPAD_1: - simulated = simulateKeyStroke('1'); - break; - - case KEYPAD_2: - simulated = simulateKeyStroke('2'); - break; - - case KEYPAD_3: - simulated = simulateKeyStroke('3'); - break; - - case KEYPAD_4: - simulated = simulateKeyStroke('4'); - break; - - case KEYPAD_5: - simulated = simulateKeyStroke('5'); - break; - - case KEYPAD_6: - simulated = simulateKeyStroke('6'); - break; - - case KEYPAD_7: - simulated = simulateKeyStroke('7'); - break; - - case KEYPAD_8: - simulated = simulateKeyStroke('8'); - break; - - case KEYPAD_9: - simulated = simulateKeyStroke('9'); - break; - - case KEYPAD_PERIOD: - simulated = simulateKeyStroke('.'); - break; - - case KEYPAD_COMMA: - simulated = simulateKeyStroke(','); - break; - - case KEYPAD_MINUS: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - int s = screenFields.getCurrentField().getFieldShift(); - - if (s == 3 || s == 5 || s == 7) { - planes.setChar(lastPos, '-'); - resetDirty(lastPos); - advancePos(); - - if (fieldExit()) { - screenFields.setCurrentFieldMDT(); - - if (!screenFields.isCurrentFieldContinued()) { - gotoFieldNext(); - } - else { - do { - gotoFieldNext(); - } - while (screenFields - .isCurrentFieldContinuedMiddle() - || screenFields - .isCurrentFieldContinuedLast()); - } - - simulated = true; - updateDirty(); - - if (screenFields.isCurrentFieldAutoEnter()) - sendAid(AID_ENTER); - } - } - else { - displayError(ERR_FIELD_MINUS); - } - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - break; - - case FIELD_EXIT: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - resetDirty(lastPos); - boolean autoFE = screenFields.isCurrentFieldAutoEnter(); - - if (fieldExit()) { - screenFields.setCurrentFieldMDT(); - - if (!screenFields.isCurrentFieldContinued() && - !screenFields.isCurrentFieldAutoEnter()) { - gotoFieldNext(); - } - else { - do { - gotoFieldNext(); - - if (screenFields.isCurrentFieldContinued()) - fieldExit(); - } - while (screenFields.isCurrentFieldContinuedMiddle() - || screenFields.isCurrentFieldContinuedLast()); - } - } - - updateDirty(); - simulated = true; - - if (autoFE) - sendAid(AID_ENTER); - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - break; - - case FIELD_PLUS: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - resetDirty(lastPos); - boolean autoFE = screenFields.isCurrentFieldAutoEnter(); - - if (fieldExit()) { - screenFields.setCurrentFieldMDT(); - - if (!screenFields.isCurrentFieldContinued() && - !screenFields.isCurrentFieldAutoEnter()) { - gotoFieldNext(); - } - else { - do { - gotoFieldNext(); - } - while (screenFields.isCurrentFieldContinuedMiddle() - || screenFields.isCurrentFieldContinuedLast()); - } - } - - updateDirty(); - simulated = true; - - if (autoFE) - sendAid(AID_ENTER); - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - break; - - case FIELD_MINUS: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - int s = screenFields.getCurrentField().getFieldShift(); - - if (s == 3 || s == 5 || s == 7) { - planes.setChar(lastPos, '-'); - resetDirty(lastPos); - advancePos(); - boolean autoFE = screenFields.isCurrentFieldAutoEnter(); - - if (fieldExit()) { - screenFields.setCurrentFieldMDT(); - - if (!screenFields.isCurrentFieldContinued() - && !screenFields.isCurrentFieldAutoEnter()) { - gotoFieldNext(); - } - else { - do { - gotoFieldNext(); - } - while (screenFields.isCurrentFieldContinuedMiddle() - || screenFields.isCurrentFieldContinuedLast()); - } - } - - updateDirty(); - simulated = true; - - if (autoFE) - sendAid(AID_ENTER); - } - else { - displayError(ERR_FIELD_MINUS); - } - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - break; - - case BOF: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - int where = screenFields.getCurrentField().startPos(); - - if (where > 0) { - goto_XY(where); - } - - simulated = true; - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - resetDirty(lastPos); - break; - - case SYSREQ: - sessionVT.systemRequest(); - simulated = true; - break; - - case RESET: - if (isStatusErrorCode()) { - resetError(); - isInField(); - updateDirty(); - } - else { - setPrehelpState(false, oia.isKeyBoardLocked(), false); - } - - simulated = true; - break; - - case ATTN: - sessionVT.sendAttentionKey(); - simulated = true; - break; - - case DUP_FIELD: - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - if (screenFields.isCurrentFieldDupEnabled()) { - resetDirty(lastPos); - screenFields.getCurrentField().setFieldChar(lastPos, - (char) 0x1C); - screenFields.setCurrentFieldMDT(); - gotoFieldNext(); - updateDirty(); - simulated = true; - } - else { - displayError(ERR_DUP_KEY_NOT_ALLOWED); - } - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - - break; - - case NEW_LINE: - if (screenFields.getSize() > 0) { - int startRow = getRow(lastPos) + 1; - int startPos = lastPos; - - if (startRow == getRows()) - startRow = 0; - - setCursor(++startRow, 1); - - if (!isInField() && screenFields.getCurrentField() != null - && !screenFields.isCurrentFieldBypassField()) { - while (!isInField() - && screenFields.getCurrentField() != null - && !screenFields.isCurrentFieldBypassField()) { - // lets keep going - advancePos(); - - // Have we looped the screen? - if (lastPos == startPos) { - // if so then go back to starting point - goto_XY(startPos); - break; - } - } - } - } - - simulated = true; - break; - - case FAST_CURSOR_DOWN: - int rowNow = (getCurrentRow() - 1) + 3; - - if (rowNow > getRows() - 1) - rowNow = rowNow - getRows(); - - this.goto_XY(getPos(rowNow, getCurrentCol() - 1)); - simulated = true; - break; - - case FAST_CURSOR_UP: - rowNow = (getCurrentRow() - 1) - 3; - - if (rowNow < 0) - rowNow = (getRows()) + rowNow; - - this.goto_XY(getPos(rowNow, getCurrentCol() - 1)); - simulated = true; - break; - - case FAST_CURSOR_LEFT: - int colNow = (getCurrentCol() - 1) - 3; - rowNow = getCurrentRow() - 1; - - if (colNow <= 0) { - colNow = getColumns() + colNow; - rowNow--; - } - - if (rowNow < 0) - rowNow = getRows() - 1; - - process_XY(getPos(rowNow, colNow)); - simulated = true; - break; - - case FAST_CURSOR_RIGHT: - colNow = (getCurrentCol() - 1) + 3; - rowNow = getCurrentRow() - 1; - - if (colNow >= getColumns()) { - colNow = colNow - getColumns(); - rowNow++; - } - - if (rowNow > getRows() - 1) - rowNow = getRows() - rowNow; - - process_XY(getPos(rowNow, colNow)); - simulated = true; - break; - - default: - Log.i(TAG, " Mnemonic not supported " + mnem); - break; - } - - return simulated; - } - - protected boolean simulateKeyStroke(char c) { - if (isStatusErrorCode() && !Character.isISOControl(c) && !keyProcessed) { - if (resetRequired) return false; - - resetError(); - } - - boolean updateField = false; - boolean numericError = false; - boolean updatePos = false; - boolean autoEnter = false; - - if (!Character.isISOControl(c)) { - if (screenFields.getCurrentField() != null - && screenFields.withinCurrentField(lastPos) - && !screenFields.isCurrentFieldBypassField()) { - if (screenFields.isCurrentFieldFER() - && !screenFields.withinCurrentField(screenFields - .getCurrentFieldPos()) - && lastPos == screenFields.getCurrentField().endPos() - && screenFields.getCurrentFieldPos() > screenFields - .getCurrentField().endPos()) { - displayError(ERR_FIELD_EXIT_INVALID); - feError = true; - return false; - } - - switch (screenFields.getCurrentFieldShift()) { - case 0: // Alpha shift - case 2: // Numeric Shift - case 4: // Kakana Shift - updateField = true; - break; - - case 1: // Alpha Only - if (Character.isLetter(c) || c == ',' || c == '-' - || c == '.' || c == ' ') - updateField = true; - - break; - - case 3: // Numeric only - if (Character.isDigit(c) || c == '+' || c == ',' - || c == '-' || c == '.' || c == ' ') - updateField = true; - else - numericError = true; - - break; - - case 5: // Digits only - if (Character.isDigit(c)) - updateField = true; - else - displayError(ERR_NUMERIC_09); - - break; - - case 7: // Signed numeric - if (Character.isDigit(c) || c == '+' || c == '-') - if (lastPos == screenFields.getCurrentField().endPos() - && (c != '+' && c != '-')) - displayError(ERR_INVALID_SIGN); - else - updateField = true; - else - displayError(ERR_NUMERIC_09); - - break; - } - - if (updateField) { - if (screenFields.isCurrentFieldToUpper()) - c = Character.toUpperCase(c); - - updatePos = true; - resetDirty(lastPos); - - if (oia.isInsertMode()) { - if (endOfField(false) != screenFields.getCurrentField() - .endPos()) - shiftRight(lastPos); - else { - displayError(ERR_NO_ROOM_INSERT); - updatePos = false; - } - } - - if (updatePos) { - screenFields.getCurrentField().getKeyPos( - getRow(lastPos), getCol(lastPos)); - screenFields.getCurrentField().changePos(1); - planes.setChar(lastPos, c); - screenFields.setCurrentFieldMDT(); - - // if we have gone passed the end of the field then goto - // the next field - if (!screenFields.withinCurrentField(screenFields - .getCurrentFieldPos())) { - if (screenFields.isCurrentFieldAutoEnter()) { - autoEnter = true; - } - else if (!screenFields.isCurrentFieldFER()) - gotoFieldNext(); - else { - // screenFields.getCurrentField().changePos(1); - // - // if (screenFields. - // cursorPos == endPos) - // System.out.println("end of field"); - // - // feError != feError; - // if (feError) - // displayError(ERR_FIELD_EXIT_INVALID); - } - } - else - setCursor(screenFields.getCurrentField() - .getCursorRow() + 1, screenFields - .getCurrentField().getCursorCol() + 1); - } - - fireScreenChanged(); - - if (autoEnter) - sendAid(AID_ENTER); - } - else { - if (numericError) { - displayError(ERR_NUMERIC_ONLY); - } - } - } - else { - displayError(ERR_CURSOR_PROTECTED); - } - } - - return updatePos; - } - - /** - * Method: endOfField - * <p> - * - * convenience method that call endOfField with lastRow lastCol and passes - * the posSpace to that method - * - * @param posSpace - * value of type boolean - specifying to return the position of - * the the last space or not - * @return a value of type int - the screen postion (row * columns) + col - * - */ - private int endOfField(boolean posSpace) { - return endOfField(lastPos, posSpace); - } - - /** - * Method: endOfField - * <p> - * - * gets the position of the last character of the current field posSpace - * parameter tells the routine whether to return the position of the last - * space ( <= ' ') or the last non space posSpace == true last occurrence of - * char <= ' ' posSpace == false last occurrence of char > ' ' - * - * @param pos - * value of type int - position to start from - * @param posSpace - * value of type boolean - specifying to return the position of - * the the last space or not - * @return a value of type int - the screen postion (row * columns) + col - * - */ - private int endOfField(int pos, boolean posSpace) { - int endPos = screenFields.getCurrentField().endPos(); - int fePos = endPos; - // get the number of characters to the right - int count = endPos - pos; - - // first lets get the real ending point without spaces and the such - while (planes.getChar(endPos) <= ' ' && count-- > 0) { - endPos--; - } - - if (endPos == fePos) { - return endPos; - } - - screenFields.getCurrentField().getKeyPos(endPos); - - if (posSpace) screenFields.getCurrentField().changePos(+1); - - return screenFields.getCurrentFieldPos(); - } - - private boolean fieldExit() { - int pos = lastPos; - boolean mdt = false; - int end = endOfField(false); // get the ending position of the first - // non blank character in field - ScreenField sf = screenFields.getCurrentField(); - - if (sf.isMandatoryEnter() && end == sf.startPos()) { - displayError(ERR_MANDATORY_ENTER); - return false; - } - - // save off the current pos of the field for checking field exit required - // positioning. the getKeyPos resets this information so it is useless - // for comparing if we are positioned passed the end of field. - // Maybe this should be changed to not update the current cursor position - // of the field. - int currentPos = sf.getCurrentPos(); - // get the number of characters to the right - int count = (end - sf.startPos()) - sf.getKeyPos(pos); - - if (count == 0 && sf.isFER()) { - if (currentPos > sf.endPos()) { - mdt = true; - return mdt; - } - } - - for (; count >= 0; count--) { - planes.setChar(pos, initChar); - setDirty(pos); - pos++; - mdt = true; - } - - // This checks for a field minus because a field minus places - // a negative sign and then advances a position. If it is the - // end of the field where the minus is placed then this offset will - // place the count as -1. - if (count == -1) { - int s = sf.getFieldShift(); - - if (s == 3 || s == 5 || s == 7) { - mdt = true; - } - } - - int adj = sf.getAdjustment(); - - if (adj != 0) { - switch (adj) { - case 5: - rightAdjustField('0'); - sf.setRightAdjusted(); - break; - - case 6: - rightAdjustField(' '); - sf.setRightAdjusted(); - break; - - case 7: - sf.setMandatoryEntered(); - break; - } - } - else { - // we need to right adjust signed numeric fields as well. - if (sf.isSignedNumeric()) { - rightAdjustField(' '); - } - } - - return mdt; - } - - private void rightAdjustField(char fill) { - int end = endOfField(false); // get the ending position of the first - // non blank character in field - // get the number of characters to the right - int count = screenFields.getCurrentField().endPos() - end; - - // subtract 1 from count for signed numeric - note for later - if (screenFields.getCurrentField().isSignedNumeric()) { - if (planes.getChar(end - 1) != '-') - count--; - } - - int pos = screenFields.getCurrentField().startPos(); - - while (count-- >= 0) { - shiftRight(pos); - planes.setChar(pos, fill); - setDirty(pos); - } - } - - private void shiftLeft(int sPos) { - int endPos = 0; - int pos = sPos; - int pPos = sPos; - ScreenField sf = screenFields.getCurrentField(); - int end; - int count; - - do { - end = endOfField(pPos, false); // get the ending position of the - // first - // non blank character in field - count = (end - screenFields.getCurrentField().startPos()) - - screenFields.getCurrentField().getKeyPos(pPos); - - // now we loop through and shift the remaining characters to the - // left - while (count-- > 0) { - pos++; - planes.setChar(pPos, planes.getChar(pos)); - setDirty(pPos); - pPos = pos; - } - - if (screenFields.isCurrentFieldContinued()) { - gotoFieldNext(); - - if (screenFields.getCurrentField().isContinuedFirst()) - break; - - pos = screenFields.getCurrentField().startPos(); - planes.setChar(pPos, planes.getChar(pos)); - setDirty(pPos); - pPos = pos; - } - } - while (screenFields.isCurrentFieldContinued() - && !screenFields.getCurrentField().isContinuedFirst()); - - if (end >= 0 && count >= -1) { - endPos = end; - } - else { - endPos = sPos; - } - - screenFields.setCurrentField(sf); - planes.setChar(endPos, initChar); - setDirty(endPos); - goto_XY(screenFields.getCurrentFieldPos()); - sf = null; - } - - private void shiftRight(int sPos) { - int end = endOfField(true); // get the ending position of the first - // non blank character in field - int pos = end; - int pPos = end; - int count = end - sPos; - - // now we loop through and shift the remaining characters to the right - while (count-- > 0) { - pos--; - planes.setChar(pPos, planes.getChar(pos)); - setDirty(pPos); - pPos = pos; - } - } - - public int getRow(int pos) { - // if (pos == 0) - // return 1; - int row = pos / numCols; - - if (row < 0) { - row = lastPos / numCols; - } - - if (row > (lenScreen / numCols) - 1) - row = (lenScreen / numCols) - 1; - - return row; - } - - public int getCol(int pos) { - int col = pos % (getColumns()); - - if (col > 0) return col; - - return 0; - } - - /** - * This routine is 0 based offset. So to get row 20,1 then pass row 19,0 - * - * @param row - * @param col - * @return - */ - public int getPos(int row, int col) { - return (row * numCols) + col; - } - - /** - * Current position is based on offsets of 1,1 not 0,0 of the current - * position of the screen - * - * @return int - */ - public int getCurrentPos() { - // return lastPos + numCols + 1; - return lastPos + 1; - } - - /** - * I got this information from a tcp trace of each error. I could not find - * any documenation for this. Maybe there is but I could not find it. If - * anybody finds this documention could you please send me a copy. Please - * note that I did not look that hard either. - * <p> - * 0000: 00 50 73 1D 89 81 00 50 DA 44 C8 45 08 00 45 00 .Ps....P.D.E..E. - * </p> - * <p> - * 0010: 00 36 E9 1C 40 00 80 06 9B F9 C1 A8 33 58 C0 A8 .6..@...k....3X.. - * </p> - * <p> - * 0020: C0 02 06 0E 00 17 00 52 6E 88 73 40 DE CB 50 18 .......Rn.s@..P. - * </p> - * <p> - * 0030: 20 12 3C 53 00 00 00 0C 12 A0 00 00 04 01 00 00 . <S............ - * </p> - * <p> - * 0040: 00 05 FF EF .... ----------|| The 00 XX is the code to be sent. I - * found the following <table BORDER COLS=2 WIDTH="50%" > - * <tr> - * <td>ERR_CURSOR_PROTECTED</td> - * <td>0x05</td> - * </tr> - * <tr> - * <td>ERR_INVALID_SIGN</td> - * <td>0x11</td> - * </tr> - * <tr> - * <td>ERR_NO_ROOM_INSERT</td> - * <td>0x12</td> - * </tr> - * <tr> - * <td>ERR_NUMERIC_ONLY</td> - * <td>0x09</td> - * </tr> - * <tr> - * <td>ERR_NUMERIC_09</td> - * <td>0x10</td> - * </tr> - * <tr> - * <td>ERR_FIELD_MINUS</td> - * <td>0x16</td> - * </tr> - * <tr> - * <td>ERR_ENTER_NOT_ALLOWED</td> - * <td>0x20</td> - * </tr> - * <tr> - * <td>ERR_MANDATORY_ENTER</td> - * <td>0x21</td> - * </tr> - * <tr> - * <td>ERR_ENTER_NOT_ALLOWED</td> - * <td>0x20</td> - * </tr> - * </table> I am tired of typing and they should be self explanitory. Finding - * them in the first place was the pain. - * </p> - * - * @param ec error code - */ - private void displayError(int ec) { - saveHomePos = homePos; - homePos = lastPos + numCols + 1; - pendingInsert = true; - sessionVT.sendNegResponse2(ec); - } - - private void process_XY(int pos) { - if (pos < 0) - pos = lenScreen + pos; - - if (pos > lenScreen - 1) - pos = pos - lenScreen; - - // if there was a field exit error then we need to treat the movement - // of the cursor in a special way that equals that of Client Access. - // If the cursor is moved from the field then we need to reset the - // position within the field so that the last character can be typed - // over again instead of sending the field exit error again. - // We also need to reset the field exit error flag. - // - // How we know we have a field exit error is when the field position is - // set beyond the end of the field and a character is then typed we can - // not position that character. To reset this we need to set the next - // position of the field to not be beyond the end of field but to the - // last character. - // - // Now to make it work like Client Access if the cursor is a back space - // then do not move the cursor but place it on the last field. All - // other keys will reset the field position so that entering over the - // last character will not cause an error but replace that character or - // just plain move the cursor if the key was to do that. - ScreenField sf = screenFields.getCurrentField(); - - if (feError) { - feError = false; - sf.changePos(-1); - } - else { - if (sf != null && sf.isFER()) { - if ((sf.getCurrentPos() - > sf.endPos())) { - if (sf.withinField(pos)) { - sf.getKeyPos(pos); - return; - } - - sf.getKeyPos(sf.endPos()); - } - } - - goto_XY(pos); - } - } - - public boolean isUsingGuiInterface() { - return guiInterface; - } - - /** - * Convinience class to return if the cursor is in a field or not. - * - * @return true or false - */ - - protected boolean isInField() { - return isInField(lastPos, true); - } - - /** - * - * Convinience class to return if the position that is passed is in a field - * or not. If it is then the chgToField parameter will change the current - * field to this field where the position indicates - * - * @param pos - * @param chgToField - * @return true or false - */ - public boolean isInField(int pos, boolean chgToField) { - return screenFields.isInField(pos, chgToField); - } - - /** - * - * Convinience class to return if the position that is passed is in a field - * or not. If it is then the field at this position becomes the current - * working field - * - * @param pos - * @return true or false - */ - public boolean isInField(int pos) { - return screenFields.isInField(pos, true); - } - - /** - * Convinience class to return if the position at row and column that is - * passed is in a field or not. If it is then the field at this position - * becomes the current working field. - * - * @param row - * @param col - * @return true or false - */ - public boolean isInField(int row, int col) { - return isInField(row, col, true); - } - - /** - * - * Convinience class to return if the position at row and column that is - * passed is in a field or not. If it is then the chgToField parameter will - * change the current field to this field where the row and column - * indicates. - * - * @param row - * @param col - * @param chgToField - * @return true or false - */ - public boolean isInField(int row, int col, boolean chgToField) { - return screenFields.isInField((row * numCols) + col, chgToField); - } - - /** - * Gets the length of the screen - number of rows times number of columns - * - * @return int value of screen length - */ - public int getScreenLength() { - return lenScreen; - } - - /** - * Get the number or rows available. - * - * @return number of rows - */ - public int getRows() { - return numRows; - } - - /** - * Get the number of columns available. - * - * @return number of columns - */ - public int getColumns() { - return numCols; - } - - /** - * Get the current row where the cursor is - * - * @return the cursor current row position 1,1 based - */ - public int getCurrentRow() { - return (lastPos / numCols) + 1; - } - - /** - * Get the current column where the cursor is - * - * @return the cursor current column position 1,1 based - */ - public int getCurrentCol() { - return (lastPos % numCols) + 1; - } - - /** - * The last position of the cursor on the screen - Note - position is based - * 0,0 - * - * @return last position - */ - protected int getLastPos() { - return lastPos; - } - - /** - * Hotspot More... string - * - * @return string literal of More... - */ - public StringBuffer getHSMore() { - return hsMore; - } - - /** - * Hotspot Bottom string - * - * @return string literal of Bottom - */ - public StringBuffer getHSBottom() { - return hsBottom; - } - - /** - * - * Return the screen represented as a character array - * - * @return character array containing the text - */ - public char[] getScreenAsChars() { - char[] sac = new char[lenScreen]; - char c; - - for (int x = 0; x < lenScreen; x++) { - c = planes.getChar(x); - - // only draw printable characters (in this case >= ' ') - if ((c >= ' ') && (!planes.isAttributePlace(x))) { - sac[x] = c; - // TODO: implement the underline check here - // if (screen[x].underLine && c <= ' ') - // sac[x] = '_'; - } - else - sac[x] = ' '; - } - - return sac; - } - - public char[] getData(int startRow, int startCol, int endRow, int endCol, int plane) { - try { - int from = getPos(startRow, startCol); - int to = getPos(endRow, endCol); - - if (from > to) { - int f = from; - to = f; - from = f; - } - - return planes.getPlaneData(from, to, plane); - } - catch (Exception oe) { - return null; - } - } - - /** - * <p> - * GetScreen retrieves the various planes associated with the presentation - * space. The data is returned as a linear array of character values in the - * array provided. The array is not terminated by a null character except - * when data is retrieved from the text plane, in which case a single null - * character is appended. - * </p> - * <p> - * The application must supply a buffer for the returned data and the length - * of the buffer. Data is returned starting from the beginning of the - * presentation space and continuing until the buffer is full or the entire - * plane has been copied. For text plane data, the buffer must include one - * extra position for the terminating null character. - * <p> - * - * @param buffer - * @param bufferLength - * @param plane - * @return The number of characters copied to the buffer - * @throws OhioException - */ - - public synchronized int GetScreen(char buffer[], int bufferLength, int plane) - // throws OhioException { - { - return GetScreen(buffer, bufferLength, 0, lenScreen, plane); - } - - /** - * <p> - * GetScreen retrieves the various planes associated with the presentation - * space. The data is returned as a linear array of character values in the - * array provided. The array is not terminated by a null character except - * when data is retrieved from the text plane, in which case a single null - * character is appended. - * </p> - * <p> - * The application must supply a buffer for the returned data and the length - * of the buffer. Data is returned starting from the given position and - * continuing until the specified number of characters have been copied, the - * buffer is full or the entire plane has been copied. For text plane data, - * the buffer must include one extra position for the terminating null character. - * </p> - * - * @param buffer - * @param bufferLength - * @param from - * @param length - * @param plane - * @return The number of characters copied to the buffer - * @throws OhioException - */ - - public synchronized int GetScreen(char buffer[], int bufferLength, int from, - int length, int plane) - // throws OhioException { - { - return planes.GetScreen(buffer, bufferLength, from, length, plane); - } - - /** - * <p> - * GetScreen retrieves the various planes associated with the presentation - * space. The data is returned as a linear array of character values in the - * array provided. The array is not terminated by a null character except - * when data is retrieved from the text plane, in which case a single null - * character is appended. - * </p> - * <p> - * The application must supply a buffer for the returned data and the length - * of the buffer. Data is returned starting from the given coordinates and - * continuing until the specified number of characters have been copied, - * the buffer is full, or the entire plane has been copied. For text plane - * data, the buffer must include one extra position for the terminating null - * character. - * </p> - * - * @param buffer - * @param bufferLength - * @param row - * @param col - * @param length - * @param plane - * @return The number of characters copied to the buffer. - * @throws OhioException - */ - - public synchronized int GetScreen(char buffer[], int bufferLength, int row, - int col, int length, int plane) - // throws OhioException { - { - // Call GetScreen function after converting row and column to - // a position. - return planes.GetScreen(buffer, bufferLength, row, col, length, plane); - } - - /** - * <p> - * GetScreenRect retrieves data from the various planes associated with the - * presentation space. The data is returned as a linear array of character - * values in the buffer provided. - * </p> - * - * <p> - * The application supplies two positions that represent opposing corners of - * a rectangle within the presentation space. The starting and ending - * positions can have any spatial relationship to each other. The data - * returned starts from the row containing the upper-most point to the row - * containing the lower-most point, and from the left-most column to the - * right-most column. - * </p> - * <p> - * The specified buffer must be at least large enough to contain the number - * of characters in the rectangle. If the buffer is too small, no data is - * copied and zero is returned by the method. Otherwise, the method returns - * the number of characters copied. - * </p> - * - * @param buffer - * @param bufferLength - * @param startPos - * @param endPos - * @param plane - * @return The number of characters copied to the buffer - * @throws OhioException - */ - - public synchronized int GetScreenRect(char buffer[], int bufferLength, - int startPos, int endPos, int plane) - // throws OhioException { - { - return planes.GetScreenRect(buffer, bufferLength, startPos, endPos, plane); - } - - /** - * <p> - * GetScreenRect retrieves data from the various planes associated with the - * presentation space. The data is returned as a linear array of character - * values in the buffer provided. The buffer is not terminated by a null - * character. - * </p> - * <p> - * The application supplies two coordinates that represent opposing corners - * of a rectangle within the presentation space. The starting and ending - * coordinates can have any spatial relationship to each other. The data - * returned starts from the row containing the upper-most point to the row - * containing the lower-most point, and from the left-most column to the - * right-most column. - * </p> - * <p> - * The specified buffer must be at least large enough to contain the number - * of characters in the rectangle. If the buffer is too small, no data is - * copied and zero is returned by the method. Otherwise, the method returns - * the number of characters copied. - * </p> - * - * @param buffer - * @param bufferLength - * @param startRow - * @param startCol - * @param endRow - * @param endCol - * @param plane - * @return The number characters copied to the buffer - * @throws OhioException - */ - - public synchronized int GetScreenRect(char buffer[], int bufferLength, - int startRow, int startCol, - int endRow, int endCol, int plane) - // throws OhioException { - { - return planes.GetScreenRect(buffer, bufferLength, startRow, startCol, endRow, - endCol, plane); - } - - public synchronized boolean[] getActiveAidKeys() { - return sessionVT.getActiveAidKeys(); - } - - protected synchronized void setScreenData(String text, int location) { - // throws OhioException { - if (location < 0 || location > lenScreen) { - return; - // throw new OhioException(sessionVT.getSessionConfiguration(), - // OhioScreen5250.class.getName(), "osohio.screen.ohio00300", 1); - } - - int pos = location; - int l = text.length(); - boolean updated = false; - boolean flag = false; - int x = 0; - - for (; x < l; x++) { - if (isInField(pos + x, true)) { - if (!screenFields.getCurrentField().isBypassField()) { - if (!flag) { - screenFields.getCurrentField().setMDT(); - updated = true; - resetDirty(pos + x); - screenFields.setMasterMDT(); - flag = true; - } - - planes.screen[pos + x] = text.charAt(x); - setDirty(pos + x); - } - } - } - - lastPos = pos + x; - - if (updated) { - fireScreenChanged(); - } - } - - /** - * This routine is based on offset 1,1 not 0,0 it will translate to offset - * 0,0 and call the goto_XY(int pos) it is mostly used from external classes - * that use the 1,1 offset - * - * @param row - * @param col - */ - public void setCursor(int row, int col) { - goto_XY(((row - 1) * numCols) + (col - 1)); - } - - // this routine is based on offset 0,0 not 1,1 - protected void goto_XY(int pos) { - lastPos = pos; - updateCursorLoc(); - } - - /* - * set the content of the field at (l,c) to data - * if l == -1, set the current field contents to data - */ - public void setField(int l, int c, char [] data) { - ScreenField cf; - - if (l >= 0) { - lastPos = l * numCols + c; - - while (!isInField()) advancePos(); - - setDirty(lastPos); - fireCursorChanged(); - } - - if ((data != null) && (data.length > 0)) { - cf = screenFields.getCurrentField(); - cf.setString(new String(data)); - lastPos = cf.getStartPos(); - setDirty(lastPos); - setDirty(lastPos + cf.getLength()); - lastPos += data.length; - - if (!isInField()) { - gotoFieldNext(); - isInField(); - cf = screenFields.getCurrentField(); - lastPos = cf.getStartPos(); - } - - setDirty(lastPos); - fireCursorChanged(); - } - - updateDirty(); - } - - /** - * Set the current working field to the field number specified. - * - * @param f - - * numeric field number on the screen - * @return true or false whether it was sucessful - */ - public boolean gotoField(int f) { - int sizeFields = screenFields.getSize(); - - if (f > sizeFields || f <= 0) - return false; - - screenFields.setCurrentField(screenFields.getField(f - 1)); - - while (screenFields.isCurrentFieldBypassField() && f < sizeFields) { - screenFields.setCurrentField(screenFields.getField(f++)); - } - - return gotoField(screenFields.getCurrentField()); - } - - /** - * Convenience method to set the field object passed as the currect working - * screen field - * - * @param f - * @return true or false whether it was sucessful - * @see org.tn5250j.ScreenField - */ - protected boolean gotoField(ScreenField f) { - if (f != null) { - goto_XY(f.startPos()); - return true; - } - - return false; - } - - /** - * Convenience class to position the cursor to the next word on the screen - * - */ - private void gotoNextWord() { - int pos = lastPos; - - if (planes.getChar(lastPos) > ' ') { - advancePos(); - - // get the next space character - while (planes.getChar(lastPos) > ' ' && pos != lastPos) { - advancePos(); - } - } - else - advancePos(); - - // now that we are positioned on the next space character get the - // next none space character - while (planes.getChar(lastPos) <= ' ' && pos != lastPos) { - advancePos(); - } - } - - /** - * Convenience class to position the cursor to the previous word on the - * screen - * - */ - private void gotoPrevWord() { - int pos = lastPos; - changePos(-1); - - // position previous white space character - while (planes.getChar(lastPos) <= ' ') { - changePos(-1); - - if (pos == lastPos) - break; - } - - changePos(-1); - - // get the previous space character - while (planes.getChar(lastPos) > ' ' && pos != lastPos) { - changePos(-1); - } - - // and position one position more should give us the beginning of word - advancePos(); - } - - /** - * Convinience class to position to the next field on the screen. - * - * @see org.tn5250j.ScreenFields - */ - private void gotoFieldNext() { - if (screenFields.isCurrentFieldHighlightedEntry()) - unsetFieldHighlighted(screenFields.getCurrentField()); - - screenFields.gotoFieldNext(); - - if (screenFields.isCurrentFieldHighlightedEntry()) - setFieldHighlighted(screenFields.getCurrentField()); - } - - /** - * Convinience class to position to the previous field on the screen. - * - * @see org.tn5250j.ScreenFields - */ - private void gotoFieldPrev() { - if (screenFields.isCurrentFieldHighlightedEntry()) - unsetFieldHighlighted(screenFields.getCurrentField()); - - screenFields.gotoFieldPrev(); - - if (screenFields.isCurrentFieldHighlightedEntry()) - setFieldHighlighted(screenFields.getCurrentField()); - } - - /* *** NEVER USED LOCALLY ************************************************** */ - // /** - // * Used to restrict the cursor to a particular position on the screen. Used - // * in combination with windows to restrict the cursor to the active window - // * show on the screen. - // * - // * Not supported yet. Please implement me :-( - // * - // * @param depth - // * @param width - // */ - // protected void setRestrictCursor(int depth, int width) { - // - // restrictCursor = true; - // // restriction - // - // } - - /** - * Creates a window on the screen - * - * @param depth - * @param width - * @param type - * @param gui - * @param monoAttr - * @param colorAttr - * @param ul - * @param upper - * @param ur - * @param left - * @param right - * @param ll - * @param bottom - * @param lr - */ - protected void createWindow(int depth, int width, int type, boolean gui, - int monoAttr, int colorAttr, int ul, int upper, int ur, int left, - int right, int ll, int bottom, int lr) { - int c = getCol(lastPos); - int w = 0; - width++; - w = width; - // set leading attribute byte - // screen[lastPos].setCharAndAttr(initChar, initAttr, true); - planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); - setDirty(lastPos); - advancePos(); - // set upper left - // screen[lastPos].setCharAndAttr((char) ul, colorAttr, false); - planes.setScreenCharAndAttr(lastPos, (char) ul, colorAttr, false); - - if (gui) { - // screen[lastPos].setUseGUI(UPPER_LEFT); - planes.setUseGUI(lastPos, UPPER_LEFT); - } - - setDirty(lastPos); - advancePos(); - - // draw top row - - while (w-- >= 0) { - // screen[lastPos].setCharAndAttr((char) upper, colorAttr, false); - planes.setScreenCharAndAttr(lastPos, (char) upper, colorAttr, false); - - if (gui) { - // screen[lastPos].setUseGUI(UPPER); - planes.setUseGUI(lastPos, UPPER); - } - - setDirty(lastPos); - advancePos(); - } - - // set upper right - // screen[lastPos].setCharAndAttr((char) ur, colorAttr, false); - planes.setScreenCharAndAttr(lastPos, (char) ur, colorAttr, false); - - if (gui) { - // screen[lastPos].setUseGUI(UPPER_RIGHT); - planes.setUseGUI(lastPos, UPPER_RIGHT); - } - - setDirty(lastPos); - advancePos(); - // set ending attribute byte - planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); - setDirty(lastPos); - lastPos = ((getRow(lastPos) + 1) * numCols) + c; - - // now handle body of window - while (depth-- > 0) { - // set leading attribute byte - planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); - setDirty(lastPos); - advancePos(); - // set left - planes.setScreenCharAndAttr(lastPos, (char) left, colorAttr, false); - - if (gui) { - planes.setUseGUI(lastPos, GUI_LEFT); - } - - setDirty(lastPos); - advancePos(); - w = width; - - // fill it in - while (w-- >= 0) { - // screen[lastPos].setCharAndAttr(initChar, initAttr, true); - planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); - // screen[lastPos].setUseGUI(NO_GUI); - planes.setUseGUI(lastPos, NO_GUI); - setDirty(lastPos); - advancePos(); - } - - // set right - // screen[lastPos].setCharAndAttr((char) right, colorAttr, false); - planes.setScreenCharAndAttr(lastPos, (char) right, colorAttr, false); - - if (gui) { - // screen[lastPos].setUseGUI(RIGHT); - planes.setUseGUI(lastPos, GUI_RIGHT); - } - - setDirty(lastPos); - advancePos(); - // set ending attribute byte - // screen[lastPos].setCharAndAttr(initChar, initAttr, true); - planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); - setDirty(lastPos); - lastPos = ((getRow(lastPos) + 1) * numCols) + c; - } - - // set leading attribute byte - // screen[lastPos].setCharAndAttr(initChar, initAttr, true); - planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); - setDirty(lastPos); - advancePos(); - // set lower left - // screen[lastPos].setCharAndAttr((char) ll, colorAttr, false); - planes.setScreenCharAndAttr(lastPos, (char) ll, colorAttr, false); - - if (gui) { - // screen[lastPos].setUseGUI(LOWER_LEFT); - planes.setUseGUI(lastPos, LOWER_LEFT); - } - - setDirty(lastPos); - advancePos(); - w = width; - - // draw bottom row - while (w-- >= 0) { - planes.setScreenCharAndAttr(lastPos, (char) bottom, colorAttr, false); - - if (gui) { - planes.setUseGUI(lastPos, BOTTOM); - } - - setDirty(lastPos); - advancePos(); - } - - // set lower right - planes.setScreenCharAndAttr(lastPos, (char) lr, colorAttr, false); - - if (gui) { - planes.setUseGUI(lastPos, LOWER_RIGHT); - } - - setDirty(lastPos); - advancePos(); - // set ending attribute byte - planes.setScreenCharAndAttr(lastPos, initChar, initAttr, true); - setDirty(lastPos); - } - - /** - * Creates a scroll bar on the screen using the parameters provided. - * ** we only support vertical scroll bars at the time. - * - * @param flag - - * type to draw - vertical or horizontal - * @param totalRowScrollable - * @param totalColScrollable - * @param sliderRowPos - * @param sliderColPos - * @param sbSize - */ - protected void createScrollBar(int flag, int totalRowScrollable, - int totalColScrollable, int sliderRowPos, int sliderColPos, - int sbSize) { - // System.out.println("Scrollbar flag: " + flag + - // " scrollable Rows: " + totalRowScrollable + - // " scrollable Cols: " + totalColScrollable + - // " thumb Row: " + sliderRowPos + - // " thumb Col: " + sliderColPos + - // " size: " + sbSize + - // " row: " + getRow(lastPos) + - // " col: " + getCol(lastPos)); - int sp = lastPos; - int size = sbSize - 2; - int thumbPos = (int)(size * ((float) sliderColPos / (float) totalColScrollable)); - // System.out.println(thumbPos); - planes.setScreenCharAndAttr(sp, ' ', 32, false); - planes.setUseGUI(sp, BUTTON_SB_UP); - int ctr = 0; - - while (ctr < size) { - sp += numCols; - planes.setScreenCharAndAttr(sp, ' ', 32, false); - - if (ctr == thumbPos) - planes.setUseGUI(sp, BUTTON_SB_THUMB); - else - planes.setUseGUI(sp, BUTTON_SB_GUIDE); - - ctr++; - } - - sp += numCols; - planes.setScreenCharAndAttr(sp, ' ', 32, false); - planes.setUseGUI(sp, BUTTON_SB_DN); - } - - /** - * Write the title of the window that is on the screen - * - * @param pos - * @param depth - * @param width - * @param orientation - * @param monoAttr - * @param colorAttr - * @param title - */ - protected void writeWindowTitle(int pos, int depth, int width, - byte orientation, int monoAttr, int colorAttr, StringBuffer title) { - int len = title.length(); - - // get bit 0 and 1 for interrogation - switch (orientation & 0xc0) { - case 0x40: // right - pos += (4 + width - len); - break; - - case 0x80: // left - pos += 2; - break; - - default: // center - // this is to place the position to the first text position of the - // window - // the position passed in is the first attribute position, the next - // is the border character and then there is another attribute after - // that. - pos += (3 + ((width / 2) - (len / 2))); - break; - } - - // if bit 2 is on then this is a footer - if ((orientation & 0x20) == 0x20) - pos += ((depth + 1) * numCols); - - // System.out.println(pos + "," + width + "," + len+ "," + getRow(pos) - // + "," + getCol(pos) + "," + ((orientation >> 6) & 0xf0)); - - for (int x = 0; x < len; x++) { - planes.setChar(pos, title.charAt(x)); - planes.setUseGUI(pos++, NO_GUI); - } - } - - /** - * Roll the screen up or down. - * - * Byte 1: Bit 0 0 = Roll up 1 = Roll down Bits 1-2 Reserved Bits 3-7 Number - * of lines that the designated area is to be rolled Byte 2: Bits 0-7 Line - * number defining the top line of the area that will participate in the - * roll. Byte 3: Bits 0-7 Line number defining the bottom line of the area - * that will participate in the roll. - * - * @param direction - * @param topLine - * @param bottomLine - */ - protected void rollScreen(int direction, int topLine, int bottomLine) { - // get the number of lines which are the last 5 bits - /* int lines = direction & 0x7F; */ - // get the direction of the roll which is the first bit - // 0 - up - // 1 - down - int updown = direction & 0x80; - final int lines = direction & 0x7F; - // calculate the reference points for the move. - int start = this.getPos(topLine - 1, 0); - int end = this.getPos(bottomLine - 1, numCols - 1); - int len = end - start; - - // System.out.println(" starting roll"); - // dumpScreen(); - switch (updown) { - case 0: - - // Now round em up and head em UP. - for (int x = start; x < end + numCols; x++) { - if (x + lines * numCols >= lenScreen) { - //Clear at the end - planes.setChar(x, ' '); - } - else { - planes.setChar(x, planes.getChar(x + lines * numCols)); - } - } - - break; - - case 1: - - // Now round em up and head em DOWN. - for (int x = end + numCols; x > 0; x--) { - if ((x - lines * numCols) < 0) { - //Do nothing ... tooo small!!! - } - else { - planes.setChar(x - lines * numCols, planes.getChar(x)); - //and clear - planes.setChar(x, ' '); - } - } - - break; - - default: - Log.w(TAG, " Invalid roll parameter - please report this"); - } - - // System.out.println(" end roll"); - // dumpScreen(); - } - - public void dumpScreen() { - StringBuffer sb = new StringBuffer(); - char[] s = getScreenAsChars(); - int c = getColumns(); - int l = getRows() * c; - int col = 0; - - for (int x = 0; x < l; x++, col++) { - sb.append(s[x]); - - if (col == c) { - sb.append('\n'); - col = 0; - } - } - - Log.i(TAG, sb.toString()); - } - - /** - * Add a field to the field format table. - * - * @param attr - Field attribute - * @param len - length of field - * @param ffw1 - Field format word 1 - * @param ffw2 - Field format word 2 - * @param fcw1 - Field control word 1 - * @param fcw2 - Field control word 2 - */ - protected void addField(int attr, int len, int ffw1, int ffw2, int fcw1, - int fcw2) { - lastAttr = attr; - planes.setScreenCharAndAttr(lastPos, initChar, lastAttr, true); - setDirty(lastPos); - advancePos(); - ScreenField sf = null; - - // from 14.6.12 for Start of Field Order 5940 function manual - // examine the format table for an entry that begins at the current - // starting address plus 1. - if (screenFields.existsAtPos(lastPos)) { - screenFields.setCurrentFieldFFWs(ffw1, ffw2); - } - else { - sf = screenFields.setField(attr, getRow(lastPos), getCol(lastPos), - len, ffw1, ffw2, fcw1, fcw2); - lastPos = sf.startPos(); - int x = len; - boolean gui = guiInterface; - - if (sf.isBypassField()) - gui = false; - - while (x-- > 0) { - if (planes.getChar(lastPos) == 0) - planes.setScreenCharAndAttr(lastPos, ' ', lastAttr, false); - else - planes.setScreenAttr(lastPos, lastAttr); - - if (gui) { - planes.setUseGUI(lastPos, FIELD_MIDDLE); - } - - // now we set the field plane attributes - planes.setScreenFieldAttr(lastPos, ffw1); - advancePos(); - } - - if (gui) - if (len > 1) { - planes.setUseGUI(sf.startPos(), FIELD_LEFT); - - if (lastPos > 0) - planes.setUseGUI(lastPos - 1, FIELD_RIGHT); - else - planes.setUseGUI(lastPos, FIELD_RIGHT); - } - else { - planes.setUseGUI(lastPos - 1, FIELD_ONE); - } - - // screen[lastPos].setCharAndAttr(initChar,initAttr,true); - setEndingAttr(initAttr); - lastPos = sf.startPos(); - } - - // if (fcw1 != 0 || fcw2 != 0) { - // System.out.println("lr = " + lastRow + " lc = " + lastCol + " " + - // sf.toString()); - // } - sf = null; - } - - - // public void addChoiceField(int attr, int len, int ffw1, int ffw2, int - // fcw1, int fcw2) { - // - // lastAttr = attr; - // - // screen[lastPos].setCharAndAttr(initChar,lastAttr,true); - // setDirty(lastPos); - // - // advancePos(); - // - // boolean found = false; - // ScreenField sf = null; - // - // // from 14.6.12 for Start of Field Order 5940 function manual - // // examine the format table for an entry that begins at the current - // // starting address plus 1. - // for (int x = 0;x < sizeFields; x++) { - // sf = screenFields[x]; - // - // if (lastPos == sf.startPos()) { - // screenFields.getCurrentField() = sf; - // screenFields.getCurrentField().setFFWs(ffw1,ffw2); - // found = true; - // } - // - // } - // - // if (!found) { - // sf = - // setField(attr,getRow(lastPos),getCol(lastPos),len,ffw1,ffw2,fcw1,fcw2); - // - // lastPos = sf.startPos(); - // int x = len; - // - // boolean gui = guiInterface; - // if (sf.isBypassField()) - // gui = false; - // - // while (x-- > 0) { - // - // if (screen[lastPos].getChar() == 0) - // screen[lastPos].setCharAndAttr(' ',lastAttr,false); - // else - // screen[lastPos].setAttribute(lastAttr); - // - // if (gui) - // screen[lastPos].setUseGUI(FIELD_MIDDLE); - // - // advancePos(); - // - // } - // - // if (gui) - // if (len > 1) { - // screen[sf.startPos()].setUseGUI(FIELD_LEFT); - // if (lastPos > 0) - // screen[lastPos-1].setUseGUI(FIELD_RIGHT); - // else - // screen[lastPos].setUseGUI(FIELD_RIGHT); - // - // } - // else - // screen[lastPos-1].setUseGUI(FIELD_ONE); - // - // setEndingAttr(initAttr); - // - // lastPos = sf.startPos(); - // } - // - // // if (fcw1 != 0 || fcw2 != 0) { - // // - // // System.out.println("lr = " + lastRow + " lc = " + lastCol + " " + - // sf.toString()); - // // } - // sf = null; - // - // } - - /** - * Return the fields that are contained in the Field Format Table - * - * @return ScreenFields object - * @see org.tn5250j.ScreenFields - */ - public ScreenFields getScreenFields() { - return screenFields; - } - - /** - * Redraw the fields on the screen. Used for gui enhancement to redraw the - * fields when toggling - * - */ - protected void drawFields() { - ScreenField sf; - int sizeFields = screenFields.getSize(); - - for (int x = 0; x < sizeFields; x++) { - sf = screenFields.getField(x); - - if (!sf.isBypassField()) { - int pos = sf.startPos(); - int l = sf.length; - boolean f = true; - - if (l >= lenScreen) - l = lenScreen - 1; - - if (l > 1) { - while (l-- > 0) { - if (guiInterface && f) { - planes.setUseGUI(pos, FIELD_LEFT); - f = false; - } - else { - planes.setUseGUI(pos, FIELD_MIDDLE); - } - - if (guiInterface && l == 0) { - planes.setUseGUI(pos, FIELD_RIGHT); - } - - setDirty(pos++); - } - } - else { - planes.setUseGUI(pos, FIELD_ONE); - } - } - } - - //updateDirty(); - } - - /** - * Draws the field on the screen. Used to redraw or change the attributes of - * the field. - * - * @param sf - - * Field to be redrawn - * @see org.tn5250j.ScreenField.java - */ - protected void drawField(ScreenField sf) { - int pos = sf.startPos(); - int x = sf.length; - - while (x-- > 0) { - setDirty(pos++); - } - - updateDirty(); - } - - /** - * Set the field to be displayed as highlighted. - * - * @param sf - - * Field to be highlighted - */ - protected void setFieldHighlighted(ScreenField sf) { - int pos = sf.startPos(); - int x = sf.length; - int na = sf.getHighlightedAttr(); - - while (x-- > 0) { - planes.setScreenAttr(pos, na); - setDirty(pos++); - } - - fireScreenChanged(); - } - - /** - * Draw the field as un higlighted. This is used to reset the field - * presentation on the screen after the field is exited. - * - * @param sf - - * Field to be unhighlighted - */ - protected void unsetFieldHighlighted(ScreenField sf) { - int pos = sf.startPos(); - int x = sf.length; - int na = sf.getAttr(); - - while (x-- > 0) { - planes.setScreenAttr(pos, na); - setDirty(pos++); - } - - fireScreenChanged(); - } - - protected void setChar(int cByte) { - if (lastPos > 0) { - lastAttr = planes.getCharAttr(lastPos - 1); - } - - if (cByte > 0 && (char)cByte < ' ') { - planes.setScreenCharAndAttr(lastPos, (char) 0x00, 33, false); - setDirty(lastPos); - advancePos(); - } - else { - planes.setScreenCharAndAttr(lastPos, (char) cByte, lastAttr, false); - setDirty(lastPos); - - if (guiInterface && !isInField(lastPos, false)) { - planes.setUseGUI(lastPos, NO_GUI); - } - - advancePos(); - } - } - - protected void setEndingAttr(int cByte) { - int attr = lastAttr; - setAttr(cByte); - lastAttr = attr; - } - - protected void setAttr(int cByte) { - lastAttr = cByte; - // int sattr = screen[lastPos].getCharAttr(); - // System.out.println("changing from " + sattr + " to attr " + lastAttr - // + - // " at " + (this.getRow(lastPos) + 1) + "," + (this.getCol(lastPos) + - // 1)); - planes.setScreenCharAndAttr(lastPos, initChar, lastAttr, true); - setDirty(lastPos); - advancePos(); - int pos = lastPos; - int times = 0; - // sattr = screen[lastPos].getCharAttr(); - // System.out.println(" next position after change " + sattr + " last - // attr " + lastAttr + - // " at " + (this.getRow(lastPos) + 1) + "," + (this.getCol(lastPos) + - // 1) + - // " attr place " + screen[lastPos].isAttributePlace()); - - while (planes.getCharAttr(lastPos) != lastAttr - && !planes.isAttributePlace(lastPos)) { - planes.setScreenAttr(lastPos, lastAttr); - - if (guiInterface && !isInField(lastPos, false)) { - int g = planes.getWhichGUI(lastPos); - - if (g >= FIELD_LEFT && g <= FIELD_ONE) - planes.setUseGUI(lastPos, NO_GUI); - } - - setDirty(lastPos); - times++; - advancePos(); - } - - // sanity check for right now - // if (times > 200) - // System.out.println(" setAttr = " + times + " start = " + (sr + 1) + - // "," + (sc + 1)); - lastPos = pos; - } - - protected void setScreenCharAndAttr(char right, int colorAttr, boolean isAttr) { - planes.setScreenCharAndAttr(lastPos, right, colorAttr, isAttr); - setDirty(lastPos); - advancePos(); - } - - protected void setScreenCharAndAttr(char right, int colorAttr, - int whichGui, boolean isAttr) { - planes.setScreenCharAndAttr(lastPos, right, colorAttr, isAttr); - planes.setUseGUI(lastPos, whichGui); - setDirty(lastPos); - advancePos(); - } - - /** - * Draw or redraw the dirty parts of the screen and display them. - * - * Rectangle dirty holds the dirty area of the screen to be updated. - * - * If you want to change the screen in anyway you need to set the screen - * attributes before calling this routine. - */ - protected void updateDirty() { - fireScreenChanged(); - } - - protected void setDirty(int pos) { - int minr = Math.min(getRow(pos), getRow(dirtyScreen.x)); - int minc = Math.min(getCol(pos), getCol(dirtyScreen.x)); - int maxr = Math.max(getRow(pos), getRow(dirtyScreen.y)); - int maxc = Math.max(getCol(pos), getCol(dirtyScreen.y)); - int x1 = getPos(minr, minc); - int x2 = getPos(maxr, maxc); - dirtyScreen.setBounds(x1, x2, 0, 0); - } - - private void resetDirty(int pos) { - dirtyScreen.setBounds(pos, pos, 0, 0); - } - - /** - * Change the screen position by one column - */ - protected void advancePos() { - changePos(1); - } - - /** - * Change position of the screen by the increment of parameter passed. - * - * If the position change is under the minimum of the first screen position - * then the position is moved to the last row and column of the screen. - * - * If the position change is over the last row and column of the screen then - * cursor is moved to first position of the screen. - * - * @param i - */ - protected void changePos(int i) { - lastPos += i; - - while (lastPos < 0) lastPos += lenScreen; - - while (lastPos >= lenScreen) lastPos -= lenScreen; - } - - - protected void goHome() { - // now we try to move to first input field according to - // 14.6 WRITE TO DISPLAY Command - // ? If the WTD command is valid, after the command is processed, - // the cursor moves to one of three locations: - // - The location set by an insert cursor order (unless control - // character byte 1, bit 1 is equal to B'1'.) - // - The start of the first non-bypass input field defined in the - // format table - // - A default starting address of row 1 column 1. - if (pendingInsert && homePos > 0) { - setCursor(getRow(homePos), getCol(homePos)); - isInField(); - } - else { - if (!gotoField(1)) { - homePos = getPos(1, 1); - setCursor(1, 1); - isInField(0, 0); - } - else { - homePos = getPos(getCurrentRow(), getCurrentCol()); - } - } - } - - protected void setPendingInsert(boolean flag, int icX, int icY) { - pendingInsert = flag; - - if (pendingInsert) { - homePos = getPos(icX, icY); - } - - if (!isStatusErrorCode()) { - setCursor(icX, icY); - } - } - - protected void setPendingInsert(boolean flag) { - if (homePos != -1) - pendingInsert = flag; - } - - /** - * Set the error line number to that of number passed. - * - * @param line - */ - protected void setErrorLine(int line) { - planes.setErrorLine(line); - } - - /** - * Returns the current error line number - * - * @return current error line number - */ - protected int getErrorLine() { - return planes.getErrorLine(); - } - - /** - * Saves off the current error line characters to be used later. - * - */ - protected void saveErrorLine() { - planes.saveErrorLine(); - } - - /** - * Restores the error line characters from the save buffer. - * - * @see #saveErrorLine() - */ - protected void restoreErrorLine() { - if (planes.isErrorLineSaved()) { - planes.restoreErrorLine(); - fireScreenChanged(planes.getErrorLine() - 1, 0, planes.getErrorLine() - 1, numCols - 1); - } - } - - protected void setStatus(byte attr, byte value, String s) { - // set the status area - switch (attr) { - case STATUS_SYSTEM: - if (value == STATUS_VALUE_ON) { - oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, ScreenOIA.OIA_LEVEL_INPUT_INHIBITED, s); - } - else { - oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED, ScreenOIA.OIA_LEVEL_NOT_INHIBITED, s); - } - - break; - - case STATUS_ERROR_CODE: - if (value == STATUS_VALUE_ON) { - setPrehelpState(true, true, false); - oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_ERROR, s); - sessionVT.signalBell(); - } - else { - oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED, - ScreenOIA.OIA_LEVEL_NOT_INHIBITED); - setPrehelpState(false, true, true); - homePos = saveHomePos; - saveHomePos = 0; - pendingInsert = false; - } - - break; - } - } - - protected boolean isStatusErrorCode() { - return oia.getLevel() == ScreenOIA.OIA_LEVEL_INPUT_ERROR; - } - - /** - * This routine clears the screen, resets row and column to 0, resets the - * last attribute to 32, clears the fields, turns insert mode off, - * clears/initializes the screen character array. - */ - protected void clearAll() { - lastAttr = 32; - lastPos = 0; - clearTable(); - clearScreen(); - planes.setScreenAttr(0, initAttr); - oia.setInsertMode(false); - } - - /** - * Clear the fields table - */ - protected void clearTable() { - oia.setKeyBoardLocked(true); - screenFields.clearFFT(); - planes.initalizeFieldPlanes(); - pendingInsert = false; - homePos = -1; - } - - /** - * Clear the gui constructs - * - */ - protected void clearGuiStuff() { - for (int x = 0; x < lenScreen; x++) { - planes.setUseGUI(x, NO_GUI); - } - - dirtyScreen.setBounds(0, lenScreen - 1, 0, 0); - } - - /** - * Clear the screen by setting the initial character and initial attribute - * to all the positions on the screen - */ - protected void clearScreen() { - planes.initalizePlanes(); - dirtyScreen.setBounds(0, lenScreen - 1, 0, 0); - oia.clearScreen(); - } - - protected void restoreScreen() { - lastAttr = 32; - dirtyScreen.setBounds(0, lenScreen - 1, 0, 0); - updateDirty(); - } - - public void onFontSizeChanged(float size) { - fireScreenChanged(0, 0, numRows - 1, numCols - 1); - } - - /** - * repaint part of the screen - * - */ - private void fireScreenChanged(int startRow, int startCol, int endRow, int endCol) { - int [] vt320color = {0x0, // black - 0x4, // blue - 0x2, // green - 0x6, // cyan - 0x1, // red - 0x5, // magenta/purple - 0xb, // yellow - 0x7, // light gray/white - 0x8, // dark gray - 0xc, // light blue - 0xa, // light green - 0xe, // light cyan - 0x9, // light red - 0xd, // light magenta/purple - 0x3, // brown - 0xf // bright white - }; - - for (int r = startRow; r <= endRow; r++) { - for (int c = startCol; c <= endCol; c++) { - int p = getPos(r, c); - char ch = planes.getChar(p); - char co = planes.getCharColor(p); - char at = planes.getCharExtended(p); - boolean ia = planes.isAttributePlace(p); - - if (ch < ' ') ch = ' '; - - int bg = vt320color[(co >> 8) & 0x0f] + 1; - int fg = vt320color[co & 0x0f] + 1; - int ul = at & EXTENDED_5250_UNDERLINE; - int nd = at & EXTENDED_5250_NON_DSP; - int vt_attr = (fg << VDUBuffer.COLOR_FG_SHIFT) + (bg << VDUBuffer.COLOR_BG_SHIFT); - - if (ul > 0) vt_attr |= VDUBuffer.UNDERLINE; - - if (ia || (nd > 0)) vt_attr |= VDUBuffer.INVISIBLE; - - buffer.putChar(c, r, ch, vt_attr); - } - } - - buffer.redrawPassthru(); - dirtyScreen.setBounds(lenScreen, 0, 0, 0); - } - - /** - * repaint the dirty part of the screen - * - */ - - private synchronized void fireScreenChanged() { - if (dirtyScreen.x > dirtyScreen.y) return; - fireScreenChanged(getRow(dirtyScreen.x), getCol(dirtyScreen.x), - getRow(dirtyScreen.y), getCol(dirtyScreen.y)); - } - - /** - * update the cursor position - * - */ - - private synchronized void fireCursorChanged() { - int l = getRow(lastPos); - int c = getCol(lastPos); - buffer.setCursorPosition(c, l); - } - - /** - * update the screen size. - */ - private void fireScreenSizeChanged() { - buffer.setScreenSize(numCols, numRows, true); - } - - /** - * This method does a complete refresh of the screen. - */ - public final void updateScreen() { - repaintScreen(); - setCursorActive(false); - setCursorActive(true); - } - - /** - * Utility method to share the repaint behaviour between setBounds() and - * updateScreen. - */ - public void repaintScreen() { - setCursorOff(); - dirtyScreen.setBounds(0, lenScreen - 1, 0, 0); - updateDirty(); - - // restore statuses that were on the screen before resize - if (oia.getLevel() == ScreenOIA.OIA_LEVEL_INPUT_ERROR) { - oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_ERROR); - } - - if (oia.getLevel() == ScreenOIA.OIA_LEVEL_INPUT_INHIBITED) { - oia.setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); - } - - if (oia.isMessageWait()) - oia.setMessageLightOn(); - - setCursorOn(); - } - - // ADDED BY BARRY - changed by Kenneth to use the character plane - // This should be replaced with the getPlane methods when they are implemented - public char[] getCharacters() { - return planes.screen; - } - -}
--- a/src/org/tn5250j/framework/tn5250/ScreenField.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,537 +0,0 @@ -/** - * Title: tn5250J - * Copyright: Copyright (c) 2001 - * Company: - * @author Kenneth J. Pouncey - * @version 0.4 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.framework.tn5250; - -public class ScreenField { - - protected ScreenField(Screen5250 s) { - this.s = s; - } - - protected ScreenField setField(int attr, int len, int ffw1, int ffw2, - int fcw1, int fcw2) { - return setField(attr, - s.getCurrentRow() - 1, - s.getCurrentCol() - 1, - len, - ffw1, - ffw2, - fcw1, - fcw2); - } - - protected ScreenField setField(int attr, int row, int col, int len, int ffw1, int ffw2, - int fcw1, int fcw2) { -// startRow = row; -// startCol = col; - cursorProg = 0; - fieldId = 0; - length = len; - startPos = (row * s.getColumns()) + col; - endPos = startPos + length - 1; - this.attr = attr; - setFFWs(ffw1, ffw2); - setFCWs(fcw1, fcw2); - next = null; - prev = null; - return this; - } - - public int getAttr() { - return attr; - } - - public int getHighlightedAttr() { - return (fcw2 & 0x0f) | 0x20; - } - - public int getLength() { - return length; - } - - protected boolean setFFWs(int ffw1, int ffw2) { - this.ffw1 = ffw1; - this.ffw2 = ffw2; - int adj = getAdjustment(); - - if (adj > 0) { - checkCanSend = true; - - switch (adj) { - case 5: - case 6: - rightAdjd = false; - break; - - case 7: - mandatory = false; - break; - } - } - - mdt = (ffw1 & 0x8) == 0x8; -// if (mdt) -// s.masterMDT = true; - return mdt; - } - - - public int getFFW1() { - return ffw1; - } - public int getFFW2() { - return ffw2; - } - - protected void setFCWs(int fcw1, int fcw2) { - this.fcw1 = fcw1; - this.fcw2 = fcw2; - -// if ((fcw1 & 0x88) == 0x88) { - if (fcw1 == 0x88) { - cursorProg = fcw2; - } - } - - public int getFCW1() { - return fcw1; - } - - public int getFCW2() { - return fcw2; - } - - public int getFieldLength() { - return length; - } - - public int getCursorProgression() { - return cursorProg; - } - - public int getFieldId() { - return fieldId; - } - - protected void setFieldId(int fi) { - fieldId = fi; - } - - public int getCursorRow() { - return cursorPos / s.getColumns(); - } - - public int getCursorCol() { - return cursorPos % s.getColumns(); - } - - protected void changePos(int i) { - cursorPos += i; - } - - protected String getText() { - StringBuffer text = new StringBuffer(); - getKeyPos(endPos); - int x = length; - text.setLength(x); - - while (x-- > 0) { - // here we manipulate the unicode characters a little for attributes - // that are imbedded in input fields. We will offset them by unicode - // \uff00. All routines that process these fields will have to - // return them to their proper offsets. - // example: - // if we read an attribute byte of 32 for normal display the unicode - // character for this is \u0020 and the unicode character for - // a space is also \u0020 thus the offset. - if (s.planes.isAttributePlace(cursorPos)) { - text.setCharAt(x, (char)('\uff00' + s.planes.getCharAttr(cursorPos))); - } - else { - text.setCharAt(x, s.planes.getChar(cursorPos)); - } - - changePos(-1); - } - - // Since only the mdt of the first continued field is set we will get - // the text of the next continued field if we are dealing with continued - // fields. See routine setMDT for the whys of this. This is only - // executed if this is the first field of a continued field. - if (isContinued() && isContinuedFirst()) { - ScreenField sf = this; - - do { - sf = sf.next; - text.append(sf.getText()); - } - while (!sf.isContinuedLast()); - - sf = null; - } - - return text.toString(); - } - - public String getString() { - StringBuffer text = new StringBuffer(); - getKeyPos(endPos); - int x = length; - text.setLength(x); - - while (x-- > 0) { - // here we manipulate the unicode characters a little for attributes - // that are imbedded in input fields. We will offset them by unicode - // \uff00. All routines that process these fields will have to - // return them to their proper offsets. - // example: - // if we read an attribute byte of 32 for normal display the unicode - // character for this is \u0020 and the unicode character for - // a space is also \u0020 thus the offset. - if (s.planes.isAttributePlace(cursorPos)) { - text.setCharAt(x, (char)('\uff00' + s.planes.getCharAttr(cursorPos))); - } - else { - if (s.planes.getChar(cursorPos) < ' ') - text.setCharAt(x, ' '); - else - text.setCharAt(x, s.planes.getChar(cursorPos)); - } - - changePos(-1); - } - - // Since only the mdt of the first continued field is set we will get - // the text of the next continued field if we are dealing with continued - // fields. See routine setMDT for the whys of this. This is only - // executed if this is the first field of a continued field. - if (isContinued() && isContinuedFirst()) { - ScreenField sf = this; - - do { - sf = sf.next; - text.append(sf.getString()); - } - while (!sf.isContinuedLast()); - - sf = null; - } - - return text.toString(); - } - - public void setFieldChar(char c) { - int x = length; - cursorPos = startPos; - - while (x-- > 0) { - s.planes.setChar(cursorPos, c); - changePos(1); - } - } - - public void setFieldChar(int lastPos, char c) { - int x = endPos - lastPos + 1; - cursorPos = lastPos; - - while (x-- > 0) { - s.planes.setChar(cursorPos, c); - s.setDirty(cursorPos); - changePos(1); - } - } - - protected void setRightAdjusted() { - rightAdjd = true; - } - - protected void setMandatoryEntered() { - mandatory = true; - } - - protected void resetMDT() { - mdt = false; - } - - protected void setMDT() { - // get the first field of a continued edit field if it is continued - if (isContinued() && !isContinuedFirst()) { - ScreenField sf = prev; - - while (sf.isContinued() && !sf.isContinuedFirst()) { - sf = sf.prev; - } - - sf.setMDT(); - sf = null; - } - else { - mdt = true; - } - } - - public boolean isBypassField() { - return (ffw1 & 0x20) == 0x20; - } - - public int getAdjustment() { - return (ffw2 & 0x7); - } - - // is field exit required - public boolean isFER() { - return (ffw2 & 0x40) == 0x40; - } - - // is field mandatory enter - public boolean isMandatoryEnter() { - return (ffw2 & 0x8) == 0x8; - } - - public boolean isToUpper() { - return (ffw2 & 0x20) == 0x20; - } - - // bits 5 - 7 - public int getFieldShift() { - return (ffw1 & 0x7); - } - - public boolean isHiglightedEntry() { - return (fcw1 == 0x89); - } - - public boolean isAutoEnter() { - return (ffw2 & 0x80) == 0x80; - } - - public boolean isSignedNumeric() { - return (getFieldShift() == 7); - } - - public boolean isRightToLeft() { - return (getFieldShift() == 0x04); - } - - public boolean isNumeric() { - return (getFieldShift() == 3); - } - - public boolean isDupEnabled() { - return (ffw1 & 0x10) == 0x10; - } - - public boolean isContinued() { - return (fcw1 & 0x86) == 0x86 && (fcw2 >= 1 && fcw2 <= 3) ; - } - - public boolean isContinuedFirst() { - return (fcw1 & 0x86) == 0x86 && (fcw2 == 1); - } - - public boolean isContinuedMiddle() { - return (fcw1 & 0x86) == 0x86 && (fcw2 == 3); - } - - public boolean isContinuedLast() { - return (fcw1 & 0x86) == 0x86 && (fcw2 == 2); - } - - protected boolean isCanSend() { - int adj = getAdjustment(); - - // here we need to check the Field Exit Required value first before checking - // the adjustments. If the last character has been entered and we are - // now setting past the last position then we are allowed to process the - // the field without continuing. - if (isFER() && cursorPos > endPos) { - return true; - } - - // signed numeric fields need to be checked as well. - if (isSignedNumeric() && cursorPos < endPos - 1) { - return false; - } - - if (adj > 0) { - switch (adj) { - case 5: - case 6: - return rightAdjd; - - case 7: - return mandatory; - - default: - return true; - } - } - - return true; - } - - public boolean isSelectionField() { - return isSelectionField; - } - - public void setSelectionFieldInfo(int type, int index, int position) { - selectionFieldType = type; - selectionIndex = index; - selectionPos = position; - isSelectionField = true; - } - - protected int getKeyPos(int row1, int col1) { - int x = ((row1 * s.getColumns()) + col1); - int y = x - startPos(); - cursorPos = x; - return y; - } - - protected int getKeyPos(int pos) { - int y = pos - startPos(); - cursorPos = pos; - return y; - } - - public int getCurrentPos() { - return cursorPos; - } - - public boolean withinField(int pos) { - if (pos >= startPos && pos <= endPos) - return true; - - return false; - } - - public int startPos() { - return startPos; - } - - /** - * Get the starting row of the field. Offset is 0 so row 6 returned - * is row 7 mapped to screen - * @return int starting row of the field offset 0 - */ - public int startRow() { - return startPos / s.getColumns(); - } - - /** - * Get the starting column of the field. Offset is 0 so column 6 returned - * is column 7 mapped to screen - * @return int starting column of the field offset 0 - */ - public int startCol() { - return startPos % s.getColumns(); - } - - public int endPos() { - return endPos; - } - - /** - * Sets the field's text plane to the specified string. If the string is - * shorter than the length of the field, the rest of the field is cleared. - * If the string is longer than the field, the text is truncated. A subsequent - * call to getText on this field will not show the changed text. To see the - * changed text, do a refresh on the iOhioFields collection and retrieve the - * refreshed field object. - * - * @param text - The text to be placed in the field's text plane. - */ - public void setString(String text) { - cursorPos = startPos; - - if (isRightToLeft()) { - text = new StringBuilder(text).reverse().toString(); - } - - final ScreenPlanes planes = s.getPlanes(); - for (int x = 0,len = text.length(); x < length; x++) { - char tc = (x < len) ? text.charAt(x) : ' '; - planes.setChar(cursorPos, tc); - changePos(1); - } - setMDT(); - s.getScreenFields().setMasterMDT(); - } - - @Override - public String toString() { - int fcw = (fcw1 & 0xff) << 8 | fcw2 & 0xff; - return "startRow = " + startRow() + " startCol = " + startCol() + - " length = " + length + " ffw1 = (0x" + Integer.toHexString(ffw1) + - ") ffw2 = (0x" + Integer.toHexString(ffw2) + - ") fcw1 = (0x" + Integer.toHexString(fcw1) + - ") fcw2 = (0x" + Integer.toHexString(fcw2) + - ") fcw = (" + Integer.toBinaryString(fcw) + - ") fcw hex = (0x" + Integer.toHexString(fcw) + - ") is bypass field = " + isBypassField() + - ") is autoenter = " + isAutoEnter() + - ") is mandatoryenter = " + isMandatoryEnter() + - ") is field exit required = " + isFER() + - ") is Numeric = " + isNumeric() + - ") is Signed Numeric = " + isSignedNumeric() + - ") is cursor progression = " + (fcw1 == 0x88) + - ") next progression field = " + fcw2 + - ") field id " + fieldId + - " continued edit field = " + isContinued() + - " first continued edit field = " + isContinuedFirst() + - " middle continued edit field = " + isContinuedMiddle() + - " last continued edit field = " + isContinuedLast() + - " mdt = " + mdt; - } - - public int getStartPos() { - return startPos; - } - - int startPos = 0; - int endPos = 0; - boolean mdt = false; - protected boolean checkCanSend; - protected boolean rightAdjd; - protected boolean mandatory; - boolean canSend = true; - int attr = 0; - int length = 0; - int ffw1 = 0; - int ffw2 = 0; - int fcw1 = 0; - int fcw2 = 0; - int cursorPos = 0; - Screen5250 s; - int cursorProg = 0; - int fieldId = 0; - ScreenField next = null; - ScreenField prev = null; - boolean isSelectionField; - int selectionFieldType; - int selectionIndex; - int selectionPos; -} \ No newline at end of file
--- a/src/org/tn5250j/framework/tn5250/ScreenFields.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,685 +0,0 @@ -/** - * Title: tn5250J - * Copyright: Copyright (c) 2001 - * Company: - * @author Kenneth J. Pouncey - * @version 0.5 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.framework.tn5250; - -import static org.tn5250j.TN5250jConstants.CMD_READ_INPUT_FIELDS; -import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_FIELDS; -import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_IMMEDIATE_ALT; - -import java.io.ByteArrayOutputStream; - -import org.tn5250j.encoding.ICodePage; - -public class ScreenFields { - - private ScreenField[] screenFields; - private ScreenField currentField; - private ScreenField saveCurrent; - private int sizeFields; - private boolean cpfExists; - private int nextField; - private int fieldIds; - private Screen5250 screen; - private boolean masterMDT; - protected boolean currentModified; - - public ScreenFields(Screen5250 s) { - screen = s; - screenFields = new ScreenField[256]; - } - - protected void clearFFT() { - sizeFields = nextField = fieldIds = 0; - cpfExists = false; // clear the cursor progression fields flag - currentField = null; - masterMDT = false; - } - - protected boolean existsAtPos(int lastPos) { - ScreenField sf = null; - - // from 14.6.12 for Start of Field Order 5940 function manual - // examine the format table for an entry that begins at the current - // starting address plus 1. - for (int x = 0; x < sizeFields; x++) { - sf = screenFields[x]; - - if (lastPos == sf.startPos()) { - currentField = sf; - currentModified = false; - return true; - } - } - - return false; - } - - public boolean isMasterMDT() { - return masterMDT; - } - - protected void setMasterMDT() { - masterMDT = true; - } - - public boolean isCurrentField() { - return currentField == null; - } - - public boolean isCurrentFieldFER() { - return currentField.isFER(); - } - - public boolean isCurrentFieldDupEnabled() { - return currentField.isDupEnabled(); - } - - public boolean isCurrentFieldToUpper() { - return currentField.isToUpper(); - } - - public boolean isCurrentFieldBypassField() { - return currentField.isBypassField(); - } - - public boolean isCurrentFieldHighlightedEntry() { - if (currentField != null) - return currentField.isHiglightedEntry(); - else - return false; - } - - public boolean isCurrentFieldAutoEnter() { - return currentField.isAutoEnter(); - } - - public boolean withinCurrentField(int pos) { - return currentField.withinField(pos); - } - - public boolean isCurrentFieldContinued() { - return currentField.isContinued(); - } - - public boolean isCurrentFieldContinuedFirst() { - return currentField.isContinuedFirst(); - } - - public boolean isCurrentFieldContinuedMiddle() { - return currentField.isContinuedMiddle(); - } - - public boolean isCurrentFieldContinuedLast() { - return currentField.isContinuedLast(); - } - - public boolean isCurrentFieldModified() { - return currentModified; - } - - /** - * This routine is used to check if we can send the Aid key to the host - * - * Taken from Section 16.2.1.2 Enter/Rec Adv Key - * - * In the normal unlocked state, when the workstation operator presses the - * Enter/Rec Adv key: - * - * 1. The 5494 checks for the completion of mandatory-fill, self-check, and - * right-adjust fields when in an active field. (An active field is one in - * which the workstation operator has begun entering data.) If the - * requirements of the field have not been satisfied, an error occurs. - * - * @return - * - */ - public boolean isCanSendAid() { - // We also have to check if we are still in the field. - if (currentField != null && - (currentField.getAdjustment() > 0 || currentField.isSignedNumeric()) - && currentModified && isInField() - && !currentField.isCanSend()) - return false; - else - return true; - } - - protected void saveCurrentField() { - saveCurrent = currentField; - } - - protected void restoreCurrentField() { - currentField = saveCurrent; - } - - protected void setCurrentField(ScreenField sf) { - currentField = sf; - } - - protected void setCurrentFieldMDT() { - currentField.setMDT(); - currentModified = true; - masterMDT = true; - } - - protected void setCurrentFieldFFWs(int ffw1, int ffw2) { - masterMDT = currentField.setFFWs(ffw1, ffw2); - } - - - protected ScreenField setField(int attr, int row, int col, int len, int ffw1, - int ffw2, int fcw1, int fcw2) { - ScreenField sf = null; - screenFields[nextField] = new ScreenField(screen); - screenFields[nextField].setField(attr, row, col, len, ffw1, ffw2, fcw1, fcw2); - sf = screenFields[nextField++]; - sizeFields++; - // set the field id if it is not a bypass field - // this is used for cursor progression - // changed this because of problems not allocating field id's for - // all fields. kjp 2002/10/21 -// if (!sf.isBypassField()) - sf.setFieldId(++fieldIds); - - // check if the cursor progression field flag should be set. -// if ((fcw1 & 0x88) == 0x88) - if (fcw1 == 0x88) - cpfExists = true; - - if (currentField != null) { - currentField.next = sf; - sf.prev = currentField; - } - - currentField = sf; - - // check if the Modified Data Tag was set while creating the field - if (!masterMDT) - masterMDT = currentField.mdt; - - currentModified = false; - return currentField; - } - - public ScreenField getField(int index) { - return screenFields[index]; - } - - public ScreenField getCurrentField() { - return currentField; - } - - public int getCurrentFieldPos() { - return currentField.getCurrentPos(); - } - - protected int getCurrentFieldShift() { - return currentField.getFieldShift(); - } - - public String getCurrentFieldText() { - return currentField.getText(); - } - - public int getCurrentFieldHighlightedAttr() { - return currentField.getHighlightedAttr(); - } - - public int getSize() { - return sizeFields; - } - - public int getFieldCount() { - return sizeFields; - } - - protected boolean isInField(int pos) { - return isInField(pos, true); - } - - protected boolean isInField() { - return isInField(screen.getLastPos(), true); - } - - protected boolean isInField(int pos, boolean chgToField) { - ScreenField sf; - - for (int x = 0; x < sizeFields; x++) { - sf = screenFields[x]; - - if (sf.withinField(pos)) { - if (chgToField) { - if (!currentField.equals(sf)) - currentModified = false; - - currentField = sf; - } - - return true; - } - } - - return false; - } - - /** - * Searches the collection for the target string and returns the iOhioField - * object containing that string. The string must be totally contained - * within the field to be considered a match. - * - * @param targetString The target string. - * @param startPos The row and column where to start the search. The position - * is inclusive (for example, row 1, col 1 means that - * position 1,1 will be used as the starting location and - * 1,1 will be included in the search). - * @param length The length from startPos to include in the search. - * @param dir An OHIO_DIRECTION value: - * - * <table BORDER COLS=3 WIDTH="50%" > - * <tr><th>Constant </th><th>Value</th> - * <th>Description</th></tr> - * <tr><td>OS_OHIO_DIRECTION_FORWARD </td><td>0</td> - * <td>Forward (beginning towards end)</td></tr> - * <tr><td>OS_OHIO_DIRECTION_BACKWARD </td><td>1</td> - * <td>Backward (end towards beginning)</td></tr> - * </table> - * Constant Value Description - * ignoreCase - Indicates whether the search is case sensitive. - * True means that case will be ignored. False means the search will - * be case sensitive. - * @return If found, an iOhioField object containing the target string. If - * not found, returns a null. - */ - public ScreenField findByString(String targetString, - int startPos, - int length, - int dir, - boolean ignoreCase) { - // first lets check if the string exists in the screen space -// iOhioPosition pos = screen.findString(targetString, startPos, length, -// dir, ignoreCase); - // if it does exist then lets search the fields by the position that - // was found and return the results of that search. -// if (pos != null) { - return findByPosition(startPos); -// } - //return null; - } - - /** - * Searches the collection for the target position and returns the ScreenField - * object containing that position. - * - * @param targetPosition The target row and column expressed as a linear - * position within the presentation space. - * - * @return If found, a ScreenField object containing the target position. - * If not found, returns a null. - */ - public ScreenField findByPosition(int targetPosition) { - ScreenField sf = null; - - for (int x = 0; x < sizeFields; x++) { - sf = screenFields[x]; - - if (sf.withinField(targetPosition)) { - return sf; - } - } - - return null; - } - - /** - * Searches the collection for the target position and returns the ScreenField - * object containing that position. - * - * @param row The beginning row to start search with in the presentation space. - * @param col The beginning column to start search with in the presentation space. - * - * @return If found, a ScreenField object containing the target position. - * If not found, returns a null. - */ - public ScreenField findByPosition(int row, int col) { - return findByPosition(screen.getPos(row, col)); - } - - public ScreenField[] getFields() { - ScreenField[] fields = new ScreenField[sizeFields]; - - for (int x = 0; x < sizeFields; x++) { - fields[x] = screenFields[x]; - } - - return fields; - } - - public ScreenField getFirstInputField() { - if (sizeFields <= 0) - return null; - - int f = 0; - ScreenField sf = screenFields[f]; - - while (sf.isBypassField() && f++ < sizeFields) { - sf = screenFields[f]; - } - - if (sf.isBypassField()) - return null; - else - return sf; - } - - public void gotoFieldNext() { - // sanity check - we were getting null pointers after a restore of screen - // and cursor was not positioned on a field when returned - // *** Note *** to myself - // maybe this is fixed I will have to check this some time - int lastPos = screen.getLastPos(); - - if (currentField == null && (sizeFields != 0) && !isInField(lastPos, true)) { - int pos = lastPos; - screen.setCursorOff(); - screen.advancePos(); - lastPos = screen.getLastPos(); - - while (!isInField() && pos != lastPos) { - screen.advancePos(); - } - - screen.setCursorOn(); - } - - // if we are still null do nothing - if (currentField == null) - return; - - ScreenField sf = currentField; - - if (!sf.withinField(lastPos)) { - screen.setCursorOff(); - - if (sizeFields > 0) { - // lets get the current position so we can test if we have looped - // the screen and not found a valid field. - int pos = lastPos; - int savPos = lastPos; - boolean done = false; - - do { - screen.advancePos(); - lastPos = screen.getLastPos(); - - if (isInField(lastPos) - || pos == lastPos) { - if (!currentField.isBypassField()) { - screen.gotoField(currentField); - done = true; - } - } - } - while (!done && lastPos != savPos); - } - - currentModified = false; - screen.setCursorOn(); - } - else { - if (!cpfExists) { - do { - sf = sf.next; - } - while (sf != null && sf.isBypassField()); - } - else { - int f = 0; - int cp = sf.getCursorProgression(); - - if (cp == 0) { - do { - sf = sf.next; - } - while (sf != null && sf.isBypassField()); - } - else { - ScreenField sf1 = null; - boolean found = false; - - while (!found && f < sizeFields) { - sf1 = screenFields[f++]; - - if (sf1.getFieldId() == cp) - found = true; - } - - if (found) - sf = sf1; - else { - do { - sf = sf.next; - } - while (sf != null && sf.isBypassField()); - } - - sf1 = null; - } - } - - if (sf == null) - screen.gotoField(1); - else { - currentField = sf; - screen.gotoField(currentField); - } - - currentModified = false; - } - } - - public void gotoFieldPrev() { - ScreenField sf = currentField; - int lastPos = screen.getLastPos(); - - if (!sf.withinField(lastPos)) { - screen.setCursorOff(); - - if (sizeFields > 0) { - // lets get the current position so we can test if we have looped - // the screen and not found a valid field. - int pos = lastPos; - int savPos = lastPos; - boolean done = false; - - do { - screen.changePos(-1); - lastPos = screen.getLastPos(); - - if (isInField(lastPos) - || (pos == lastPos)) { - if (!currentField.isBypassField()) { - screen.gotoField(currentField); - done = true; - } - } - } - while (!done && lastPos != savPos); - } - - screen.setCursorOn(); - } - else { - if (sf.startPos() == lastPos) { - if (!cpfExists) { - do { - sf = sf.prev; - } - while (sf != null && sf.isBypassField()); - } - else { - int f = 0; - int cp = sf.getFieldId(); - ScreenField sf1 = null; - boolean found = false; - - while (!found && f < sizeFields) { - sf1 = screenFields[f++]; - - if (sf1.getCursorProgression() == cp) - found = true; - } - - if (found) - sf = sf1; - else { - do { - sf = sf.prev; - } - while (sf != null && sf.isBypassField()); - } - - sf1 = null; - } - } - - if (sf == null) { - int size = sizeFields; - sf = screenFields[size - 1]; - - while (sf.isBypassField() && size-- > 0) { - sf = screenFields[size]; - } - } - - currentField = sf; - currentModified = false; - screen.gotoField(currentField); - } - } - - protected void readFormatTable(ByteArrayOutputStream baosp, int readType, ICodePage codePage) { - ScreenField sf; - boolean isSigned = false; - char c; - - if (masterMDT) { - StringBuffer sb = new StringBuffer(); - - for (int x = 0; x < sizeFields; x++) { - isSigned = false; - sf = screenFields[x]; - - if (sf.mdt || (readType == CMD_READ_INPUT_FIELDS)) { - sb.setLength(0); - sb.append(sf.getText()); - - if (readType == CMD_READ_MDT_FIELDS || - readType == CMD_READ_MDT_IMMEDIATE_ALT) { - int len = sb.length() - 1; - - // we strip out all '\u0020' and less - while (len >= 0 && -// (sb.charAt(len) <= ' ' || sb.charAt(len) >= '\uff20' )) { - (sb.charAt(len) < ' ' || sb.charAt(len) >= '\uff20')) { - // if we have the dup character and dup is enabled then we - // stop here - if (sb.charAt(len) == 0x1C && sf.isDupEnabled()) - break; - - sb.deleteCharAt(len--); - } - } - -// System.out.println("field " + sf.toString()); -// System.out.println(">" + sb.toString() + "<"); -// System.out.println(" field is all nulls"); - if (sf.isSignedNumeric() && sb.length() > 0 && sb.charAt(sb.length() - 1) == '-') { - isSigned = true; - sb.setLength(sb.length() - 1); - } - - int len3 = sb.length(); - - if (len3 > 0 || (readType == CMD_READ_MDT_FIELDS || - readType == CMD_READ_MDT_IMMEDIATE_ALT)) { - if ((readType == CMD_READ_MDT_FIELDS || - readType == CMD_READ_MDT_IMMEDIATE_ALT)) { - baosp.write(17); // start of field data - - if (sf.isSelectionField()) { - baosp.write(screen.getRow(sf.selectionPos) + 1); - baosp.write(screen.getCol(sf.selectionPos) + 1); - } - else { - baosp.write(sf.startRow() + 1); - baosp.write(sf.startCol() + 1); - } - } - -// int len = sb.length(); - if (sf.isSelectionField()) { - baosp.write(0); - baosp.write(sf.selectionIndex + 0x1F); - } - else { - for (int k = 0; k < len3; k++) { - c = sb.charAt(k); - - // here we have to check for special instances of the - // characters in the string field. Attribute bytes - // are encoded with an offset of \uff00 - // This is a hack !!!!!!!!!!! - // See ScreenField object for a description - if (c < ' ' || c >= '\uff20') { - // if it is an offset attribute byte we just pass - // it straight on to the output stream - if (c >= '\uff20' && c <= '\uff3f') { - baosp.write(c - '\uff00'); - } - else - - // check for dup character - if (c == 0x1C) - baosp.write(c); - else - baosp.write(codePage.uni2ebcdic(' ')); - } - else { - if (isSigned && k == len3 - 1) { - baosp.write(0xd0 | (0x0f & c)); - } - else - baosp.write(codePage.uni2ebcdic(c)); - } - } - } - } - } - } - } - } - -} \ No newline at end of file
--- a/src/org/tn5250j/framework/tn5250/ScreenOIA.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,282 +0,0 @@ -/** - * <p>Title: ScreenOIA.java</p> - * <p>Description: Main interface to control Operator information area screen</p> - * <p>Copyright: Copyright (c) 2000 - 2002</p> - * <p> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * </p> - * @author Kenneth J. Pouncey - * @version 0.5 - */ -package org.tn5250j.framework.tn5250; - -import java.util.Vector; - -import org.tn5250j.event.ScreenOIAListener; - -/** - * The operator information area of a host session. This area is used to provide - * status information regarding the state of the host session and location of - * the cursor. A ScreenOIA object can be obtained using the GetOIA() method on - * an instance of Screen5250. - * - * - */ -public class ScreenOIA { - // OIA_LEVEL - public static final int OIA_LEVEL_INPUT_INHIBITED = 1; - public static final int OIA_LEVEL_NOT_INHIBITED = 2; - public static final int OIA_LEVEL_MESSAGE_LIGHT_ON = 3; - public static final int OIA_LEVEL_MESSAGE_LIGHT_OFF = 4; - public static final int OIA_LEVEL_AUDIBLE_BELL = 5; - public static final int OIA_LEVEL_INSERT_MODE = 6; - public static final int OIA_LEVEL_KEYBOARD = 7; - public static final int OIA_LEVEL_CLEAR_SCREEN = 8; - public static final int OIA_LEVEL_SCREEN_SIZE = 9; - public static final int OIA_LEVEL_INPUT_ERROR = 10; - public static final int OIA_LEVEL_KEYS_BUFFERED = 11; - public static final int OIA_LEVEL_SCRIPT = 12; - - // INPUTINHIBITED - public static final int INPUTINHIBITED_NOTINHIBITED = 0; - public static final int INPUTINHIBITED_SYSTEM_WAIT = 1; - public static final int INPUTINHIBITED_COMMCHECK = 2; - public static final int INPUTINHIBITED_PROGCHECK = 3; - public static final int INPUTINHIBITED_MACHINECHECK = 4; - public static final int INPUTINHIBITED_OTHER = 5; - - public ScreenOIA(Screen5250 screen) { - source = screen; - } - - public boolean isInsertMode() { - return insertMode; - } - - protected void setInsertMode(boolean mode) { - level = OIA_LEVEL_INSERT_MODE; - insertMode = mode; - fireOIAChanged(ScreenOIAListener.OIA_CHANGED_INSERT_MODE); - } - - public int getCommCheckCode() { - return commCheck; - } - - public int getInputInhibited() { - return inputInhibited; - } - - public int getMachineCheckCode() { - return machineCheck; - } - - public int getOwner() { - return owner; - } - - public int getProgCheckCode() { - return 0; - } - - /** - * Is the keyboard locked or not - * - * @return locked or not - */ - public boolean isKeyBoardLocked() { - return locked; - } - - public boolean isKeysBuffered() { - return keysBuffered; - } - - public void setKeysBuffered(boolean kb) { - level = OIA_LEVEL_KEYS_BUFFERED; - boolean oldKB = keysBuffered; - keysBuffered = kb; - - if (keysBuffered != oldKB) - fireOIAChanged(ScreenOIAListener.OIA_CHANGED_KEYS_BUFFERED); - } - - protected void setKeyBoardLocked(boolean lockIt) { - level = OIA_LEVEL_KEYBOARD; - boolean oldLocked = locked; - locked = lockIt; - - if (!lockIt) { - if (isKeysBuffered()) { - source.sendKeys(""); - } - } - - if (locked != oldLocked) - fireOIAChanged(ScreenOIAListener.OIA_CHANGED_KEYBOARD_LOCKED); - } - - public boolean isMessageWait() { - return messageWait; - } - - protected void setMessageLightOn() { - level = OIA_LEVEL_MESSAGE_LIGHT_ON; - messageWait = true; - fireOIAChanged(ScreenOIAListener.OIA_CHANGED_MESSAGELIGHT); - } - - protected void setMessageLightOff() { - level = OIA_LEVEL_MESSAGE_LIGHT_OFF; - messageWait = false; - fireOIAChanged(ScreenOIAListener.OIA_CHANGED_MESSAGELIGHT); - } - - public void setScriptActive(boolean running) { - level = OIA_LEVEL_SCRIPT; - scriptRunning = running; - fireOIAChanged(ScreenOIAListener.OIA_CHANGED_SCRIPT); - } - - public boolean isScriptActive() { - return scriptRunning; - } - - public void setAudibleBell() { - level = OIA_LEVEL_AUDIBLE_BELL; - fireOIAChanged(ScreenOIAListener.OIA_CHANGED_BELL); - } - - protected void clearScreen() { - level = OIA_LEVEL_CLEAR_SCREEN; - fireOIAChanged(ScreenOIAListener.OIA_CHANGED_CLEAR_SCREEN); - } - - /** - * Add a ScreenOIAListener to the listener list. - * - * @param listener The ScreenOIAListener to be added - */ - public void addOIAListener(ScreenOIAListener listener) { - if (listeners == null) { - listeners = new java.util.Vector<ScreenOIAListener>(3); - } - - listeners.addElement(listener); - } - - /** - * Remove a iOhioSessionListener from the listener list. - * - * @param listener The iOhioSessionListener to be removed - */ - public void removeOIAListener(ScreenOIAListener listener) { - if (listeners == null) { - return; - } - - listeners.removeElement(listener); - } - - // object methods - public Screen5250 getSource() { - return source; - } - - - public void setSource(Screen5250 screen) { - source = screen; - } - - public void setOwner(int newOwner) { - owner = newOwner; - } - - public int getLevel() { - return level; - } - - public String getInhibitedText() { - return inhibitedText; - } - - public void setInputInhibited(int inhibit , int whatCode) { - setInputInhibited(inhibit, whatCode, null); - } - - public void setInputInhibited(int inhibit , int whatCode, String message) { - inputInhibited = inhibit; - level = OIA_LEVEL_INPUT_INHIBITED; - inhibitedText = message; - -// if (saveInhibit != inhibit || saveInhibitLevel != whatCode) { - switch (inhibit) { - case INPUTINHIBITED_COMMCHECK : - commCheck = whatCode; - break; - - case INPUTINHIBITED_PROGCHECK : -// progCheck = whatCode; // never used - break; - - case INPUTINHIBITED_MACHINECHECK : - machineCheck = whatCode; - break; - - case INPUTINHIBITED_SYSTEM_WAIT : - level = whatCode; - break; - - case INPUTINHIBITED_NOTINHIBITED : - level = whatCode; - break; - } - - fireOIAChanged(ScreenOIAListener.OIA_CHANGED_INPUTINHIBITED); -// } - } - - /** - * Notify all registered listeners of the onOIAChanged event. - * - */ - private void fireOIAChanged(int change) { - if (listeners != null) { - int size = listeners.size(); - - for (int i = 0; i < size; i++) { - ScreenOIAListener target = - listeners.elementAt(i); - target.onOIAChanged(this, change); - } - } - } - - private Vector<ScreenOIAListener> listeners = null; - private boolean insertMode; - private boolean locked; - private boolean keysBuffered; - private int owner = 0; - private int level = 0; - private Screen5250 source = null; - private int commCheck = 0; - private int machineCheck = 0; - private boolean messageWait; - private boolean scriptRunning; - private int inputInhibited = INPUTINHIBITED_NOTINHIBITED; - private String inhibitedText; - -}
--- a/src/org/tn5250j/framework/tn5250/ScreenPlanes.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,803 +0,0 @@ -/** - * Title: ScreenPlanes.java - * Copyright: Copyright (c) 2001 - * Company: - * @author Kenneth J. Pouncey - * @version 0.5 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.framework.tn5250; - -import static org.tn5250j.TN5250jConstants.*; - -public class ScreenPlanes { - - private final Screen5250 scr; - private int screenSize; - private int numRows; - private int numCols; - private int errorLineNum; - - private static final int initAttr = 32; - private static final char initChar = 0; - - protected char[] screen; // text plane - private char[] screenAttr; // attribute plane - private char[] screenGUI; // gui plane - private char[] screenIsAttr; - private char[] fieldExtended; - private char[] screenField; - private char[] screenColor; // color plane - protected char[] screenExtended; // extended plane - private char[] screenIsChanged; - - private char[] initArray; - - private char[] errorLine; - private char[] errorLineAttr; - private char[] errorLineIsAttr; - private char[] errorLineGui; - - public ScreenPlanes(Screen5250 s5250, int size) { - scr = s5250; - setSize(size); - } - - protected void setSize(int newSize) { - screenSize = newSize; - numCols = 80; - - switch (newSize) { - case 24: - numRows = 24; - break; - - case 27: - numRows = 27; - numCols = 132; - break; - } - - // this is used here when size changes - setErrorLine(numRows); - screenSize = numRows * numCols; - screen = new char[screenSize]; - screenAttr = new char[screenSize]; - screenIsAttr = new char[screenSize]; - screenGUI = new char[screenSize]; - screenColor = new char[screenSize]; - screenExtended = new char[screenSize]; - fieldExtended = new char[screenSize]; - screenIsChanged = new char[screenSize]; - screenField = new char[screenSize]; - initArray = new char[screenSize]; - initalizePlanes(); - } - - protected void setErrorLine(int line) { - // * NOTE * for developers I have changed the send qry to pass different - // parameters to the host so check setsize for setting error line as well. - // - if (line == 0 || line > numRows) - errorLineNum = numRows; - else - errorLineNum = line; - } - - /** - * Returns the current error line number - * - * @return current error line number - */ - protected int getErrorLine() { - return errorLineNum; - } - - protected void saveErrorLine() { - // if there is already an error line saved then do not save it again - // This signifies that there was a previous error and the original error - // line was not restored yet. - if (errorLine == null) { - errorLine = new char[numCols]; - errorLineAttr = new char[numCols]; - errorLineIsAttr = new char[numCols]; - errorLineGui = new char[numCols]; - int r = scr.getPos(errorLineNum - 1, 0); - - for (int x = 0; x < numCols; x++) { - errorLine[x] = screen[r + x]; - errorLineAttr[x] = screenAttr[r + x]; - errorLineIsAttr[x] = screenIsAttr[r + x]; - errorLineGui[x] = screenGUI[r + x]; - } - } - } - - /** - * Restores the error line characters from the save buffer. - * - * @see #saveErrorLine() - */ - protected void restoreErrorLine() { - if (errorLine != null) { - int r = scr.getPos(errorLineNum - 1, 0); - - for (int x = 0; x < numCols - 1; x++) { - setScreenCharAndAttr(r + x, errorLine[x], errorLineAttr[x], - (errorLineIsAttr[x] == '1' ? true : false)); - screenGUI[x] = errorLineGui[x]; - } - - errorLine = null; - errorLineAttr = null; - errorLineIsAttr = null; - errorLineGui = null; - } - } - - protected boolean isErrorLineSaved() { - return errorLine == null ? false : true; - } - - protected void setScreenCharAndAttr(int pos, char c, int attr, boolean isAttr) { - screen[pos] = c; - screenAttr[pos] = (char)attr; - disperseAttribute(pos, attr); - screenIsAttr[pos] = (isAttr ? (char)1 : (char)0); - screenGUI[pos] = NO_GUI; - } - - protected void setScreenAttr(int pos, int attr, boolean isAttr) { - screenAttr[pos] = (char)attr; - screenIsAttr[pos] = isAttr ? (char)1 : (char)0; - disperseAttribute(pos, attr); - screenGUI[pos] = initChar; - } - - protected void setScreenAttr(int pos, int attr) { - screenAttr[pos] = (char)attr; - //screenGUI[pos] = initChar; - disperseAttribute(pos, attr); - } - - protected void setScreenFieldAttr(int pos, int attr) { - screenField[pos] = (char)attr; - } - - protected final void setChar(int pos, char c) { - screenIsChanged[pos] = screen[pos] == c ? '0' : '1'; - screen[pos] = c; - - if (screenIsAttr[pos] == 1) - setScreenCharAndAttr(pos, c, 32, false); - } - - protected final char getChar(int pos) { - return screen[pos]; - } - - protected final char getCharColor(int pos) { - return screenColor[pos]; - } - - protected final int getCharAttr(int pos) { - return screenAttr[pos]; - } - - protected final char getCharExtended(int pos) { - return screenExtended[pos]; - } - - protected final boolean isAttributePlace(int pos) { - return screenIsAttr[pos] == 1 ? true : false; - } - - public final void setUseGUI(int pos, int which) { - screenIsChanged[pos] = screenGUI[pos] == which ? '0' : '1'; - screenGUI[pos] = (char)which; - } - - private void disperseAttribute(int pos, int attr) { - char c = 0; - char cs = 0; - char ul = 0; - char nd = 0; - - if (attr == 0) - return; - - switch (attr) { - case 32: // green normal - c = ATTR_32; - break; - - case 33: // green/revers - c = ATTR_33; - break; - - case 34: // white normal - c = ATTR_34; - break; - - case 35: // white/reverse - c = ATTR_35; - break; - - case 36: // green/underline - c = ATTR_36; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 37: // green/reverse/underline - c = ATTR_37; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 38: // white/underline - c = ATTR_38; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 39: - nd = EXTENDED_5250_NON_DSP; - break; - - case 40: - case 42: // red/normal - c = ATTR_40; - break; - - case 41: - case 43: // red/reverse - c = ATTR_41; - break; - - case 44: - case 46: // red/underline - c = ATTR_44; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 45: // red/reverse/underline - c = ATTR_45; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 47: - nd = EXTENDED_5250_NON_DSP; - break; - - case 48: - c = ATTR_48; - cs = EXTENDED_5250_COL_SEP; - break; - - case 49: - c = ATTR_49; - cs = EXTENDED_5250_COL_SEP; - break; - - case 50: - c = ATTR_50; - cs = EXTENDED_5250_COL_SEP; - break; - - case 51: - c = ATTR_51; - cs = EXTENDED_5250_COL_SEP; - break; - - case 52: - c = ATTR_52; - // colSep = true; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 53: - c = ATTR_53; - // colSep = true; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 54: - c = ATTR_54; - // colSep = true; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 55: - nd = EXTENDED_5250_NON_DSP; - break; - - case 56: // pink - c = ATTR_56; - break; - - case 57: // pink/reverse - c = ATTR_57; - break; - - case 58: // blue/reverse - c = ATTR_58; - break; - - case 59: // blue - c = ATTR_59; - break; - - case 60: // pink/underline - c = ATTR_60; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 61: // pink/reverse/underline - c = ATTR_61; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 62: // blue/underline - c = ATTR_62; - ul = EXTENDED_5250_UNDERLINE; - break; - - case 63: // nondisplay - nd = EXTENDED_5250_NON_DSP; - cs = EXTENDED_5250_COL_SEP; - break; - - default: - c = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_YELLOW & 0xff); - break; - } - - screenColor[pos] = c; - screenExtended[pos] = (char)(ul | cs | nd); - } - - protected void initalizePlanes() { - char c = (COLOR_BG_BLACK << 8 & 0xff00) | - (COLOR_FG_GREEN & 0xff); - - for (int y = 0; y < screenSize; y++) { - screenAttr[y] = initAttr; - screenColor[y] = c; - } - - // here we will just copy the initialized plane onto the other planes - // using arraycopy which will be faster. I hope. - System.arraycopy(initArray, 0, screen, 0, screenSize); - System.arraycopy(initArray, 0, screenGUI, 0, screenSize); - System.arraycopy(initArray, 0, screenIsAttr, 0, screenSize); - System.arraycopy(initArray, 0, screenExtended, 0, screenSize); - System.arraycopy(initArray, 0, fieldExtended, 0, screenSize); - System.arraycopy(initArray, 0, screenField, 0, screenSize); - } - - protected void initalizeFieldPlanes() { - System.arraycopy(initArray, 0, fieldExtended, 0, screenSize); - System.arraycopy(initArray, 0, screenField, 0, screenSize); - } - - protected final int getWhichGUI(int pos) { - return screenGUI[pos]; - } - - protected final boolean isChanged(int pos) { - return screenIsChanged[pos] == 0 ? false : true; - } - - protected final boolean isUseGui(int pos) { - return screenGUI[pos] == NO_GUI ? false : true; - } - - /** - * Return the data associated with the plane that is passed. - * - * @param from Position from which to start - * @param to Position to end - * @param plane From which plane to obtain the data - * @return Character array containing the data requested - */ - - protected synchronized char[] getPlaneData(int from, int to, int plane) { - int len = (to - from); - char[] planeChars = new char[len + 1]; - - switch (plane) { - case PLANE_TEXT: - System.arraycopy(screen, from, planeChars, 0, len); - break; - - case PLANE_ATTR: - System.arraycopy(screenAttr, from, planeChars, 0, len); - break; - - case PLANE_COLOR: - System.arraycopy(screenColor, from, planeChars, 0, len); - break; - - case PLANE_EXTENDED: - System.arraycopy(screenExtended, from, planeChars, 0, len); - break; - - case PLANE_EXTENDED_GRAPHIC: - System.arraycopy(screenGUI, from, planeChars, 0, len); - break; - - case PLANE_FIELD: - System.arraycopy(screenField, from, planeChars, 0, len); - break; - - case PLANE_IS_ATTR_PLACE: - System.arraycopy(screenIsAttr, from, planeChars, 0, len); - break; - - default: - System.arraycopy(screen, from, planeChars, 0, len); - } - - return planeChars; - } - - /** - * Converts a linear presentation space position to its corresponding row. - * - * @param pos The position to be converted - * @return The row which corresponds to the position given - * @throws OhioException - */ - private int convertPosToRow(int pos) { - return (pos / numCols) + 1; - } - - /** - * Converts a linear presentation space position to its corresponding column. - * - * @param pos The position to be converted - * @return The column which corresponds to the position given - * @throws OhioException - */ - private int convertPosToColumn(int pos) { - return (pos % numCols) + 1; - } - - /** - * - * Converts a row and column coordinate to its corresponding linear position. - * - * @param row - The row of the coordinate - * @param col - The column of the coordinate - * @return The linear position which corresponds to the coordinate given. - * @throws OhioException - */ - private int convertRowColToPos(int row, int col) { - return (row - 1) * numCols + col - 1; - } - - - /** - * <p> - * GetScreen retrieves the various planes associated with the presentation - * space. The data is returned as a linear array of character values in the - * array provided. The array is not terminated by a null character except - * when data is retrieved from the text plane, in which case a single null - * character is appended. - * </p> - * <p> - * The application must supply a buffer for the returned data and the length - * of the buffer. Data is returned starting from the beginning of the - * presentation space and continuing until the buffer is full or the entire - * plane has been copied. For text plane data, the buffer must include one - * extra position for the terminating null character. - * <p> - * - * @param buffer - * @param bufferLength - * @param plane - * @return The number of characters copied to the buffer - * @throws OhioException - */ - - public synchronized int GetScreen(char buffer[], int bufferLength, int plane) { - return GetScreen(buffer, bufferLength, 0, screenSize, plane); - } - - /** - * <p> - * GetScreen retrieves the various planes associated with the presentation - * space. The data is returned as a linear array of character values in the - * array provided. The array is not terminated by a null character except - * when data is retrieved from the text plane, in which case a single null - * character is appended. - * </p> - * <p> - * The application must supply a buffer for the returned data and the length - * of the buffer. Data is returned starting from the given position and - * continuing until the specified number of characters have been copied, the - * buffer is full or the entire plane has been copied. For text plane data, - * the buffer must include one extra position for the terminating null character. - * </p> - * - * @param buffer - * @param bufferLength - * @param from - * @param length - * @param plane - * @return The number of characters copied to the buffer - * @throws OhioException - */ - - public synchronized int GetScreen(char buffer[], int bufferLength, int from, - int length, int plane) { - // if(buffer == null) - // throw new OhioException(sessionVT.getSessionConfiguration(), - // OhioScreen.class.getName(), "osohio.screen.ohio00300", 1); - if (buffer == null) - return 0; - - int min = Math.min(Math.min(buffer.length, bufferLength), screenSize); - - if ((from + min) > screenSize) { - min = screenSize - from; - } - - char[] pd = getPlaneData(from, from + min, plane); - - if (pd != null) { - System.arraycopy(pd, 0, buffer, 0, min); - return pd.length; - } - - return 0; - } - - /** - * <p> - * GetScreen retrieves the various planes associated with the presentation - * space. The data is returned as a linear array of character values in the - * array provided. The array is not terminated by a null character except - * when data is retrieved from the text plane, in which case a single null - * character is appended. - * </p> - * <p> - * The application must supply a buffer for the returned data and the length - * of the buffer. Data is returned starting from the given coordinates and - * continuing until the specified number of characters have been copied, - * the buffer is full, or the entire plane has been copied. For text plane - * data, the buffer must include one extra position for the terminating null - * character. - * </p> - * - * @param buffer - * @param bufferLength - * @param row - * @param col - * @param length - * @param plane - * @return The number of characters copied to the buffer. - * @throws OhioException - */ - - public synchronized int GetScreen(char buffer[], int bufferLength, int row, - int col, int length, int plane) - // throws OhioException { - { - // Call GetScreen function after converting row and column to - // a position. - return GetScreen(buffer, bufferLength, convertRowColToPos(row, col), - length, plane); - } - - /** - * <p> - * GetScreenRect retrieves data from the various planes associated with the - * presentation space. The data is returned as a linear array of character - * values in the buffer provided. - * </p> - * - * <p> - * The application supplies two positions that represent opposing corners of - * a rectangle within the presentation space. The starting and ending - * positions can have any spatial relationship to each other. The data - * returned starts from the row containing the upper-most point to the row - * containing the lower-most point, and from the left-most column to the - * right-most column. - * </p> - * <p> - * The specified buffer must be at least large enough to contain the number - * of characters in the rectangle. If the buffer is too small, no data is - * copied and zero is returned by the method. Otherwise, the method returns - * the number of characters copied. - * </p> - * - * @param buffer - * @param bufferLength - * @param startPos - * @param endPos - * @param plane - * @return The number of characters copied to the buffer - * @throws OhioException - */ - protected int GetScreenRect(char buffer[], int bufferLength, - int startPos, int endPos, int plane) - // throws OhioException { - { - // We will use the row,col routine here because it is easier to use - // row colum than it is for position since I wrote the other first and - // am to lazy to implement it here - // Maybe it would be faster to do it the other way? - int startRow = convertPosToRow(startPos); - int startCol = convertPosToColumn(startPos); - int endRow = convertPosToRow(endPos); - int endCol = convertPosToColumn(endPos); - return GetScreenRect(buffer, bufferLength, startRow, startCol, - endRow, endCol, plane); - } - - /** - * <p> - * GetScreenRect retrieves data from the various planes associated with the - * presentation space. The data is returned as a linear array of character - * values in the buffer provided. The buffer is not terminated by a null - * character. - * </p> - * <p> - * The application supplies two coordinates that represent opposing corners - * of a rectangle within the presentation space. The starting and ending - * coordinates can have any spatial relationship to each other. The data - * returned starts from the row containing the upper-most point to the row - * containing the lower-most point, and from the left-most column to the - * right-most column. - * </p> - * <p> - * The specified buffer must be at least large enough to contain the number - * of characters in the rectangle. If the buffer is too small, no data is - * copied and zero is returned by the method. Otherwise, the method returns - * the number of characters copied. - * </p> - * - * @param buffer - * @param bufferLength - * @param startRow - * @param startCol - * @param endRow - * @param endCol - * @param plane - * @return The number characters copied to the buffer - * @throws OhioException - */ - protected int GetScreenRect(char buffer[], int bufferLength, - int startRow, int startCol, - int endRow, int endCol, int plane) - // throws OhioException { - { - // number of bytes obtained - int numBytes = 0; - - // lets check the row range. If they are reversed then we need to - // place them in the correct order. - if (startRow > endRow) { - int r = startRow; - startRow = endRow; - endRow = r; - } - - // lets check the column range. If they are reversed then we need to - // place them in the correct order. - if (startCol > endCol) { - int c = startCol; - startCol = endCol; - endCol = c; - } - - int numCols = (endCol - startCol) + 1; - int numRows = (endRow - startRow) + 1; - - // lets make sure it is within the bounds of the character array passed - // if not the return as zero bytes where read as per documentation. - if (numCols * numRows <= bufferLength) { - // make sure it is one larger. I guess for other languanges to - // reference like in C which is terminated by a zero byte at the end - // of strings. - char cb[] = new char[numCols + 1]; - int charOffset = 0; - int bytes = 0; - - // now let's loop through and get the screen information for - // each row; - for (int row = startRow; row <= endRow;) { - if ((bytes = GetScreen(cb, cb.length, row, startCol, numCols, plane)) != 0) { - System.arraycopy(cb, 0, buffer, charOffset, numCols); - } - - row++; - charOffset += numCols; - // make sure we count the number of bytes returned - numBytes += bytes; - } - } - - return numBytes; - } - - private int isOption(char[] screen, - int x, - int lenScreen, - int numPref, - int numSuff, - char suff) { - boolean hs = true; - int sp = x; - int os = 0; - - // check to the left for option - while (--sp >= 0 && screen[sp] <= ' ') { - if (x - sp > numPref || screen[sp] == suff || - screen[sp] == '.' || - screen[sp] == '*') { - hs = false; - break; - } - } - - // now lets check for how long the option is it has to be numPref or less - os = sp; - - while (hs && --os > 0 && screen[os] > ' ') { - if (sp - os >= numPref || screen[os] == suff || - screen[os] == '.' || - screen[os] == '*') { - hs = false; - break; - } - } - - if (sp - os > 1 && !Character.isDigit(screen[os + 1])) { - hs = false; - } - - sp = x; - - if (Character.isDigit(screen[sp + 1])) - hs = false; - - // now lets make sure there are no more than numSuff spaces after option - while (hs && (++sp < lenScreen && screen[sp] <= ' ' - || screen[sp] == suff)) { - if (sp - x >= numSuff || screen[sp] == suff || - screen[sp] == '.' || - screen[sp] == '*') { - hs = false; - break; - } - } - - if (hs && !Character.isLetterOrDigit(screen[sp])) - hs = false; - - if (hs) { - return os; - } - - return -1; - } - -} \ No newline at end of file
--- a/src/org/tn5250j/framework/tn5250/Stream5250.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/** - * Title: tn5250J - * Copyright: Copyright (c) 2001 - * Company: - * @author Kenneth J. Pouncey - * @version 0.4 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.framework.tn5250; - -public class Stream5250 { - - public int streamSize; - public int opCode; - public int dataStart; - public int pos; - public byte buffer[]; - - public Stream5250(byte abyte0[]) { - buffer = abyte0; - // size without end of record 0xFF 0xEF - streamSize = (abyte0[0] & 0xff) << 8 | abyte0[1] & 0xff; - opCode = abyte0[9]; - dataStart = 6 + abyte0[6]; - pos = dataStart; - } - - public Stream5250() { - buffer = null; - streamSize = 0; - opCode = 0; - dataStart = 0; - pos = dataStart; - } - - /** - * This method takes a byte array and initializes the object information - * to be used. - * - * @param abyte0 - */ - public void initialize(byte abyte0[]) { - buffer = abyte0; - // size without end of record 0xFF 0xEF - streamSize = (abyte0[0] & 0xff) << 8 | abyte0[1] & 0xff; - opCode = abyte0[9]; - dataStart = 6 + abyte0[6]; - pos = dataStart; - } - - public final int getOpCode() { - return opCode; - } - - public final byte getNextByte() - throws Exception { - if (buffer == null || pos > buffer.length) - throw new Exception("Buffer length exceeded: " + pos); - else - return buffer[pos++]; - } - - public final void setPrevByte() - throws Exception { - if (pos == 0) { - throw new Exception("Index equals zero."); - } - else { - pos--; - return; - } - } - - /** - * Returns where we are in the buffer - * @return position in the buffer - */ - public final int getCurrentPos() { - return pos; - } - - public final byte getByteOffset(int off) - throws Exception { - if (buffer == null || (pos + off) > buffer.length) - throw new Exception("Buffer length exceeded: " + pos); - else - return buffer[pos + off]; - } - - public final boolean size() { - return pos >= streamSize; - } - - - /** - * Determines if any more bytes are available in the buffer to be processed. - * @return yes or no - */ - public final boolean hasNext() { -// return pos >= buffer.length; - return pos < streamSize; - } - - /** - * This routine will retrieve a segment based on the first two bytes being - * the length of the segment. - * - * @return a new byte array containing the bytes of the segment. - * @throws Exception - */ - public final byte[] getSegment() throws Exception { - // The first two bytes contain the length of the segment. - int length = ((buffer[pos] & 0xff) << 8 | (buffer[pos + 1] & 0xff)); - // allocate space for it. - byte[] segment = new byte[length]; - getSegment(segment, length, true); - return segment; - } - - - /** - * This routine will retrieve a byte array based on the first two bytes being - * the length of the segment. - * - * @param segment - byte array - * @param length - length of segment to return - * @param adjustPos - adjust the position of the buffer to the end of the seg - * ment - * @throws Exception - */ - public final void getSegment(byte[] segment, int length, boolean adjustPos) - throws Exception { - // If the length is larger than what is available throw an exception - if ((pos + length) > buffer.length) - throw new Exception("Buffer length exceeded: start " + pos - + " length " + length); - - // use the system array copy to move the bytes from the buffer - // to the allocated byte array - System.arraycopy(buffer, pos, segment, 0, length); - - // update the offset to be after the segment so the next byte can be read - if (adjustPos) - pos += length; - } - -}
--- a/src/org/tn5250j/framework/tn5250/WTDSFParser.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,927 +0,0 @@ -/** - * Title: tn5250J - * Copyright: Copyright (c) 2001 - * Company: - * @author Kenneth J. Pouncey - * @version 0.5 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.framework.tn5250; - -import static org.tn5250j.TN5250jConstants.BOTTOM; -import static org.tn5250j.TN5250jConstants.GUI_LEFT; -import static org.tn5250j.TN5250jConstants.GUI_RIGHT; -import static org.tn5250j.TN5250jConstants.LOWER_LEFT; -import static org.tn5250j.TN5250jConstants.LOWER_RIGHT; -import static org.tn5250j.TN5250jConstants.NO_GUI; -import static org.tn5250j.TN5250jConstants.NR_REQUEST_ERROR; -import static org.tn5250j.TN5250jConstants.UPPER; -import static org.tn5250j.TN5250jConstants.UPPER_LEFT; -import static org.tn5250j.TN5250jConstants.UPPER_RIGHT; - -import java.util.ArrayList; -import java.util.List; - -import org.tn5250j.encoding.ICodePage; -import android.util.Log; - - -/** - * - * Write To Display Structured Field: - * - * This module will parse the structured field information for enhanced - * emulation mode. - * - */ -public class WTDSFParser { - private static final String TAG = "WTDSFParser"; - private Screen5250 screen52; - private tnvt vt; - private ICodePage codePage; - int pos; - byte[] segment; - int length; - boolean error; - boolean guiStructsExist; - - - - private final List<Window> guiStructs = new ArrayList<Window>(3); - private final List<ChoiceField> choices = new ArrayList<ChoiceField>(3); - - - WTDSFParser(tnvt vt) { - this.vt = vt; - screen52 = vt.screen52; - codePage = vt.codePage; - } - - protected class ChoiceField { - - int x; - int y; - int row; - int col; - int width; - int height; - char mnemonic; - int fieldId; - int selectIndex; - - ChoiceField(int row, int col, int fldRow, int fldCol) { - x = row; - y = col; - row = fldRow; - col = fldCol; - } - } - - protected class Window { - - byte[] window; - int pos; - - Window(byte[] seg, int pos) { - //Log.i(TAG,"window created at " + pos); - window = seg; - this.pos = pos; - guiStructsExist = true; - } - - } - - protected void addChoiceField(int row, int col, int fldRow, int fldCol, String text) { - ChoiceField cf = new ChoiceField(row, col, fldRow, fldCol); - cf.fieldId = screen52.getScreenFields().getCurrentField().getFieldId(); - choices.add(cf); - } - - protected boolean isGuisExists() { - return guiStructsExist; - } - - protected byte[] getSegmentAtPos(int pos) { - int len = guiStructs.size(); - - for (int x = 0; x < len; x++) { - Window w = guiStructs.get(x); - - if (w.pos == pos) - return w.window; - } - - return null; - } - - protected void clearGuiStructs() { - guiStructs.clear(); - } - - protected boolean parseWriteToDisplayStructuredField(byte[] seg) { -// bk = vt.bk; - error = false; - boolean done = false; - boolean windowDefined = false; -// int nextone; - pos = 0; - segment = seg; -// try { - length = ((segment[pos++] & 0xff) << 8 | (segment[pos++] & 0xff)); - - while (!done) { - int s = segment[pos++] & 0xff; - - switch (s) { - case 0xD9: // Class Type 0xD9 - Create Window - switch (segment[pos++]) { - case 0x50: // Define Selection Field - defineSelectionField(length); - done = true; - break; - - case 0x51: // Create Window - guiStructs.add(new Window(segment, screen52.getLastPos())); - boolean cr = false; - int rows = 0; - int cols = 0; - - // pull down not supported yet - if ((segment[pos++] & 0x80) == 0x80) - cr = true; // restrict cursor - - pos++; // get reserved field pos 6 - pos++; // get reserved field pos 7 - rows = segment[pos++]; // get window depth rows pos 8 - cols = segment[pos++]; // get window width cols pos 9 - length -= 9; - - if (length == 0) { - done = true; -// System.out.println("Create Window"); -// System.out.println(" restrict cursor " + cr); -// System.out.println(" Depth = " + rows + " Width = " + cols); -// screen52.createWindow(rows,cols,1,true,32,58, - createWindow(rows, cols, 1, true, 32, 58, - '.', - '.', - '.', - ':', - ':', - ':', - '.', - ':'); - windowDefined = true; - break; - } - - // pos 10 is Minor Structure - int ml = 0; - int type = 0; - int lastPos = screen52.getLastPos(); -// if (cr) -// screen52.setPendingInsert(true, -// screen52.getCurrentRow(), -// screen52.getCurrentCol()); - int mAttr = 0; - int cAttr = 0; - - while (length > 0) { - // get minor length - ml = (segment[pos++] & 0xff); - length -= ml; - // only normal windows are supported at this time - type = segment[pos++]; - - switch (type) { - case 0x01 : // Border presentation - boolean gui = false; - - if ((segment[pos++] & 0x80) == 0x80) - gui = true; - - mAttr = segment[pos++]; - cAttr = segment[pos++]; - char ul = '.'; - char upper = '.'; - char ur = '.'; - char left = ':'; - char right = ':'; - char ll = ':'; - char bottom = '.'; - char lr = ':'; - - // if minor length is greater than 5 then - // the border characters are specified - if (ml > 5) { - ul = codePage.ebcdic2uni(segment[pos++]); - -// ul = getASCIIChar(segment[pos++]); - if (ul == 0) - ul = '.'; - - upper = codePage.ebcdic2uni(segment[pos++]); - -// upper = getASCIIChar(segment[pos++]); - if (upper == 0) - upper = '.'; - - ur = codePage.ebcdic2uni(segment[pos++]); - -// ur = getASCIIChar(segment[pos++]); - if (ur == 0) - ur = '.'; - - left = codePage.ebcdic2uni(segment[pos++]); - -// left = getASCIIChar(segment[pos++]); - if (left == 0) - left = ':'; - - right = codePage.ebcdic2uni(segment[pos++]); - -// right = getASCIIChar(segment[pos++]); - if (right == 0) - right = ':'; - - ll = codePage.ebcdic2uni(segment[pos++]); - -// ll = getASCIIChar(segment[pos++]); - if (ll == 0) - ll = ':'; - - bottom = codePage.ebcdic2uni(segment[pos++]); - -// bottom = getASCIIChar(segment[pos++]); - if (bottom == 0) - bottom = '.'; - - lr = codePage.ebcdic2uni(segment[pos++]); - -// lr = getASCIIChar(segment[pos++]); - if (lr == 0) - lr = ':'; - } - -// System.out.println("Create Window"); -// System.out.println(" restrict cursor " + cr); -// System.out.println(" Depth = " + rows + " Width = " + cols); -// System.out.println(" type = " + type + " gui = " + gui); -// System.out.println(" mono attr = " + mAttr + " color attr = " + cAttr); -// System.out.println(" ul = " + ul + " upper = " + upper + -// " ur = " + ur + -// " left = " + left + -// " right = " + right + -// " ll = " + ll + -// " bottom = " + bottom + -// " lr = " + lr -// ); -// screen52.createWindow(rows,cols,type,gui,mAttr,cAttr, - createWindow(rows, cols, type, gui, mAttr, cAttr, - ul, - upper, - ur, - left, - right, - ll, - bottom, - lr); - windowDefined = true; - break; - - // - // The following shows the input for window with a title - // - // +0000 019A12A0 00000400 00020411 00200107 .?.?..?...?..?. - // +0010 00000018 00000011 06131500 37D95180 ........?.?..R?? - // +0020 00000A24 0D018023 23404040 40404040 ..??..??? - // +0030 40211000 000000D7 C2C1D9C4 C5D4D67A \uFFFD.....PBARDEMO: - // +0040 40D79996 879985A2 A2408281 99408485 Progress bar de - // +0050 94961108 1520D5A4 94828599 40968640 mo.???Number of - // +0060 8595A399 8985A24B 4B4B4B4B 4B7A2011 entries......:?. - // +0070 082E2040 404040F5 F0F06BF0 F0F02011 ?.? 500,000?. - // +0080 091520C3 A4999985 95A34085 95A399A8 \uFFFD??Current entry - // +0090 4095A494 8285994B 4B4B7A20 11092E20 number...:?.\uFFFD.? - // +00A0 40404040 4040F56B F0F0F020 110A1520 5,000?.??? - // +00B0 D9859481 89958995 87408595 A3998985 Remaining entrie - // +00C0 A24B4B4B 4B4B4B7A 20110A2E 20404040 s......:?.?.? - // +00D0 40F4F9F5 6BF0F0F0 20110C15 20E2A381 495,000?..??Sta - // +00E0 99A340A3 8994854B 4B4B4B4B 4B4B4B4B rt time......... - // +00F0 4B4B4B4B 7A20110C 2F2040F7 7AF5F37A ....:?...? 7:53: - - case 0x10 : // Window title/footer - if (!windowDefined) { -// screen52.createWindow(rows,cols,1,true,32,58, - guiStructs.add(new Window(segment, screen52.getLastPos())); - createWindow(rows, cols, 1, true, 32, 58, - '.', - '.', - '.', - ':', - ':', - ':', - '.', - ':'); - windowDefined = true; - } - - byte orientation = segment[pos++]; - mAttr = segment[pos++]; - cAttr = segment[pos++]; - //reserved - pos++; - ml -= 6; - StringBuffer hfBuffer = new StringBuffer(ml); - - while (ml-- > 0) { - //LDC - 13/02/2003 - Convert it to unicode - hfBuffer.append(codePage.ebcdic2uni(segment[pos++])); -// hfBuffer.append(getASCIIChar(segment[pos++])); - } - - Log.d(TAG, - " orientation " + Integer.toBinaryString(orientation) + - " mAttr " + mAttr + - " cAttr " + cAttr + - " Header/Footer " + hfBuffer); - screen52.writeWindowTitle(lastPos, - rows, - cols, - orientation, - mAttr, - cAttr, - hfBuffer); - break; - - default: - Log.w(TAG, "Invalid Window minor structure"); - length = 0; - done = true; - } - } - - done = true; - break; - - case 0x53: // Scroll Bar - int sblen = 15; - byte sbflag = segment[pos++]; // flag position 5 - pos++; // reserved position 6 - // position 7,8 - int totalRowScrollable = ((segment[pos++] & 0xff) << 8 - | (segment[pos++] & 0xff)); - // position 9,10 - int totalColScrollable = ((segment[pos++] & 0xff) << 8 - | (segment[pos++] & 0xff)); - // position 11,12 - int sliderRowPos = ((segment[pos++] & 0xff) << 8 - | (segment[pos++] & 0xff)); - // position 13,14 - int sliderColPos = ((segment[pos++] & 0xff) << 8 - | (segment[pos++] & 0xff)); - // position 15 - int sliderRC = segment[pos++]; - screen52.createScrollBar(sbflag, totalRowScrollable, - totalColScrollable, - sliderRowPos, - sliderColPos, - sliderRC); - length -= 15; - done = true; - break; - - case 0x5B: // Remove GUI ScrollBar field - pos++; // reserved must be set to off pos 5 - pos++; // reserved must be set to zero pos 6 - done = true; - break; - - case 0x5F: // Remove All GUI Constructs - Log.i(TAG, "remove all gui contructs"); - clearGuiStructs(); - guiStructsExist = false; - int len = 4; - int d = 0; - length -= s; - - while (--len > 0) - d = segment[pos++]; - -// if (length > 0) { -// len = (segment[pos++] & 0xff )<< 8; -// -// while (--len > 0) -// d = segment[pos++]; -// } - screen52.clearGuiStuff(); - // per 14.6.13.4 documentation we should clear the - // format table after this command - screen52.clearTable(); - done = true; - break; - - case 0x59: // remove gui window - Log.i(TAG, " remove window at " + screen52.getCurrentPos()); - done = true; - break; - - case 0x60: // Erase/Draw Grid Lines - not supported - // do not know what they are - // as of 03/11/2002 we should not be getting - // this anymore but I will leave it here - // just in case. -// System.out.println("erase/draw grid lines " + length); - len = 6; - d = 0; - length -= 9; - - while (--len > 0) - d = segment[pos++]; - - if (length > 0) { - len = (segment[pos++] & 0xff) << 8; - - while (--len > 0) { - d = segment[pos++]; - } - } - - done = true; - break; - - default: - vt.sendNegResponse(NR_REQUEST_ERROR, 0x03, 0x01, 0x01, "invalid wtd structured field sub command " - + (pos - 1)); -// + bk.getByteOffset(-1)); - error = true; - break; - } - - break; - - default: - vt.sendNegResponse(NR_REQUEST_ERROR, 0x03, 0x01, 0x01, - "invalid wtd structured field command " - + (pos - 1)); -// + bk.getByteOffset(-1)); - error = true; - break; - } - - if (error) - done = true; - } - -// } -// catch (Exception e) {}; - return error; - } - - /** - * Creates a window on the screen - * - * @param depth - * @param width - * @param type - * @param gui - * @param monoAttr - * @param colorAttr - * @param ul - * @param upper - * @param ur - * @param left - * @param right - * @param ll - * @param bottom - * @param lr - */ - protected void createWindow(int depth, int width, int type, boolean gui, - int monoAttr, int colorAttr, int ul, int upper, int ur, int left, - int right, int ll, int bottom, int lr) { - int lastPos = screen52.getLastPos(); - int numCols = screen52.getColumns(); - int c = screen52.getCol(lastPos); - int w = 0; - width++; - w = width; - char initChar = Screen5250.initChar; - int initAttr = Screen5250.initAttr; - // set leading attribute byte - screen52.setScreenCharAndAttr(initChar, initAttr, true); - - // set upper left - if (gui) { - screen52.setScreenCharAndAttr((char) ul, colorAttr, UPPER_LEFT, false); - } - else { - screen52.setScreenCharAndAttr((char) ul, colorAttr, false); - } - - // draw top row - while (w-- >= 0) { - if (gui) { - screen52.setScreenCharAndAttr((char) upper, colorAttr, UPPER, false); - } - else { - screen52.setScreenCharAndAttr((char) upper, colorAttr, false); - } - } - - // set upper right - if (gui) { - screen52.setScreenCharAndAttr((char) ur, colorAttr, UPPER_RIGHT, false); - } - else { - screen52.setScreenCharAndAttr((char) ur, colorAttr, false); - } - - // set ending attribute byte - screen52.setScreenCharAndAttr(initChar, initAttr, true); - lastPos = ((screen52.getRow(lastPos) + 1) * numCols) + c; - screen52.goto_XY(lastPos); - - // now handle body of window - while (depth-- > 0) { - // set leading attribute byte - screen52.setScreenCharAndAttr(initChar, initAttr, true); - - // set left - if (gui) { - screen52.setScreenCharAndAttr((char) left, colorAttr, GUI_LEFT, false); - } - else { - screen52.setScreenCharAndAttr((char) left, colorAttr, false); - } - - w = width - 2; - screen52.setScreenCharAndAttr(initChar, initAttr, NO_GUI, true); - - // fill it in - while (w-- >= 0) { -// if (!planes.isUseGui(screen52.getLastPos())) - screen52.setScreenCharAndAttr(initChar, initAttr, NO_GUI, false); - } - - screen52.setScreenCharAndAttr(initChar, initAttr, NO_GUI, true); - - // set right - if (gui) { - screen52.setScreenCharAndAttr((char) right, colorAttr, GUI_RIGHT, false); - } - else { - screen52.setScreenCharAndAttr((char) right, colorAttr, false); - } - - screen52.setScreenCharAndAttr(initChar, initAttr, true); - lastPos = ((screen52.getRow(lastPos) + 1) * numCols) + c; - screen52.goto_XY(lastPos); - } - - // set leading attribute byte - screen52.setScreenCharAndAttr(initChar, initAttr, true); - - if (gui) { - screen52.setScreenCharAndAttr((char) ll, colorAttr, LOWER_LEFT, false); - } - else { - screen52.setScreenCharAndAttr((char) ll, colorAttr, false); - } - - w = width; - - // draw bottom row - while (w-- >= 0) { - if (gui) { - screen52.setScreenCharAndAttr((char) bottom, colorAttr, BOTTOM, false); - } - else { - screen52.setScreenCharAndAttr((char) bottom, colorAttr, false); - } - } - - // set lower right - if (gui) { - screen52.setScreenCharAndAttr((char) lr, colorAttr, LOWER_RIGHT, false); - } - else { - screen52.setScreenCharAndAttr((char) lr, colorAttr, false); - } - - // set ending attribute byte - screen52.setScreenCharAndAttr(initChar, initAttr, true); - } - - /* *** NEVER USED LOCALLY ************************************************** */ -// private void clearWindowBody(ScreenPlanes planes, int startPos, int depth, int width) { -// -// int lastPos = startPos; -// char initChar = Screen5250.initChar; -// int initAttr = Screen5250.initAttr; -// -// // now handle body of window -// while (depth-- > 0) { -// -// // set leading attribute byte -//// planes.setScreenCharAndAttr(lastPos,initChar, initAttr, true); -//// setDirty(lastPos); -//// advancePos(); -//// -//// // set left -//// planes.setScreenCharAndAttr(lastPos, (char) left, colorAttr, false); -//// -//// if (gui) { -//// planes.setUseGUI(lastPos,GUI_LEFT); -//// } -//// setDirty(lastPos); -//// advancePos(); -// -// int w = width; -// // fill it in -// while (w-- >= 0) { -//// screen[lastPos].setCharAndAttr(initChar, initAttr, true); -// planes.setScreenCharAndAttr(lastPos,initChar, initAttr, true); -//// screen[lastPos].setUseGUI(NO_GUI); -// planes.setUseGUI(lastPos,NO_GUI); -//// setDirty(lastPos); -// lastPos++; -// advancePos(); -// } -// -//// // set right -//// // screen[lastPos].setCharAndAttr((char) right, colorAttr, false); -//// planes.setScreenCharAndAttr(lastPos,(char) right, colorAttr, false); -//// if (gui) { -//// // screen[lastPos].setUseGUI(RIGHT); -//// planes.setUseGUI(lastPos,GUI_RIGHT); -//// } -//// -//// setDirty(lastPos); -//// advancePos(); -//// -//// // set ending attribute byte -//// // screen[lastPos].setCharAndAttr(initChar, initAttr, true); -//// planes.setScreenCharAndAttr(lastPos,initChar, initAttr, true); -//// setDirty(lastPos); -// -// lastPos = startPos; -// } -// -// } - - /* *** NEVER USED LOCALLY ************************************************** */ -// private void setDirty(int pos) { -// -// screen52.setDirty(pos); -// -// } - - /* *** NEVER USED LOCALLY ************************************************** */ -// private void advancePos() { -// -// screen52.advancePos(); -// } - - private void defineSelectionField(int majLen) { - // 0030: 20 00 2C 3E 00 00 00 69 12 A0 00 00 04 00 00 03 .,>...i........ - // 0040: 04 40 04 11 00 28 01 07 00 00 00 19 00 00 04 11 .@...(.......... - // 0050: 14 19 15 00 48 D9 50 00 60 00 11 01 84 84 00 00 ....H.P.`....... - // 0060: 05 03 01 01 00 00 00 13 01 E0 00 21 00 21 00 3B ...........!.!.; - // 0070: 22 20 20 20 20 3A 24 20 20 3A 0B 10 08 00 E0 00 " :$ :...... - // 0080: D6 95 85 40 40 0B 10 08 00 E0 00 E3 A6 96 40 40 ...@@.........@@ - // 0090: 0B 10 08 00 E0 00 E3 88 99 85 85 04 52 00 00 FF ............R... - // 00A0: EF . - try { - int flag1 = segment[pos++]; // Flag byte 1 - byte 5 - int flag2 = segment[pos++]; // Flag byte 2 - byte 6 - int flag3 = segment[pos++]; // Flag byte 3 - byte 7 - int typeSelection = segment[pos++]; // Type of selection Field - byte 8 - // GUI Device Characteristics: - // This byte is used if the target device is a GUI PWS or a GUI-like - // NWS. If neigher of these WS are the targets, this byte is ignored - int guiDevice = segment[pos++]; // byte 9 - int withMnemonic = segment[pos++]; // byte 10 - int noMnemonic = segment[pos++]; // byte 11 - pos++; // Reserved - byte 12 - pos++; // Reserved - byte 13 - int cols = segment[pos++]; // Text Size - byte 14 - int rows = segment[pos++]; // Rows - byte 15 - int maxColChoice = segment[pos++]; // byte 16 num of column choices - int padding = segment[pos++]; // byte 17 - int numSepChar = segment[pos++]; // byte 18 - int ctySepChar = segment[pos++]; // byte 19 - int cancelAID = segment[pos++]; // byte 20 - int cnt = 0; - int minLen = 0; - majLen -= 21; - Log.d(TAG, " row: " + screen52.getCurrentRow() - + " col: " + screen52.getCurrentCol() - + " type " + typeSelection - + " gui " + guiDevice - + " withMnemonic " + Integer.toHexString(withMnemonic & 0xf0) - + " noMnemonic " + Integer.toHexString(noMnemonic & 0xf0) - + " noMnemonic " + Integer.toBinaryString(noMnemonic) - + " noMnemonicType " + Integer.toBinaryString((noMnemonic & 0xf0)) - + " noMnemonicSel " + Integer.toBinaryString((noMnemonic & 0x0f)) - + " maxcols " + maxColChoice - + " cols " + cols - + " rows " + rows); - int rowCtr = 0; - int colCtr = 0; - int chcRowStart = screen52.getCurrentRow(); - int chcColStart = screen52.getCurrentCol(); - int chcRow = chcRowStart; - int chcCol = chcColStart; - int chcPos = screen52.getPos(chcRow - 1, chcCol); -// client access -//0000 00 04 ac 9e b9 35 00 01 02 32 bb 4e 08 00 45 00 .....5...2.N..E. -//0010 00 3c 4f 8e 40 00 80 06 00 00 c1 a8 33 58 c1 a8 .<O.@.......3X.. -//0020 33 01 09 e4 00 17 5b bf b7 a4 c3 41 43 d1 50 18 3.....[....AC.P. -//0030 fc de e9 d8 00 00 00 12 12 a0 00 00 04 00 80 03 ................ -//0040 16 18 f1 11 14 1a 00 22 ff ef .......".. - int colAvail = 0x20; - int colSelAvail = 0x20; - int fld = 0; - - do { - minLen = segment[pos++]; // Minor Length byte 21 - int minType = segment[pos++]; // Minor Type - - switch (minType) { - case 0x01: // Choice Presentation Display - // flag - int flagCP1 = segment[pos++]; - pos++; // mon select cursor avail emphasis - byte4 - colSelAvail = segment[pos++]; // -byte 5 - pos++; // mon select cursor - byte 6 - int colSelCur = segment[pos++]; // -byte 7 - pos++; // mon select cursor not avail emphasis - byte 8 - int colSelNotAvail = segment[pos++]; // -byte 9 - pos++; // mon avail emphasis - byte 10 - colAvail = segment[pos++]; // -byte 11 - pos++; // mon select emphasis - byte 12 - int colSel = segment[pos++]; // -byte 13 - pos++; // mon not avail emphasis - byte 14 - int colNotAvail = segment[pos++]; // -byte 15 - pos++; // mon indicator emphasis - byte 16 - int colInd = segment[pos++]; // -byte 17 - pos++; // mon indicator not avail emphasis - byte 18 - int colNotAvailInd = segment[pos++]; // -byte 19 - break; - - case 0x10: // Choice Text minor structure - cnt = 5; - int flagCT1 = segment[pos++]; - int flagCT2 = segment[pos++]; - int flagCT3 = segment[pos++]; - int mnemOffset = 0; - boolean aid = false; - boolean selected = false; - - // is in selected state - if ((flagCT1 & 0x40) == 0x40) { - Log.d(TAG, " selected "); - selected = true; - } - - //System.out.println(Integer.toBinaryString((flagCT1 & 0xf0))); - // is mnemonic offset specified - if ((flagCT1 & 0x08) == 8) { - Log.d(TAG, " mnemOffset " + mnemOffset); - mnemOffset = segment[pos++]; - cnt++; - } - - // is aid key specified - if ((flagCT1 & 0x04) == 4) { - aid = true; - Log.d(TAG, " aidKey " + aid); -// cnt++; - } - - // is single digit number specified - if ((flagCT1 & 0x01) == 0x01) { - Log.d(TAG, " single digit "); - pos++; - cnt++; - } - - // is double digint number specified - if ((flagCT1 & 0x02) == 0x02) { - Log.d(TAG, " double digit "); - pos++; - cnt++; - } - - String s = ""; - byte byte0 = 0; - fld++; - screen52.setCursor(chcRowStart, chcColStart); - - // we do not add a selection if it is marked as unavailable - if ((flagCT1 & 0x80) != 0x80) { - screen52.addField(0x26, 1, 0, 0, 0, 0); - screen52.getScreenFields().getCurrentField().setFieldChar('.'); - screen52.getScreenFields().getCurrentField().setSelectionFieldInfo(17, - fld, - chcPos); - screen52.setCursor(chcRowStart, chcColStart + 3); - - for (; cnt < minLen; cnt++) { - byte0 = segment[pos++]; - s += vt.codePage.ebcdic2uni(byte0); - screen52.setChar(vt.codePage.ebcdic2uni(byte0)); - } - - addChoiceField(chcRowStart, chcColStart, chcRow, chcCol, s); - } - -// screen52.getScreenFields().getCurrentField().setMDT(); - Log.d(TAG, s + " selected " + selected); -// chcRowStart; - //maxColChoice - colCtr++; - -// rowCtr++; - if (colCtr >= maxColChoice) { - rowCtr++; - colCtr = 0; - chcColStart = chcCol; - chcRowStart = chcRow + rowCtr; - - if (rowCtr > rows) { - chcRowStart = chcRow; - rowCtr = 0; - chcColStart = chcColStart + 3 + cols + padding; - } - } - else { - chcColStart = chcColStart + padding + cols + 3; -// - } - - break; - - default: - for (cnt = 2; cnt < minLen; cnt++) { - pos++; - } - } - - majLen -= minLen; - } - while (majLen > 0); - } - catch (Exception exc) { - Log.w(TAG, " defineSelectionField :", exc); - exc.printStackTrace(); - } - } - - // negotiating commands -// private static final byte IAC = (byte)-1; // 255 FF -// private static final byte DONT = (byte)-2; //254 FE -// private static final byte DO = (byte)-3; //253 FD -// private static final byte WONT = (byte)-4; //252 FC -// private static final byte WILL = (byte)-5; //251 FB -// private static final byte SB = (byte)-6; //250 Sub Begin FA -// private static final byte SE = (byte)-16; //240 Sub End F0 -// private static final byte EOR = (byte)-17; //239 End of Record EF -// private static final byte TERMINAL_TYPE = (byte)24; // 18 -// private static final byte OPT_END_OF_RECORD = (byte)25; // 19 -// private static final byte TRANSMIT_BINARY = (byte)0; // 0 -// private static final byte QUAL_IS = (byte)0; // 0 -// private static final byte TIMING_MARK = (byte)6; // 6 -// private static final byte NEW_ENVIRONMENT = (byte)39; // 27 -// private static final byte IS = (byte)0; // 0 -// private static final byte SEND = (byte)1; // 1 -// private static final byte INFO = (byte)2; // 2 -// private static final byte VAR = (byte)0; // 0 -// private static final byte VALUE = (byte)1; // 1 -// private static final byte NEGOTIATE_ESC = (byte)2; // 2 -// private static final byte USERVAR = (byte)3; // 3 - - // miscellaneous -// private static final byte ESC = 0x04; // 04 -// private static final char char0 = 0; - -// private static final byte CMD_READ_IMMEDIATE_ALT = (byte)0x83; // 131 - - -} \ No newline at end of file
--- a/src/org/tn5250j/framework/tn5250/tnvt.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2609 +0,0 @@ -/** - * Title: tnvt.java - * Copyright: Copyright (c) 2001 Company: - * - * @author Kenneth J. Pouncey - * @version 0.5 - * - * Description: - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this software; see the file COPYING. If not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.framework.tn5250; - -import static java.lang.Math.max; -import static java.lang.Math.min; -import static org.tn5250j.TN5250jConstants.AID_HELP; -import static org.tn5250j.TN5250jConstants.AID_PRINT; -import static org.tn5250j.TN5250jConstants.CMD_CLEAR_FORMAT_TABLE; -import static org.tn5250j.TN5250jConstants.CMD_CLEAR_UNIT; -import static org.tn5250j.TN5250jConstants.CMD_CLEAR_UNIT_ALTERNATE; -import static org.tn5250j.TN5250jConstants.CMD_READ_INPUT_FIELDS; -import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_FIELDS; -import static org.tn5250j.TN5250jConstants.CMD_READ_MDT_IMMEDIATE_ALT; -import static org.tn5250j.TN5250jConstants.CMD_READ_SCREEN_IMMEDIATE; -import static org.tn5250j.TN5250jConstants.CMD_READ_SCREEN_TO_PRINT; -import static org.tn5250j.TN5250jConstants.CMD_RESTORE_SCREEN; -import static org.tn5250j.TN5250jConstants.CMD_ROLL; -import static org.tn5250j.TN5250jConstants.CMD_SAVE_SCREEN; -import static org.tn5250j.TN5250jConstants.CMD_WRITE_ERROR_CODE; -import static org.tn5250j.TN5250jConstants.CMD_WRITE_ERROR_CODE_TO_WINDOW; -import static org.tn5250j.TN5250jConstants.CMD_WRITE_STRUCTURED_FIELD; -import static org.tn5250j.TN5250jConstants.CMD_WRITE_TO_DISPLAY; -import static org.tn5250j.TN5250jConstants.NR_REQUEST_ERROR; -import static org.tn5250j.TN5250jConstants.PF1; -import static org.tn5250j.TN5250jConstants.PF10; -import static org.tn5250j.TN5250jConstants.PF11; -import static org.tn5250j.TN5250jConstants.PF12; -import static org.tn5250j.TN5250jConstants.PF13; -import static org.tn5250j.TN5250jConstants.PF14; -import static org.tn5250j.TN5250jConstants.PF15; -import static org.tn5250j.TN5250jConstants.PF16; -import static org.tn5250j.TN5250jConstants.PF17; -import static org.tn5250j.TN5250jConstants.PF18; -import static org.tn5250j.TN5250jConstants.PF19; -import static org.tn5250j.TN5250jConstants.PF2; -import static org.tn5250j.TN5250jConstants.PF20; -import static org.tn5250j.TN5250jConstants.PF21; -import static org.tn5250j.TN5250jConstants.PF22; -import static org.tn5250j.TN5250jConstants.PF23; -import static org.tn5250j.TN5250jConstants.PF24; -import static org.tn5250j.TN5250jConstants.PF3; -import static org.tn5250j.TN5250jConstants.PF4; -import static org.tn5250j.TN5250jConstants.PF5; -import static org.tn5250j.TN5250jConstants.PF6; -import static org.tn5250j.TN5250jConstants.PF7; -import static org.tn5250j.TN5250jConstants.PF8; -import static org.tn5250j.TN5250jConstants.PF9; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.util.Arrays; -import java.util.Properties; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import javax.net.ssl.SSLSocket; - -import android.content.Intent; -import android.net.Uri; -import android.util.Log; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.bean.HostBean; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; -import de.mud.terminal.vt320; - -import org.tn5250j.TN5250jConstants; -import org.tn5250j.encoding.CharMappings; -import org.tn5250j.encoding.ICodePage; -import org.tn5250j.framework.transport.SocketConnector; - - -public final class tnvt implements Runnable { - private static final String TAG = "tnvt"; - // negotiating commands - private static final byte IAC = (byte) - 1; // 255 FF - private static final byte DONT = (byte) - 2; //254 FE - private static final byte DO = (byte) - 3; //253 FD - private static final byte WONT = (byte) - 4; //252 FC - private static final byte WILL = (byte) - 5; //251 FB - private static final byte SB = (byte) - 6; //250 Sub Begin FA - private static final byte SE = (byte) - 16; //240 Sub End F0 - private static final byte EOR = (byte) - 17; //239 End of Record EF - private static final byte TERMINAL_TYPE = (byte) 24; // 18 - private static final byte OPT_END_OF_RECORD = (byte) 25; // 19 - private static final byte TRANSMIT_BINARY = (byte) 0; // 0 - private static final byte QUAL_IS = (byte) 0; // 0 - private static final byte TIMING_MARK = (byte) 6; // 6 - private static final byte NEW_ENVIRONMENT = (byte) 39; // 27 - private static final byte IS = (byte) 0; // 0 - private static final byte SEND = (byte) 1; // 1 - private static final byte INFO = (byte) 2; // 2 - private static final byte VAR = (byte) 0; // 0 - private static final byte VALUE = (byte) 1; // 1 - private static final byte NEGOTIATE_ESC = (byte) 2; // 2 - private static final byte USERVAR = (byte) 3; // 3 - - // miscellaneous - private static final byte ESC = 0x04; // 04 - - private Socket sock; - public BufferedInputStream bin; - public BufferedOutputStream bout; - private final BlockingQueue<Object> dsq = new ArrayBlockingQueue<Object>(25); - private Stream5250 bk; - private DataStreamProducer producer; - protected Screen5250 screen52; - private boolean waitingForInput; - private boolean invited; - private boolean negotiated = false; - private Thread me; - private Thread pthread; - private int readType; - private boolean enhanced = true; - private boolean cursorOn = false; - private String hostname = ""; - private int port = 23; - private vt320 buffer; - private boolean connected = false; - private boolean support132 = true; - private ByteArrayOutputStream baosp = null; - private ByteArrayOutputStream baosrsp = null; - private int devSeq = -1; - private String devName; - private String devNameUsed; - private KbdTypesCodePages kbdTypesCodePage; - // WVL - LDC : TR.000300 : Callback scenario from 5250 - private boolean scan; // = false; - private static int STRSCAN = 1; - // WVL - LDC : 05/08/2005 : TFX.006253 - support STRPCCMD - private boolean strpccmd; // = false; - private String encryption; - private String user; - private String password = null; - private String library; - private String initialMenu; - private String program; - private boolean keepTrucking = true; - private boolean pendingUnlock = false; - private boolean[] dataIncluded; - protected ICodePage codePage; - private String sslType; - private WTDSFParser sfParser; - private TerminalBridge bridge; - private TerminalManager manager; - - - - /** - * @param screen52 - * @param enhanced - * @param support132 - * @param bridge - * @param manager - */ - public tnvt(Screen5250 screen52, boolean enhanced, boolean support132, TerminalBridge bridge, TerminalManager manager) { - this.screen52 = screen52; - this.support132 = support132; - this.enhanced = enhanced; - this.bridge = bridge; - this.manager = manager; - setCodePage("37"); - dataIncluded = new boolean[24]; - baosp = new ByteArrayOutputStream(); - baosrsp = new ByteArrayOutputStream(); - } - - public void showURL(String url) { - if (url.indexOf("://") < 0) url = "http://" + url; - - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - manager.startActivity(intent); - } - - public String getHostName() { - return hostname; - } - - public void setDeviceName(String name) { - devName = name; - } - - public String getDeviceName() { - return devName; - } - - public String getAllocatedDeviceName() { - return devNameUsed; - } - - public boolean isConnected() { - return connected; - } - - /** - * @return true when SSL is used and socket is connected. - * @see {@link #isConnected()} - */ - public boolean isSslSocket() { - if (this.connected && this.sock != null && this.sock instanceof SSLSocket) { - return true; - } - else { - return false; - } - } - - public final void setProxy(String proxyHost, String proxyPort) { - Properties systemProperties = System.getProperties(); - systemProperties.put("socksProxySet", "true"); - systemProperties.put("socksProxyHost", proxyHost); - systemProperties.put("socksProxyPort", proxyPort); - System.setProperties(systemProperties); - Log.i(TAG, " socks set "); - } - - private String fixer(String value, String def) { - if ((value == null) || (value.length() == 0)) return def; - - return value; - } - - public final boolean connect(HostBean host, String homeDirectory, vt320 buffer) { - try { - this.hostname = host.getHostname(); - this.port = host.getPort(); - this.buffer = buffer; - this.encryption = fixer(host.getEncryption5250(), "NONE"); - this.user = host.getUsername(); - this.library = host.getLibrary(); - this.initialMenu = host.getInitialMenu(); - this.program = host.getProgram(); - - try { - screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED, "X - Connecting"); - } - catch (Exception exc) { - Log.w(TAG, "setStatus(ON) " + exc.getMessage()); - } - - SocketConnector sc = new SocketConnector(); - sock = sc.createSocket(hostname, port, encryption, homeDirectory, bridge, manager); - - if (sock == null) { - Log.w(TAG, "I did not get a socket"); - disconnect(); - return false; - } - - connected = true; - // used for JDK1.3 - sock.setKeepAlive(true); - sock.setTcpNoDelay(true); - sock.setSoLinger(false, 0); - InputStream in = sock.getInputStream(); - OutputStream out = sock.getOutputStream(); - bin = new BufferedInputStream(in, 8192); - bout = new BufferedOutputStream(out); - byte abyte0[]; - - while (negotiate(abyte0 = readNegotiations())); - - negotiated = true; - - try { - screen52.setCursorActive(false); - } - catch (Exception excc) { - Log.w(TAG, "setCursorOff " + excc.getMessage()); - } - - producer = new DataStreamProducer(this, bin, dsq, abyte0); - pthread = new Thread(producer); - // pthread.setPriority(pthread.MIN_PRIORITY); - pthread.setPriority(Thread.NORM_PRIORITY); - // pthread.setPriority(Thread.NORM_PRIORITY / 2); - pthread.start(); - - try { - screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); - } - catch (Exception exc) { - Log.w(TAG, "setStatus(OFF) " + exc.getMessage()); - } - - keepTrucking = true; - me = new Thread(this); - me.start(); - } - catch (Exception exception) { - if (exception.getMessage() == null) - exception.printStackTrace(); - - Log.w(TAG, "connect() " + exception.getMessage()); - - if (sock == null) - Log.w(TAG, "I did not get a socket"); - - disconnect(); - return false; - } - - return true; - } - - public final boolean disconnect() { - if (!connected) { - screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED, "X - Disconnected"); - return false; - } - - if (me != null && me.isAlive()) { - me.interrupt(); - keepTrucking = false; - pthread.interrupt(); - } - - screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED, "X - Disconnected"); - screen52.getOIA().setKeyBoardLocked(false); - pendingUnlock = false; - - try { - if (sock != null) { - Log.i(TAG, "Closing socket"); - sock.close(); - } - - if (bin != null) bin.close(); - - if (bout != null) bout.close(); - - connected = false; - // WVL - LDC : TR.000345 : properly disconnect and clear screen - // Is this the right place to set screen realestate on disconnect? - //controller.getScreen().clearAll(); - screen52.goto_XY(0); - screen52.setCursorActive(false); - screen52.clearAll(); - screen52.restoreScreen(); - } - catch (Exception exception) { - Log.w(TAG, exception.getMessage()); - connected = false; - devSeq = -1; - return false; - } - - devSeq = -1; - return true; - } - - private final ByteArrayOutputStream appendByteStream(byte abyte0[]) { - ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); - - for (int i = 0; i < abyte0.length; i++) { - bytearrayoutputstream.write(abyte0[i]); - - if (abyte0[i] == -1) - bytearrayoutputstream.write(-1); - } - - return bytearrayoutputstream; - } - - private final byte[] readNegotiations() throws IOException { - int i = bin.read(); - - if (i < 0) { - throw new IOException("Connection closed."); - } - else { - int j = bin.available(); - byte abyte0[] = new byte[j + 1]; - abyte0[0] = (byte) i; - bin.read(abyte0, 1, j); - return abyte0; - } - } - - private final void writeByte(byte abyte0[]) throws IOException { - bout.write(abyte0); - bout.flush(); - } - - private final void readImmediate(int readType) { - if (screen52.isStatusErrorCode()) { - screen52.restoreErrorLine(); - screen52.setStatus(Screen5250.STATUS_ERROR_CODE, - Screen5250.STATUS_VALUE_OFF, null); - } - - if (!enhanced) { - screen52.setCursorActive(false); - } - - // screen52.setStatus(Screen5250.STATUS_SYSTEM, - // Screen5250.STATUS_VALUE_ON, null); - screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); - screen52.getOIA().setKeyBoardLocked(true); - pendingUnlock = false; - invited = false; - screen52.getScreenFields().readFormatTable(baosp, readType, codePage); - - try { - Log.i(TAG, "readImmediate() writeGDS()"); - writeGDS(0, 3, baosp.toByteArray()); - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - } - - baosp.reset(); - } - - public final boolean sendAidKey(int aid) { - if (screen52.isStatusErrorCode()) { - screen52.restoreErrorLine(); - screen52.setStatus(Screen5250.STATUS_ERROR_CODE, - Screen5250.STATUS_VALUE_OFF, null); - } - - if (!enhanced) { - screen52.setCursorActive(false); - } - - // screen52.setStatus(Screen5250.STATUS_SYSTEM, - // Screen5250.STATUS_VALUE_ON, null); - screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); - screen52.getOIA().setKeyBoardLocked(true); - pendingUnlock = false; - invited = false; - baosp.write(screen52.getCurrentRow()); - baosp.write(screen52.getCurrentCol()); - baosp.write(aid); - - if (dataIncluded(aid)) - screen52.getScreenFields().readFormatTable(baosp, readType, - codePage); - - try { - Log.i(TAG, "sendAidKey() writeGDS()"); - writeGDS(0, 3, baosp.toByteArray()); - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - baosp.reset(); - return false; - } - - baosp.reset(); - return true; - } - - private boolean dataIncluded(int aid) { - switch (aid) { - case PF1: - return !dataIncluded[0]; - - case PF2: - return !dataIncluded[1]; - - case PF3: - return !dataIncluded[2]; - - case PF4: - return !dataIncluded[3]; - - case PF5: - return !dataIncluded[4]; - - case PF6: - return !dataIncluded[5]; - - case PF7: - return !dataIncluded[6]; - - case PF8: - return !dataIncluded[7]; - - case PF9: - return !dataIncluded[8]; - - case PF10: - return !dataIncluded[9]; - - case PF11: - return !dataIncluded[10]; - - case PF12: - return !dataIncluded[11]; - - case PF13: - return !dataIncluded[12]; - - case PF14: - return !dataIncluded[13]; - - case PF15: - return !dataIncluded[14]; - - case PF16: - return !dataIncluded[15]; - - case PF17: - return !dataIncluded[16]; - - case PF18: - return !dataIncluded[17]; - - case PF19: - return !dataIncluded[18]; - - case PF20: - return !dataIncluded[19]; - - case PF21: - return !dataIncluded[20]; - - case PF22: - return !dataIncluded[21]; - - case PF23: - return !dataIncluded[22]; - - case PF24: - return !dataIncluded[23]; - - default: - return true; - } - } - - /** - * Help request - - * - * - * See notes inside method - */ - public final void sendHelpRequest() { - // Client sends header 000D12A0000004000003####F3FFEF - // operation code 3 - // row - first ## - // column - second ## - // F3 - Help Aid Key - // System.out.println("Help request sent"); - baosp.write(screen52.getCurrentRow()); - baosp.write(screen52.getCurrentCol()); - baosp.write(AID_HELP); - - try { - Log.i(TAG, "sendHelpRequest() writeGDS()"); - writeGDS(0, 3, baosp.toByteArray()); - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - } - - baosp.reset(); - } - - /** - * Attention Key - - * - * - * See notes inside method - */ - public final void sendAttentionKey() { - // Client sends header 000A12A000004400000FFEF - // 0x40 -> 01000000 - // - // flags - // bit 0 - ERR - // bit 1 - ATN Attention - // bits 2-4 - reserved - // bit 5 - SRQ system request - // bit 6 - TRQ Test request key - // bit 7 - HLP - - // System.out.println("Attention key sent"); - try { - Log.i(TAG, "sendAttentionKey() writeGDS()"); - writeGDS(0x40, 0, null); - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - } - } - - /** - * Opens a dialog and asks the user before sending a request - * - * @see {@link #systemRequest(String)} - */ - public final void systemRequest() { - String ask = manager.res.getString(R.string.prompt_sys_request); - String sysreq = bridge.promptHelper.requestStringPrompt(null, ask); - systemRequest(sysreq); - } - - /** - * @param sr - system request option - * @see {@link #systemRequest(String)} - */ - public final void systemRequest(char sr) { - systemRequest(Character.toString(sr)); - } - - /** - * System request, taken from the rfc1205, 5250 Telnet interface section 4.3 - * - * @param sr system request option (allowed to be null, but than nothing happens) - */ - public final void systemRequest(String sr) { - byte[] bytes = null; - - if ((sr != null) && (sr.length() > 0)) { - // XXX: Not sure, if this is a sufficient check for 'clear dataq' - if (sr.charAt(0) == '2') { - dsq.clear(); - } - - for (int i = 0, l = sr.length(); i < l; i++) { - baosp.write(codePage.uni2ebcdic(sr.charAt(i))); - } - - bytes = baosp.toByteArray(); - } - - try { - Log.i(TAG, "systemRequest() writeGDS()"); - writeGDS(4, 0, bytes); - } - catch (IOException ioe) { - Log.i(TAG, ioe.getMessage()); - } - - baosp.reset(); - } - - /** - * Cancel Invite - taken from the rfc1205 - 5250 Telnet interface section - * 4.3 - * - * See notes inside method - */ - public final void cancelInvite() { - // screen52.setStatus(Screen5250.STATUS_SYSTEM, - // Screen5250.STATUS_VALUE_ON, null); - screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); - - // from rfc1205 section 4.3 - // Server: Sends header with the 000A12A0 00000400 000AFFEF - // Opcode = Cancel Invite. - - // Client: sends header with the 000A12A0 00000400 000AFFEF - // Opcode = Cancel Invite to - // indicate that the work station is - // no longer invited. - try { - Log.i(TAG, "cancelInvite() writeGDS()"); - writeGDS(0, 10, null); - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - } - } - - public final void hostPrint(int aid) { - if (screen52.isStatusErrorCode()) { - screen52.restoreErrorLine(); - screen52.setStatus(Screen5250.STATUS_ERROR_CODE, - Screen5250.STATUS_VALUE_OFF, null); - } - - screen52.setCursorActive(false); - // screen52.setStatus(Screen5250.STATUS_SYSTEM, - // Screen5250.STATUS_VALUE_ON, null); - screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_SYSTEM_WAIT, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); - // From client access ip capture - // it seems to use an operation code of 3 and 4 - // also note that the flag field that says reserved is being sent as - // well - // with a value of 0x80 - // - // I have tried with not setting these flags and sending with 3 or 1 - // there is no effect and I still get a host print screen. Go figure - //0000: 000D 12A0 0000 0400 8003 1407 F6FFEF - //0000: 000D 12A0 0000 0400 8001 110E F6FFEF - // - // Client sends header 000D12A0000004000003####F6FFEF - // operation code 3 - // row - first ## - // column - second ## - // F6 - Print Aid Key - baosp.write(screen52.getCurrentRow()); - baosp.write(screen52.getCurrentCol()); - baosp.write(AID_PRINT); // aid key - - try { - Log.i(TAG, "hostPrint() writeGDS()"); - writeGDS(0, 3, baosp.toByteArray()); - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - } - - baosp.reset(); - } - - public final void toggleDebug() { - producer.toggleDebug(codePage); - } - - // write gerneral data stream - private final void writeGDS(int flags, int opcode, byte abyte0[]) - throws IOException { - // Added to fix for JDK 1.4 this was null coming from another method. - // There was a weird keyRelease event coming from another panel when - // using a key instead of the mouse to select button. - // The other method was fixed as well but this check should be here - // anyway. - if (bout == null) - return; - - int length; - - if (abyte0 != null) - length = abyte0.length + 10; - else - length = 10; - - // refer to rfc1205 - 5250 Telnet interface - // Section 3. Data Stream Format - // Logical Record Length - 16 bits - baosrsp.write(length >> 8); // Length LL - baosrsp.write(length & 0xff); // LL - // Record Type - 16 bits - // It should always be set to '12A0'X to indicate the - // General Data Stream (GDS) record type. - baosrsp.write(18); // 0x12 - baosrsp.write(160); // 0xA0 - // the next 16 bits are not used - baosrsp.write(0); // 0x00 - baosrsp.write(0); // 0x00 - // The second part is meant to be variable in length - // currently this portion is 4 octets long (1 byte or 8 bits for us ;-O) - baosrsp.write(4); // 0x04 - baosrsp.write(flags); // flags - // bit 0 - ERR - // bit 1 - ATN Attention - // bits 2-4 - reserved - // bit 5 - SRQ system request - // bit 6 - TRQ Test request key - // bit 7 - HLP - baosrsp.write(0); // reserved - set to 0x00 - baosrsp.write(opcode); // opcode - - if (abyte0 != null) - baosrsp.write(abyte0, 0, abyte0.length); - - baosrsp = appendByteStream(baosrsp.toByteArray()); - // make sure we indicate no more to be sent - baosrsp.write(IAC); - baosrsp.write(EOR); - baosrsp.writeTo(bout); - bout.flush(); - baosrsp.reset(); - } - - protected final int getOpCode() { - return bk.getOpCode(); - } - - protected boolean[] getActiveAidKeys() { - boolean aids[] = new boolean[dataIncluded.length]; - System.arraycopy(dataIncluded, 0, aids, 0, dataIncluded.length); - return aids; - } - - private final void setInvited() { - Log.d(TAG, "invited"); - if (!screen52.isStatusErrorCode()) - screen52.getOIA().setInputInhibited(ScreenOIA.INPUTINHIBITED_NOTINHIBITED, - ScreenOIA.OIA_LEVEL_INPUT_INHIBITED); - invited = true; - screen52.updateDirty(); - buffer.testChanged(); - } - - // WVL - LDC : 05/08/2005 : TFX.006253 - Support STRPCCMD - private void strpccmd() { - try { - int str = 11; - char c; - ScreenPlanes planes = screen52.getPlanes(); - c = planes.getChar(str); - boolean waitFor = !(c == 'a'); - StringBuffer command = new StringBuffer(); - - for (int i = str + 1; i < 132; i++) { - c = planes.getChar(i); - - if (Character.isISOControl(c)) - c = ' '; - - command.append(c); - } - - String cmd = command.toString().trim(); - run(cmd, waitFor); - } - finally { - strpccmd = false; - screen52.sendKeys(TN5250jConstants.MNEMONIC_ENTER); - } - } - - // WVL - LDC : 05/08/2005 : TFX.006253 - Support STRPCCMD - private void run(String cmd, boolean waitFor) { - try { - Log.d(TAG, "RUN cmd = " + cmd); - Log.d(TAG, "RUN wait = " + waitFor); - Runtime r = Runtime.getRuntime(); - Process p = r.exec(cmd); - - if (waitFor) { - int result = p.waitFor(); - Log.d(TAG, "RUN result = " + result); - } - } - catch (Throwable t) { - Log.e(TAG, "exception", t); - } - } - - - // WVL - LDC : TR.000300 : Callback scenario from 5250 - /** - * Activate or deactivate the command scanning behaviour. - * - * @param scan - * if true, scanning is enabled; disabled otherwise. - * - * @see scan4Cmd() - */ - public void setScanningEnabled(boolean scan) { - this.scan = scan; - } - - // WVL - LDC : TR.000300 : Callback scenario from 5250 - /** - * Checks whether command scanning is enabled. - * - * @return true is command scanning is enabled; false otherwise. - */ - public boolean isScanningEnabled() { - return this.scan; - } - - // WVL - LDC : TR.000300 : Callback scenario from 5250 - /** - * When command scanning is activated, the terminal reads the first and - * second character in the datastream (the zero position allows to - * devisualize the scan stream). If the sequence <code>#!</code> is - * encountered and if this sequence is <strong>not </strong> followed by a - * blank character, the {@link parseCommand(ScreenChar[])}is called. - */ - private void scan() { - // System.out.println("Checking command : " + - // screen52.screen[1].getChar() + screen52.screen[2].getChar()); - // ScreenChar[] screen = screen52.screen; - ScreenPlanes planes = screen52.getPlanes(); - - if ((planes.getChar(STRSCAN) == '#') - && (planes.getChar(STRSCAN + 1) == '!') - && (planes.getChar(STRSCAN + 2) != ' ')) { - try { - parseCommand(); - } - catch (Throwable t) { - Log.i(TAG, "Exec cmd: " + t.getMessage()); - t.printStackTrace(); - } - } - } - - // WVL - LDC : TR.000300 : Callback scenario from 5250 - /** - * The screen is parsed starting from second position until a white space is - * encountered. When found the Session#execCommand(String, int) is - * called with the parsed string. The position immediately following the - * encountered white space, separating the command from the rest of the - * screen, is passed as starting index. - * - * Note that the character at the starting position can potentially be a - * white space itself. The starting position in <code>execCommand</code> - * provided to make the scanning sequence more flexible. We'd like for - * example to embed also a <code>+</code> or <code>-</code> sign to - * indicate whether the tnvt should trigger a repaint or not. This would - * allow the flashing of command sequences without them becoming visible. - * - * <ul> - * <li><strong>PRE </strong> The screen character at position - * <code>STRSCAN + 2</code> is not a white space.</li> - * </ul> - */ - private void parseCommand() { - // Search for the command i.e. the first token in the stream - // after the #! sequence separated by a space from the rest - // of the screen. - char[] screen = screen52.getScreenAsChars(); - - for (int s = STRSCAN + 2, i = s; i < screen.length; i++) { - if (screen[i] == ' ') { - String command = new String(screen, s, i - s); - // Skip all white spaces between the command and the rest of - // the screen. - //for (; (i < screen.length) && (screen[i] == ' '); i++); - String remainder = new String(screen, i + 1, screen.length - - (i + 1)); - //controller.fireScanned(command, remainder); - Log.i(TAG, "trying to run " + command + " " + remainder); - break; - } - } - } - - public void run() { - if (enhanced) sfParser = new WTDSFParser(this); - - bk = new Stream5250(); - - while (keepTrucking) { - try { - Object e = dsq.take(); - - if ((e instanceof Integer) && ((Integer)e == 0)) { - screen52.updateDirty(); - buffer.testChanged(); - continue; - }; - - bk.initialize((byte[])e); - } - catch (InterruptedException ie) { - Log.w(TAG, " vt thread interrupted and stopping "); - keepTrucking = false; - continue; - } - - invited = false; - screen52.setCursorActive(false); - if (bk == null) continue; - - switch (bk.getOpCode()) { - case 00: - Log.d(TAG, "No operation"); - break; - - case 1: - Log.d(TAG, "Invite Operation"); - parseIncoming(); - pendingUnlock = true; - cursorOn = true; - setInvited(); - break; - - case 2: - Log.d(TAG, "Output Only"); - parseIncoming(); - screen52.updateDirty(); - break; - - case 3: - Log.d(TAG, "Put/Get Operation"); - parseIncoming(); - setInvited(); - break; - - case 4: - Log.d(TAG, "Save Screen Operation"); - parseIncoming(); - break; - - case 5: - Log.d(TAG, "Restore Screen Operation"); - parseIncoming(); - break; - - case 6: - Log.d(TAG, "Read Immediate"); - sendAidKey(0); - break; - - case 7: - Log.d(TAG, "Reserved"); - break; - - case 8: - Log.d(TAG, "Read Screen Operation"); - - try { - readScreen(); - } - catch (IOException ex) { - Log.w(TAG, ex.getMessage()); - } - - break; - - case 9: - Log.d(TAG, "Reserved"); - break; - - case 10: - Log.d(TAG, "Cancel Invite Operation"); - cancelInvite(); - break; - - case 11: - Log.d(TAG, "Turn on message light"); - screen52.getOIA().setMessageLightOn(); - screen52.setCursorActive(true); - break; - - case 12: - Log.d(TAG, "Turn off Message light"); - screen52.getOIA().setMessageLightOff(); - screen52.setCursorActive(true); - break; - - default: - break; - } - - if (screen52.isUsingGuiInterface()) - screen52.drawFields(); - - try { - if (!strpccmd) { - screen52.updateDirty(); - } - else { - strpccmd(); - } - } - catch (Exception exd) { - Log.w(TAG, " tnvt.run: " + exd.getMessage()); - exd.printStackTrace(); - } - - if (pendingUnlock && !screen52.isStatusErrorCode()) { - screen52.getOIA().setKeyBoardLocked(false); - pendingUnlock = false; - } - - if (cursorOn && !screen52.getOIA().isKeyBoardLocked()) { - screen52.setCursorActive(true); - cursorOn = false; - } - } - } - - public void dumpStuff() { - Log.d(TAG, " Pending unlock " + pendingUnlock); - Log.d(TAG, " Status Error " + screen52.isStatusErrorCode()); - Log.d(TAG, " Keyboard Locked " + screen52.getOIA().isKeyBoardLocked()); - Log.d(TAG, " Cursor On " + cursorOn); - Log.d(TAG, " Cursor Active " + screen52.cursorActive); - } - - - private final void readScreen() throws IOException { - int rows = screen52.getRows(); - int cols = screen52.getColumns(); - byte abyte0[] = new byte[rows * cols]; - fillScreenArray(abyte0, rows, cols); - Log.i(TAG, "readScreen() writeGDS()"); - writeGDS(0, 0, abyte0); - abyte0 = null; - } - - private final void fillScreenArray(byte[] sa, int rows, int cols) { - int la = 32; - int sac = 0; - int len = rows * cols; - ScreenPlanes planes = screen52.planes; - - try { - for (int y = 0; y < len; y++) { // save the screen data - if (planes.isAttributePlace(y)) { - la = planes.getCharAttr(y); - sa[sac++] = (byte) la; - } - else { - // The characters on screen are in unicode - char ch = planes.getChar(y); - byte byteCh; - if (isDataUnicode(ch)) byteCh = codePage.uni2ebcdic(ch); - else byteCh = (byte) ch; - sa[sac++] = byteCh; - } - } - } - catch (Exception exc) { - Log.i(TAG, exc.getMessage()); - exc.printStackTrace(); - } - } - - private final void fillRegenerationBuffer(ByteArrayOutputStream sc, int rows, int cols) - throws IOException { - int la = 32; - int sac = 0; - int len = rows * cols; - ScreenPlanes planes = screen52.planes; - byte[] sa = new byte[len]; - - try { - boolean guiExists = sfParser != null && sfParser.isGuisExists(); - - for (int y = 0; y < len; y++) { // save the screen data - if (guiExists) { - byte[] guiSeg = sfParser.getSegmentAtPos(y); - - if (guiSeg != null) { - //Log.i(TAG," gui saved at " + y + " - " + screen52.getRow(y) + "," + - // screen52.getCol(y)); - byte[] gsa = new byte[sa.length + guiSeg.length + 2]; - System.arraycopy(sa, 0, gsa, 0, sa.length); - System.arraycopy(guiSeg, 0, gsa, sac + 2, guiSeg.length); - sa = new byte[gsa.length]; - System.arraycopy(gsa, 0, sa, 0, gsa.length); - sa[sac++] = (byte)0x04; - sa[sac++] = (byte)0x11; - sac += guiSeg.length; - //y--; - // continue; - } - } - - if (planes.isAttributePlace(y)) { - la = planes.getCharAttr(y); - sa[sac++] = (byte) la; - } - else { - // The characters on screen are in unicode - char ch = planes.getChar(y); - byte byteCh; - if (isDataUnicode(ch)) byteCh = codePage.uni2ebcdic(ch); - else byteCh = (byte) ch; - sa[sac++] = byteCh; - } - } - } - catch (Exception exc) { - Log.i(TAG, exc.getMessage()); - exc.printStackTrace(); - } - - sc.write(sa); - } - - public final void saveScreen() throws IOException { - ByteArrayOutputStream sc = new ByteArrayOutputStream(); - sc.write(4); - sc.write(0x12); // 18 - sc.write(0); // 18 - sc.write(0); // 18 - sc.write((byte) screen52.getRows()); // store the current size - sc.write((byte) screen52.getColumns()); // "" - int cp = screen52.getCurrentPos(); // save off current position - // fix below submitted by Mitch Blevins - //int cp = screen52.getScreenFields().getCurrentFieldPos(); - // save off current position - sc.write((byte)(cp >> 8 & 0xff)); // "" - sc.write((byte)(cp & 0xff)); // "" - sc.write((byte)(screen52.homePos >> 8 & 0xff)); // save home pos - sc.write((byte)(screen52.homePos & 0xff)); // "" - int rows = screen52.getRows(); // store the current size - int cols = screen52.getColumns(); // "" - // byte[] sa = new byte[rows * cols]; - fillRegenerationBuffer(sc, rows, cols); - // fillScreenArray(sa, rows, cols); - // - // sc.write(sa); - // sa = null; - int sizeFields = screen52.getScreenFields().getSize(); - sc.write((byte)(sizeFields >> 8 & 0xff)); // "" - sc.write((byte)(sizeFields & 0xff)); // "" - - if (sizeFields > 0) { - int x = 0; - int s = screen52.getScreenFields().getSize(); - ScreenField sf = null; - - while (x < s) { - sf = screen52.getScreenFields().getField(x); - sc.write((byte) sf.getAttr()); // attribute - int sp = sf.startPos(); - sc.write((byte)(sp >> 8 & 0xff)); // "" - sc.write((byte)(sp & 0xff)); // "" - - if (sf.mdt) - sc.write((byte) 1); - else - sc.write((byte) 0); - - sc.write((byte)(sf.getLength() >> 8 & 0xff)); // "" - sc.write((byte)(sf.getLength() & 0xff)); // "" - sc.write((byte) sf.getFFW1() & 0xff); - sc.write((byte) sf.getFFW2() & 0xff); - sc.write((byte) sf.getFCW1() & 0xff); - sc.write((byte) sf.getFCW2() & 0xff); - Log.d(TAG, "Saved "); - Log.d(TAG, sf.toString()); - x++; - } - - sf = null; - } - - // The following two lines of code looks to have caused all sorts of - // problems so for now we have commented them out. - // screen52.getScreenFields().setCurrentField(null); // set it to null - // for GC ? - // screen52.clearTable(); - - try { - Log.i(TAG, "saveScreen() writeGDS()"); - writeGDS(0, 3, sc.toByteArray()); - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - } - - sc = null; - Log.d(TAG, "Save Screen end "); - } - - /** - * - * @throws IOException - */ - public final void restoreScreen() throws IOException { - int which = 0; - ScreenPlanes planes = screen52.planes; - - try { - Log.d(TAG, "Restore "); - bk.getNextByte(); - bk.getNextByte(); - int rows = bk.getNextByte() & 0xff; - int cols = bk.getNextByte() & 0xff; - int pos = bk.getNextByte() << 8 & 0xff00; // current position - pos |= bk.getNextByte() & 0xff; - int hPos = bk.getNextByte() << 8 & 0xff00; // home position - hPos |= bk.getNextByte() & 0xff; - - if ((rows != screen52.getRows()) || (cols != screen52.getColumns())) - screen52.setRowsCols(rows, cols); - - screen52.clearAll(); // initialize what we currenty have - - if (sfParser != null && sfParser.isGuisExists()) - sfParser.clearGuiStructs(); - - int b = 32; - int la = 32; - int len = rows * cols; - - for (int y = 0; y < len; y++) { - b = bk.getNextByte(); - - if (b == 0x04) { - Log.i(TAG, " gui restored at " + y + " - " + screen52.getRow(y) + "," + - screen52.getCol(y)); - int command = bk.getNextByte(); - byte[] seg = bk.getSegment(); - - if (seg.length > 0) { - screen52.goto_XY(y); - sfParser.parseWriteToDisplayStructuredField(seg); - } - - y--; - // screen52.goto_XY(y); - } - else { - // b = bk.getNextByte(); - if (planes.isUseGui(y)) - continue; - - if (isAttribute(b)) { - planes.setScreenCharAndAttr(y, planes.getChar(y), b, true); - la = b; - } - else { - // The characters on screen are in unicode - char ch; - if (isDataEBCDIC(b)) ch = codePage.ebcdic2uni(b); - else ch = (char) b; - planes.setScreenCharAndAttr(y, ch, la, false); - } - } - } - - int numFields = bk.getNextByte() << 8 & 0xff00; - numFields |= bk.getNextByte() & 0xff; - Log.d(TAG, "number of fields " + numFields); - - if (numFields > 0) { - int x = 0; - int attr = 0; - int fPos = 0; - int fLen = 0; - int ffw1 = 0; - int ffw2 = 0; - int fcw1 = 0; - int fcw2 = 0; - boolean mdt = false; - ScreenField sf = null; - - while (x < numFields) { - attr = bk.getNextByte(); - fPos = bk.getNextByte() << 8 & 0xff00; - fPos |= bk.getNextByte() & 0xff; - - if (bk.getNextByte() == 1) - mdt = true; - else - mdt = false; - - fLen = bk.getNextByte() << 8 & 0xff00; - fLen |= bk.getNextByte() & 0xff; - ffw1 = bk.getNextByte(); - ffw2 = bk.getNextByte(); - fcw1 = bk.getNextByte(); - fcw2 = bk.getNextByte(); - sf = screen52.getScreenFields().setField(attr, - screen52.getRow(fPos), screen52.getCol(fPos), fLen, - ffw1, ffw2, fcw1, fcw2); - - while (fLen-- > 0) { - // now we set the field plane attributes - planes.setScreenFieldAttr(fPos++, ffw1); - } - - if (mdt) { - sf.setMDT(); - screen52.getScreenFields().setMasterMDT(); - } - - Log.d(TAG, "Restored "); - Log.d(TAG, sf.toString()); - x++; - } - } - - // Redraw the gui fields if we are in gui mode - if (screen52.isUsingGuiInterface()) - screen52.drawFields(); - - screen52.restoreScreen(); // display the screen - // The position was saved with currentPos which 1,1 offset of the - // screen position. - // The setPendingInsert is the where the cursor position will be - // displayed after the restore. - screen52.setPendingInsert(true, screen52.getRow(pos + cols), screen52 - .getCol(pos + cols)); - // We need to offset the pos by -1 since the position is 1,1 based - // and the goto_XY is 0,0 based. - screen52.goto_XY(pos - 1); - screen52.isInField(); - // // Redraw the gui fields if we are in gui mode - // if (screen52.isUsingGuiInterface()) - // screen52.drawFields(); - } - catch (Exception e) { - Log.w(TAG, "error restoring screen " + which + " with " - + e.getMessage()); - } - } - - public final boolean waitingForInput() { - return waitingForInput; - } - - private void parseIncoming() { - boolean done = false; - boolean error = false; - - try { - while (bk.hasNext() && !done) { - byte b = bk.getNextByte(); - - switch (b) { - case 0: - case 1: - break; - - case CMD_SAVE_SCREEN: // 0x02 2 Save Screen - case 3: // 0x03 3 Save Partial Screen - Log.d(TAG, "save screen partial"); - saveScreen(); - break; - - case ESC: // ESCAPE - break; - - case 7: // audible bell - manager.playBeep(); - bk.getNextByte(); - bk.getNextByte(); - break; - - case CMD_WRITE_TO_DISPLAY: // 0x11 17 write to display - error = writeToDisplay(true); - - // WVL - LDC : TR.000300 : Callback scenario from 5250 - // Only scan when WRITE_TO_DISPLAY operation (i.e. refill - // screen buffer) - // has been issued! - if (scan) - scan(); - - break; - - case CMD_RESTORE_SCREEN: // 0x12 18 Restore Screen - case 13: // 0x13 19 Restore Partial Screen - Log.d(TAG, "restore screen partial"); - restoreScreen(); - break; - - case CMD_CLEAR_UNIT_ALTERNATE: // 0x20 32 clear unit alternate - int param = bk.getNextByte(); - - if (param != 0) { - Log.d(TAG, " clear unit alternate error " - + Integer.toHexString(param)); - sendNegResponse(NR_REQUEST_ERROR, 03, 01, 05, - " clear unit alternate not supported"); - done = true; - } - else { - if (screen52.getRows() != 27) - screen52.setRowsCols(27, 132); - - screen52.clearAll(); - - if (sfParser != null && sfParser.isGuisExists()) - sfParser.clearGuiStructs(); - } - - break; - - case CMD_WRITE_ERROR_CODE: // 0x21 33 Write Error Code - writeErrorCode(); - error = writeToDisplay(false); - break; - - case CMD_WRITE_ERROR_CODE_TO_WINDOW: // 0x22 34 - // Write Error Code to window - writeErrorCodeToWindow(); - error = writeToDisplay(false); - break; - - case CMD_READ_SCREEN_IMMEDIATE: // 0x62 98 - case CMD_READ_SCREEN_TO_PRINT: // 0x66 102 read screen to print - readScreen(); - break; - - case CMD_CLEAR_UNIT: // 64 0x40 clear unit - if (screen52.getRows() != 24) - screen52.setRowsCols(24, 80); - - screen52.clearAll(); - - if (sfParser != null && sfParser.isGuisExists()) - sfParser.clearGuiStructs(); - - break; - - case CMD_CLEAR_FORMAT_TABLE: // 80 0x50 Clear format table - screen52.clearTable(); - break; - - case CMD_READ_INPUT_FIELDS: //0x42 66 read input fields - case CMD_READ_MDT_FIELDS: // 0x52 82 read MDT Fields - bk.getNextByte(); - bk.getNextByte(); - readType = b; - screen52.goHome(); - // do nothing with the cursor here it is taken care of - // in the main loop. - //////////////// screen52.setCursorOn(); - waitingForInput = true; - pendingUnlock = true; - // screen52.setKeyboardLocked(false); - break; - - case CMD_READ_MDT_IMMEDIATE_ALT: // 0x53 83 - readType = b; - // screen52.goHome(); - // waitingForInput = true; - // screen52.setKeyboardLocked(false); - readImmediate(readType); - break; - - case CMD_WRITE_STRUCTURED_FIELD: // 243 0xF3 -13 Write - // structured field - writeStructuredField(); - break; - - case CMD_ROLL: // 0x23 35 Roll Not sure what it does right now - int updown = bk.getNextByte(); - int topline = bk.getNextByte(); - int bottomline = bk.getNextByte(); - screen52.rollScreen(updown, topline, bottomline); - break; - - default: - done = true; - sendNegResponse(NR_REQUEST_ERROR, 03, 01, 01, - "parseIncoming"); - break; - } - - if (error) - done = true; - } - } - catch (Exception exc) { - Log.w(TAG, "incoming " + exc.getMessage()); - } - } - - /** - * This routine handles sending negative responses back to the host. - * - * You can find a description of the types of responses to be sent back by - * looking at section 12.4 of the 5250 Functions Reference manual - * - * - * @param cat - * @param modifier - * @param uByte1 - * @param uByte2 - * @param from - * - */ - protected void sendNegResponse(int cat, int modifier, int uByte1, - int uByte2, String from) { - try { - int os = bk.getByteOffset(-1) & 0xf0; - int cp = (bk.getCurrentPos() - 1); - Log.i(TAG, "invalid " + from + " command " + os - + " at pos " + cp); - } - catch (Exception e) { - Log.w(TAG, "Send Negative Response error " + e.getMessage()); - } - - baosp.write(cat); - baosp.write(modifier); - baosp.write(uByte1); - baosp.write(uByte2); - - try { - Log.i(TAG, "sendNegResponse() writeGDS()"); - writeGDS(128, 0, baosp.toByteArray()); - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - } - - baosp.reset(); - } - - public void sendNegResponse2(int ec) { - screen52.setPrehelpState(true, true, false); - baosp.write(0x00); - baosp.write(ec); - - try { - Log.i(TAG, "sendNegResponse2() writeGDS()"); - writeGDS(1, 0, baosp.toByteArray()); - } - catch (IOException ioe) { - Log.w(TAG, ioe.getMessage()); - } - - baosp.reset(); - } - - private boolean writeToDisplay(boolean controlsExist) { - boolean error = false; - boolean done = false; - int attr; - byte control0 = 0; - byte control1 = 0; - int saRows = screen52.getRows(); - int saCols = screen52.getColumns(); - - try { - if (controlsExist) { - control0 = bk.getNextByte(); - control1 = bk.getNextByte(); - processCC0(control0); - } - - while (bk.hasNext() && !done) { - // pos = bk.getCurrentPos(); - // int rowc = screen52.getCurrentRow(); - // int colc = screen52.getCurrentCol(); - byte bytebk = bk.getNextByte(); - - switch (bytebk) { - case 1: // SOH - Start of Header Order - Log.d(TAG, "SOH - Start of Header Order"); - error = processSOH(); - break; - - case 02: // RA - Repeat to address - Log.d(TAG, "RA - Repeat to address"); - int row = screen52.getCurrentRow(); - int col = screen52.getCurrentCol(); - int toRow = bk.getNextByte(); - int toCol = bk.getNextByte() & 0xff; - - if (toRow >= row) { - int repeat = bk.getNextByte(); - - // a little intelligence here I hope - if (row == 1 && col == 2 && toRow == screen52.getRows() - && toCol == screen52.getColumns()) - screen52.clearScreen(); - else { - if (repeat != 0) { - //LDC - 13/02/2003 - convert it to unicode - repeat = codePage.ebcdic2uni(repeat); - //repeat = getASCIIChar(repeat); - } - - int times = ((toRow * screen52.getColumns()) + toCol) - - ((row * screen52.getColumns()) + col); - - while (times-- >= 0) { - screen52.setChar(repeat); - } - } - } - else { - sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x23, - " RA invalid"); - error = true; - } - - break; - - case 03: // EA - Erase to address - Log.d(TAG, "EA - Erase to address"); - int EArow = screen52.getCurrentRow(); - int EAcol = screen52.getCurrentCol(); - int toEARow = bk.getNextByte(); - int toEACol = bk.getNextByte() & 0xff; - int EALength = bk.getNextByte() & 0xff; - - while (--EALength > 0) { - bk.getNextByte(); - } - - char EAAttr = (char) 0; - - // a little intelligence here I hope - if (EArow == 1 && EAcol == 2 - && toEARow == screen52.getRows() - && toEACol == screen52.getColumns()) - screen52.clearScreen(); - else { - int times = ((toEARow * screen52.getColumns()) + toEACol) - - ((EArow * screen52.getColumns()) + EAcol); - - while (times-- >= 0) { - screen52.setChar(EAAttr); - } - } - - break; - - case 04: // Command - Escape - Log.d(TAG, "Command - Escape"); - done = true; - break; - - case 16: // TD - Transparent Data - Log.d(TAG, "TD - Transparent Data"); - int j = (bk.getNextByte() & 0xff) << 8 | bk.getNextByte() - & 0xff; // length - break; - - case 17: // SBA - set buffer address order (row column) - //Log.d(TAG,"SBA - set buffer address order (row column)"); - int saRow = bk.getNextByte(); - int saCol = bk.getNextByte() & 0xff; - - // make sure it is in bounds - if (saRow >= 0 && saRow <= screen52.getRows() && saCol >= 0 - && saCol <= screen52.getColumns()) { - screen52.setCursor(saRow, saCol); // now set screen - // position for output - } - else { - sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x22, - "invalid row/col order" + " saRow = " + saRow - + " saRows = " + screen52.getRows() - + " saCol = " + saCol); - error = true; - } - - break; - - case 18: // WEA - Extended Attribute - Log.d(TAG, "WEA - Extended Attribute"); - bk.getNextByte(); - bk.getNextByte(); - break; - - case 19: // IC - Insert Cursor - Log.d(TAG, "IC - Insert Cursor"); - int icX = bk.getNextByte(); - int icY = bk.getNextByte() & 0xff; - - if (icX >= 0 && icX <= saRows && icY >= 0 && icY <= saCols) { - Log.d(TAG, " IC " + icX + " " + icY); - screen52.setPendingInsert(true, icX, icY); - } - else { - sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x22, - " IC/IM position invalid "); - error = true; - } - - break; - - case 20: // MC - Move Cursor - Log.d(TAG, "MC - Move Cursor"); - int imcX = bk.getNextByte(); - int imcY = bk.getNextByte() & 0xff; - - if (imcX >= 0 && imcX <= saRows && imcY >= 0 - && imcY <= saCols) { - Log.d(TAG, " MC " + imcX + " " + imcY); - screen52.setPendingInsert(false, imcX, imcY); - } - else { - sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x22, - " IC/IM position invalid "); - error = true; - } - - break; - - case 21: // WTDSF - Write To Display Structured Field order - Log.d(TAG, "WTDSF - Write To Display Structured Field order"); - byte[] seg = bk.getSegment(); - error = sfParser.parseWriteToDisplayStructuredField(seg); - break; - - case 29: // SF - Start of Field - Log.d(TAG, "SF - Start of Field"); - int fcw1 = 0; - int fcw2 = 0; - int ffw1 = 0; - int ffw0 = bk.getNextByte() & 0xff; // FFW - - if ((ffw0 & 0x40) == 0x40) { - ffw1 = bk.getNextByte() & 0xff; // FFW 1 - fcw1 = bk.getNextByte() & 0xff; // check for field - - // control word - - // check if the first fcw1 is an 0x81 if it is then get - // the next pair for checking - if (fcw1 == 0x81) { - bk.getNextByte(); - fcw1 = bk.getNextByte() & 0xff; // check for field - // control word - } - - if (!isAttribute(fcw1)) { - fcw2 = bk.getNextByte() & 0xff; // FCW 2 - attr = bk.getNextByte() & 0xff; // attribute field - - while (!isAttribute(attr)) { - Log.i(TAG, Integer.toHexString(fcw1) + " " - + Integer.toHexString(fcw2) - + " "); - Log.i(TAG, Integer.toHexString(attr) - + " " - + Integer.toHexString(bk - .getNextByte() & 0xff)); - attr = bk.getNextByte() & 0xff; // attribute field - } - } - else { - attr = fcw1; // attribute of field - fcw1 = 0; - } - } - else { - attr = ffw0; - } - - int fLength = (bk.getNextByte() & 0xff) << 8 - | bk.getNextByte() & 0xff; - screen52.addField(attr, fLength, ffw0, ffw1, fcw1, fcw2); - break; - - // WVL - LDC : 05/08/2005 : TFX.006253 - Support STRPCCMD - case -128: //STRPCCMD - // if (screen52.getCurrentPos() == 82) { - Log.d(TAG, "STRPCCMD got a -128 command at " + screen52.getCurrentPos()); - StringBuffer value = new StringBuffer(); - int b; - char c; - int[] pco = new int[9]; - int[] pcoOk = {0xfc, 0xd7, 0xc3, 0xd6, 0x40, 0x83, 0x80, 0xa1, 0x80}; - - for (int i = 0; i < 9; i++) { - b = bk.getNextByte(); - pco[i] = ((b & 0xff)); - c = codePage.ebcdic2uni(b); - value.append(c); - } - - // Check "PCO-String" - if (Arrays.equals(pco, pcoOk)) { - strpccmd = true; - } - - // we return in the stream to have all chars - // arrive at the screen for later processing - for (int i = 0; i < 9; i++) - bk.setPrevByte(); - - //} - // no break: so every chars arrives - // on the screen for later parsing - //break; - - default: // all others must be output to screen - //Log.d(TAG,"all others must be output to screen"); - byte byte0 = bk.getByteOffset(-1); - - if (isAttribute(byte0)) { - screen52.setAttr(byte0); - } - else { - if (!screen52.isStatusErrorCode()) { - if (!isDataEBCDIC(byte0)) { - // if (byte0 == 255) { - // sendNegResponse(NR_REQUEST_ERROR,0x05,0x01,0x42, - // " Attempt to send FF to screen"); - // } - // else - screen52.setChar(byte0); - } - else - //LDC - 13/02/2003 - Convert it to unicode - //screen52.setChar(getASCIIChar(byte0)); - screen52.setChar(codePage.ebcdic2uni(byte0)); - } - else { - if (byte0 == 0) - screen52.setChar(byte0); - else - //LDC - 13/02/2003 - Convert it to unicode - //screen52.setChar(getASCIIChar(byte0)); - screen52.setChar(codePage.ebcdic2uni(byte0)); - } - } - - break; - } - - if (error) - done = true; - } - } - catch (Exception e) { - Log.w(TAG, "write to display " + e.getMessage()); - e.printStackTrace(); - } - - ; - - processCC1(control1); - - return error; - } - - private boolean processSOH() throws Exception { - int l = bk.getNextByte(); // length - Log.d(TAG, " byte 0 " + l); - - if (l > 0 && l <= 7) { - bk.getNextByte(); // flag byte 2 - bk.getNextByte(); // reserved - bk.getNextByte(); // resequence fields - screen52.clearTable(); - - // well that is the first time I have seen this. This fixes a - // problem with S/36 command line. Finally got it. - if (l <= 3) return false; - - screen52.setErrorLine(bk.getNextByte()); // error row - int byte1 = 0; - - if (l >= 5) { - byte1 = bk.getNextByte(); - dataIncluded[23] = (byte1 & 0x80) == 0x80; - dataIncluded[22] = (byte1 & 0x40) == 0x40; - dataIncluded[21] = (byte1 & 0x20) == 0x20; - dataIncluded[20] = (byte1 & 0x10) == 0x10; - dataIncluded[19] = (byte1 & 0x8) == 0x8; - dataIncluded[18] = (byte1 & 0x4) == 0x4; - dataIncluded[17] = (byte1 & 0x2) == 0x2; - dataIncluded[16] = (byte1 & 0x1) == 0x1; - } - - if (l >= 6) { - byte1 = bk.getNextByte(); - dataIncluded[15] = (byte1 & 0x80) == 0x80; - dataIncluded[14] = (byte1 & 0x40) == 0x40; - dataIncluded[13] = (byte1 & 0x20) == 0x20; - dataIncluded[12] = (byte1 & 0x10) == 0x10; - dataIncluded[11] = (byte1 & 0x8) == 0x8; - dataIncluded[10] = (byte1 & 0x4) == 0x4; - dataIncluded[9] = (byte1 & 0x2) == 0x2; - dataIncluded[8] = (byte1 & 0x1) == 0x1; - } - - if (l >= 7) { - byte1 = bk.getNextByte(); - dataIncluded[7] = (byte1 & 0x80) == 0x80; - dataIncluded[6] = (byte1 & 0x40) == 0x40; - dataIncluded[5] = (byte1 & 0x20) == 0x20; - dataIncluded[4] = (byte1 & 0x10) == 0x10; - dataIncluded[3] = (byte1 & 0x8) == 0x8; - dataIncluded[2] = (byte1 & 0x4) == 0x4; - dataIncluded[1] = (byte1 & 0x2) == 0x2; - dataIncluded[0] = (byte1 & 0x1) == 0x1; - } - - return false; - } - else { - sendNegResponse(NR_REQUEST_ERROR, 0x05, 0x01, 0x2B, - "invalid SOH length"); - return true; - } - } - - private void processCC0(byte byte0) { - Log.d(TAG, " Control byte0 " + Integer.toBinaryString(byte0 & 0xff)); - boolean lockKeyboard = true; - boolean resetMDT = false; - boolean resetMDTAll = false; - boolean nullMDT = false; - boolean nullAll = false; - - // Bits 3 to 6 are reserved and should be set to '0000' - // 0xE0 = '11100000' - only the first 3 bits are tested - if ((byte0 & 0xE0) == 0x00) { - lockKeyboard = false; - } - - // '00100000' = 0x20 /32 -- just lock keyboard - // '01000000' = 0x40 /64 - // '01100000' = 0x60 /96 - // '10000000' = 0x80 /128 - // '10100000' = 0xA0 /160 - // '11000000' = 0xC0 /192 - // '11100000' = 0xE0 /224 - - switch (byte0 & 0xE0) { - case 0x40: - resetMDT = true; - break; - - case 0x60: - resetMDTAll = true; - break; - - case 0x80: - nullMDT = true; - break; - - case 0xA0: - resetMDT = true; - nullAll = true; - break; - - case 0xC0: - resetMDT = true; - nullMDT = true; - break; - - case 0xE0: - resetMDTAll = true; - nullAll = true; - break; - } - - if (lockKeyboard) { - screen52.getOIA().setKeyBoardLocked(true); - pendingUnlock = false; - } - else - pendingUnlock = false; - - if (resetMDT || resetMDTAll || nullMDT || nullAll) { - ScreenField sf; - int f = screen52.getScreenFields().getSize(); - - for (int x = 0; x < f; x++) { - sf = screen52.getScreenFields().getField(x); - - if (!sf.isBypassField()) { - if ((nullMDT && sf.mdt) || nullAll) { - sf.setFieldChar((char) 0x0); - screen52.drawField(sf); - } - } - - if (resetMDTAll || (resetMDT && !sf.isBypassField())) - sf.resetMDT(); - } - - sf = null; - } - } - - private void processCC1(byte byte1) { - Log.d(TAG, " Control byte1 " + Integer.toBinaryString(byte1 & 0xff)); - - if ((byte1 & 0x04) == 0x04) { - manager.playBeep(); - } - - if ((byte1 & 0x02) == 0x02) { - screen52.getOIA().setMessageLightOff(); - } - - if ((byte1 & 0x01) == 0x01) { - screen52.getOIA().setMessageLightOn(); - } - - if ((byte1 & 0x01) == 0x01 && (byte1 & 0x02) == 0x02) { - screen52.getOIA().setMessageLightOn(); - } - - // reset blinking cursor seems to control whether to set or not set the - // the cursor position. No documentation for this just testing and - // looking at the bit settings of this field. This was a pain in the - // ass! - // - // if it is off '0' then keep existing cursor positioning information - // if it is on '1' then reset the cursor positioning information - // *** Note *** unless we receive bit 4 on at the same time - // this seems to work so far - if ((byte1 & 0x20) == 0x20 && (byte1 & 0x08) == 0x00) { - screen52.setPendingInsert(false); - Log.d(TAG, " WTD position no move"); - } - else { - screen52.setPendingInsert(true); - Log.d(TAG, " WTD position move to home" + screen52.homePos + " row " - + screen52.getRow(screen52.homePos) + " col " - + screen52.getCol(screen52.homePos)); - } - - // in enhanced mode we sometimes only receive bit 6 turned on which - // is reset blinking cursor - if ((byte1 & 0x20) == 0x20 && enhanced) { - cursorOn = true; - } - - if (!screen52.isStatusErrorCode() && (byte1 & 0x08) == 0x08) { - // screen52.setStatus(screen52.STATUS_SYSTEM,screen52.STATUS_VALUE_OFF,null); - cursorOn = true; - } - - if ((byte1 & 0x20) == 0x20 && (byte1 & 0x08) == 0x00) { - screen52.setPendingInsert(false, 1, 1); - } - } - - private boolean isAttribute(int byte0) { - int byte1 = byte0 & 0xff; - return (byte1 & 0xe0) == 0x20; - } - - //LDC - 12/02/2003 - Function name changed from isData to isDataEBCDIC - private boolean isDataEBCDIC(int byte0) { - int byte1 = byte0 & 0xff; - - // here it should always be less than 255 - if (byte1 >= 64 && byte1 < 255) - return true; - else - return false; - } - - //LDC - 12/02/2003 - Test if the unicode character is a displayable - // character. - // The first 32 characters are non displayable characters - // This is normally the inverse of isDataEBCDIC (That's why there is a - // check on 255 -> 0xFFFF - private boolean isDataUnicode(int byte0) { - return (((byte0 < 0) || (byte0 >= 32)) && (byte0 != 0xFFFF)); - } - - private void writeStructuredField() { - boolean done = false; - - try { - int length = ((bk.getNextByte() & 0xff) << 8 | (bk.getNextByte() & 0xff)); - - while (bk.hasNext() && !done) { - switch (bk.getNextByte()) { - case -39: // SOH - Start of Header Order - switch (bk.getNextByte()) { - case 112: // 5250 Query - bk.getNextByte(); // get null required field - sendQueryResponse(); - break; - - default: - Log.d(TAG, "invalid structured field sub command " - + bk.getByteOffset(-1)); - break; - } - - break; - - default: - Log.d(TAG, "invalid structured field command " - + bk.getByteOffset(-1)); - break; - } - } - } - catch (Exception e) { - } - - ; - } - - private final void writeErrorCode() throws Exception { - screen52.setCursor(screen52.getErrorLine(), 1); // Skip the control byte - screen52.setStatus(Screen5250.STATUS_ERROR_CODE, - Screen5250.STATUS_VALUE_ON, null); - screen52.saveErrorLine(); - cursorOn = true; - } - - private final void writeErrorCodeToWindow() throws Exception { - int fromCol = bk.getNextByte() & 0xff; // from column - int toCol = bk.getNextByte() & 0xff; // to column - screen52.setCursor(screen52.getErrorLine(), fromCol); // Skip the control byte - screen52.setStatus(Screen5250.STATUS_ERROR_CODE, - Screen5250.STATUS_VALUE_ON, null); - screen52.saveErrorLine(); - cursorOn = true; - } - - /** - * Method sendQueryResponse - * - * The query command is used to obtain information about the capabilities of - * the 5250 display. - * - * The Query command must follow an Escape (0x04) and Write Structured Field - * command (0xF3). - * - * This section is modeled after the rfc1205 - 5250 Telnet Interface section - * 5.3 - * - * @throws IOException - */ - private final void sendQueryResponse() throws IOException { - Log.i(TAG, "sending query response"); - byte abyte0[] = new byte[64]; - abyte0[0] = 0; // Cursor Row/column (set to zero) - abyte0[1] = 0; // "" - abyte0[2] = -120; // X'88' inbound write structure Field aid - - if (enhanced) { - abyte0[3] = 0; // 0x003D (61) length of query response - abyte0[4] = 64; // "" see note below ????????? - } - else { - abyte0[3] = 0; // 0x003A (58) length of query response - abyte0[4] = 58; // "" - // the length between 58 and 64 seems to cause - // different formatting codes to be sent from - // the host ???????????????? why ??????? - // Well the why can be found in the manual if - // read a little more ;-) - } - - abyte0[5] = -39; // command class 0xD9 - abyte0[6] = 112; // Command type query 0x70 - abyte0[7] = -128; // 0x80 Flag byte - abyte0[8] = 6; // Controller Hardware Class - abyte0[9] = 0; // 0x0600 - Other WSF or another 5250 Emulator - abyte0[10] = 1; // Controller Code Level - abyte0[11] = 1; // Version 1 Rel 1.0 - abyte0[12] = 0; // "" - abyte0[13] = 0; // 13 - 28 are reserved so set to 0x00 - abyte0[14] = 0; // "" - abyte0[15] = 0; // "" - abyte0[16] = 0; // "" - abyte0[17] = 0; // "" - abyte0[18] = 0; // "" - abyte0[19] = 0; // "" - abyte0[20] = 0; // "" - abyte0[21] = 0; // "" - abyte0[22] = 0; // "" - abyte0[23] = 0; // "" - abyte0[24] = 0; // "" - abyte0[25] = 0; // "" - abyte0[26] = 0; // "" - abyte0[27] = 0; // "" - abyte0[28] = 0; // "" - abyte0[29] = 1; // Device type - 0x01 5250 Emulator - abyte0[30] = codePage.uni2ebcdic('5'); // Device type character - abyte0[31] = codePage.uni2ebcdic('2'); // "" - abyte0[32] = codePage.uni2ebcdic('5'); // "" - abyte0[33] = codePage.uni2ebcdic('1'); // "" - abyte0[34] = codePage.uni2ebcdic('0'); // "" - abyte0[35] = codePage.uni2ebcdic('1'); // "" - abyte0[36] = codePage.uni2ebcdic('1'); // "" - abyte0[37] = 2; // Keyboard Id - 0x02 Standard Keyboard - abyte0[38] = 0; // extended keyboard id - abyte0[39] = 0; // reserved - abyte0[40] = 0; // 40 - 43 Display Serial Number - abyte0[41] = 36; // - abyte0[42] = 36; // - abyte0[43] = 0; // - abyte0[44] = 1; // Maximum number of display fields - 256 - abyte0[45] = 0; // 0x0100 - abyte0[46] = 0; // 46 -48 Reserved set to 0x00 - abyte0[47] = 0; - abyte0[48] = 0; - abyte0[49] = 1; // 49 - 53 Controller Display Capability - abyte0[50] = 17; // see rfc - tired of typing :-) - abyte0[51] = 0; // "" - abyte0[52] = 0; // "" - - // 53 - // Bit 0-2: B'000' - no graphics capability - // B'001' - 5292-2 style graphics - // Bit 3-7: B '00000' = reserved (it seems for Client access) - - if (enhanced) { - // abyte0[53] = 0x5E; // 0x5E turns on enhanced mode - // abyte0[53] = 0x27; // 0x5E turns on enhanced mode - abyte0[53] = 0x7; // 0x5E turns on ehnhanced mode - Log.i(TAG, "enhanced options"); - } - else - abyte0[53] = 0x0; // 0x0 is normal emulation - - abyte0[54] = 24; // 54 - 60 Reserved set to 0x00 - // 54 - I found out is used for enhanced user - // interface level 3. Bit 4 allows headers - // and footers for windows - abyte0[54] = 8; // 54 - 60 Reserved set to 0x00 - // 54 - I found out is used for enhanced user - // interface level 3. Bit 4 allows headers - // and footers for windows - abyte0[55] = 0; - abyte0[56] = 0; - abyte0[57] = 0; - abyte0[58] = 0; - abyte0[59] = 0; - abyte0[60] = 0; - abyte0[61] = 0; // gridlines are not supported - abyte0[62] = 0; // gridlines are not supported - abyte0[63] = 0; - Log.i(TAG, "sendQueryResponse() writeGDS()"); - writeGDS(0, 0, abyte0); // now tell them about us - abyte0 = null; - } - - protected final boolean negotiate(byte abyte0[]) throws IOException { - int i = 0; - - // from server negotiations - if (abyte0[i] == IAC) { // -1 - while (i < abyte0.length && abyte0[i++] == -1) - - // while(i < abyte0.length && (abyte0[i] == -1 || abyte0[i++] == 0x20)) - switch (abyte0[i++]) { - // we will not worry about what it WONT do - case WONT: // -4 - default: - break; - - case DO: //-3 - - // not sure why but since moving to V5R2 we are receiving a - // DO with no option when connecting a second session with - // device name. Can not find the cause at all. If anybody - // is interested please debug this until then this works. - if (i < abyte0.length) { - switch (abyte0[i]) { - case TERMINAL_TYPE: // 24 - baosp.write(IAC); - baosp.write(WILL); - baosp.write(TERMINAL_TYPE); - writeByte(baosp.toByteArray()); - baosp.reset(); - break; - - case OPT_END_OF_RECORD: // 25 - baosp.write(IAC); - baosp.write(WILL); - baosp.write(OPT_END_OF_RECORD); - writeByte(baosp.toByteArray()); - baosp.reset(); - break; - - case TRANSMIT_BINARY: // 0 - baosp.write(IAC); - baosp.write(WILL); - baosp.write(TRANSMIT_BINARY); - writeByte(baosp.toByteArray()); - baosp.reset(); - break; - - case TIMING_MARK: // 6 rfc860 - // System.out.println("Timing Mark Received and notifying " + - // "the server that we will not do it"); - baosp.write(IAC); - baosp.write(WONT); - baosp.write(TIMING_MARK); - writeByte(baosp.toByteArray()); - baosp.reset(); - break; - - case NEW_ENVIRONMENT: // 39 rfc1572, rfc4777 - // allways send new environment vars ... - baosp.write(IAC); - baosp.write(WILL); - baosp.write(NEW_ENVIRONMENT); - writeByte(baosp.toByteArray()); - baosp.reset(); - break; - - default: // every thing else we will not do at this time - baosp.write(IAC); - baosp.write(WONT); - baosp.write(abyte0[i]); // either - writeByte(baosp.toByteArray()); - baosp.reset(); - break; - } - } - - i++; - break; - - case WILL: - switch (abyte0[i]) { - case OPT_END_OF_RECORD: // 25 - baosp.write(IAC); - baosp.write(DO); - baosp.write(OPT_END_OF_RECORD); - writeByte(baosp.toByteArray()); - baosp.reset(); - break; - - case TRANSMIT_BINARY: // '\0' - baosp.write(IAC); - baosp.write(DO); - baosp.write(TRANSMIT_BINARY); - writeByte(baosp.toByteArray()); - baosp.reset(); - break; - } - - i++; - break; - - case SB: // -6 - if (abyte0[i] == NEW_ENVIRONMENT && abyte0[i + 1] == 1) { - negNewEnvironment(); - - while (++i < abyte0.length && abyte0[i + 1] != IAC); - } - - if (abyte0[i] == TERMINAL_TYPE && abyte0[i + 1] == 1) { - baosp.write(IAC); - baosp.write(SB); - baosp.write(TERMINAL_TYPE); - baosp.write(QUAL_IS); - - if (!support132) - baosp.write("IBM-3179-2".getBytes()); - else - baosp.write("IBM-3477-FC".getBytes()); - - baosp.write(IAC); - baosp.write(SE); - writeByte(baosp.toByteArray()); - baosp.reset(); - i++; - } - - i++; - break; - } - - return true; - } - else { - return false; - } - } - - /** - * Negotiate new environment string for device name - * - * @throws IOException - */ - private void negNewEnvironment() throws IOException { - baosp.write(IAC); - baosp.write(SB); - baosp.write(NEW_ENVIRONMENT); - baosp.write(IS); - - // http://tools.ietf.org/html/rfc4777 - - if (kbdTypesCodePage != null) { - baosp.write(USERVAR); - baosp.write("KBDTYPE".getBytes()); - baosp.write(VALUE); - baosp.write(kbdTypesCodePage.kbdType.getBytes()); - baosp.write(USERVAR); - baosp.write("CODEPAGE".getBytes()); - baosp.write(VALUE); - baosp.write(kbdTypesCodePage.codepage.getBytes()); - baosp.write(USERVAR); - baosp.write("CHARSET".getBytes()); - baosp.write(VALUE); - baosp.write(kbdTypesCodePage.charset.getBytes()); - } - - if (devName != null) { - baosp.write(USERVAR); - baosp.write("DEVNAME".getBytes()); - baosp.write(VALUE); - baosp.write(negDeviceName().getBytes()); - } - - if (user != null) { - baosp.write(VAR); - baosp.write("USER".getBytes()); - baosp.write(VALUE); - baosp.write(user.getBytes()); - - if (password != null) { - baosp.write(USERVAR); - baosp.write("IBMRSEED".getBytes()); - baosp.write(VALUE); - baosp.write(NEGOTIATE_ESC); - baosp.write(0x0); - baosp.write(0x0); - baosp.write(0x0); - baosp.write(0x0); - baosp.write(0x0); - baosp.write(0x0); - baosp.write(0x0); - baosp.write(0x0); - baosp.write(USERVAR); - baosp.write("IBMSUBSPW".getBytes()); - baosp.write(VALUE); - baosp.write(password.getBytes()); - } - - if (library != null) { - baosp.write(USERVAR); - baosp.write("IBMCURLIB".getBytes()); - baosp.write(VALUE); - baosp.write(library.getBytes()); - } - - if (initialMenu != null) { - baosp.write(USERVAR); - baosp.write("IBMIMENU".getBytes()); - baosp.write(VALUE); - baosp.write(initialMenu.getBytes()); - } - - if (program != null) { - baosp.write(USERVAR); - baosp.write("IBMPROGRAM".getBytes()); - baosp.write(VALUE); - baosp.write(program.getBytes()); - } - } - - baosp.write(IAC); - baosp.write(SE); - writeByte(baosp.toByteArray()); - baosp.reset(); - } - - /** - * This will negotiate a device name with controller. if the sequence is - * less than zero then it will send the device name as specified. On each - * unsuccessful attempt a sequential number is appended until we find one or - * the controller says no way. - * - * @return String - */ - private String negDeviceName() { - if (devSeq++ == -1) { - devNameUsed = devName; - return devName; - } - else { - StringBuffer sb = new StringBuffer(devName + devSeq); - int ei = 1; - - while (sb.length() > 10) { - sb.setLength(0); - sb.append(devName.substring(0, devName.length() - ei++)); - sb.append(devSeq); - } - - devNameUsed = sb.toString(); - return devNameUsed; - } - } - - public final void setCodePage(String cp) { - codePage = CharMappings.getCodePage(cp); - cp = cp.toLowerCase(); - - for (KbdTypesCodePages kbdtyp : KbdTypesCodePages.values()) { - if (("cp" + kbdtyp.codepage).equals(cp) || kbdtyp.ccsid.equals(cp)) { - kbdTypesCodePage = kbdtyp; - break; - } - } - - Log.i(TAG, "Chose keyboard mapping " + kbdTypesCodePage.toString() + " for code page " + cp); - } - - public final ICodePage getCodePage() { - return codePage; - } - - public void signalBell() { - manager.playBeep(); - } - -}
--- a/src/org/tn5250j/framework/transport/SSL/SSLImplementation.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -package org.tn5250j.framework.transport.SSL; - -/* - * @(#)SSLImplementation.java - * @author Stephen M. Kennedy - * - * Copyright: Copyright (c) 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.net.Socket; -import java.security.KeyStore; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; - -import org.tn5250j.framework.transport.SSLInterface; -import android.util.Log; - - -/** - * <p> - * This class implements the SSLInterface and is used to create SSL socket - * instances. - * </p> - * - * @author Stephen M. Kennedy <skennedy@tenthpowertech.com> - * - */ -public class SSLImplementation implements SSLInterface, X509TrustManager { - private static final String TAG = "SSLImplementation"; - SSLContext sslContext = null; - KeyStore userks = null; - private String userKsPath; - private char[] userksPassword = "changeit".toCharArray(); - - TerminalBridge bridge = null; - TerminalManager manager = null; - String target = null; // destination:port - - KeyManagerFactory userkmf = null; - - TrustManagerFactory usertmf = null; - - TrustManager[] userTrustManagers = null; - - X509Certificate[] acceptedIssuers; - - public SSLImplementation(TerminalBridge bridge, TerminalManager manager) { - this.bridge = bridge; - this.manager = manager; - } - - public void init(String sslType, String homeDirectory) { - try { - Log.d(TAG, "Initializing User KeyStore"); - userKsPath = homeDirectory + File.separator + "keystore"; - File userKsFile = new File(userKsPath); - userks = KeyStore.getInstance(KeyStore.getDefaultType()); - userks.load(userKsFile.exists() ? new FileInputStream(userKsFile) - : null, userksPassword); - Log.d(TAG, "Initializing User Key Manager Factory"); - userkmf = KeyManagerFactory.getInstance(KeyManagerFactory - .getDefaultAlgorithm()); - userkmf.init(userks, userksPassword); - Log.d(TAG, "Initializing User Trust Manager Factory"); - usertmf = TrustManagerFactory.getInstance(TrustManagerFactory - .getDefaultAlgorithm()); - usertmf.init(userks); - userTrustManagers = usertmf.getTrustManagers(); - Log.d(TAG, "Initializing SSL Context"); - sslContext = SSLContext.getInstance(sslType); - sslContext.init(userkmf.getKeyManagers(), new TrustManager[] {this}, null); - } - catch (Exception ex) { - Log.e(TAG, "Error initializing SSL [" + ex.getMessage() + "]"); - } - } - - public Socket createSSLSocket(String destination, int port) { - if (sslContext == null) - throw new IllegalStateException("SSL Context Not Initialized"); - - SSLSocket socket = null; - - try { - target = destination + ":" + String.valueOf(port); - socket = (SSLSocket) sslContext.getSocketFactory().createSocket( - destination, port); - } - catch (Exception e) { - Log.e(TAG, "Error creating ssl socket [" + e.getMessage() + "]"); - } - - return socket; - } - - // X509TrustManager Methods - - /* - * (non-Javadoc) - * - * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() - */ - public X509Certificate[] getAcceptedIssuers() { - return acceptedIssuers; - } - - /* - * (non-Javadoc) - * - * @see - * javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert. - * X509Certificate[], java.lang.String) - */ - public void checkClientTrusted(X509Certificate[] arg0, String arg1) - throws CertificateException { - throw new SecurityException("checkClientTrusted unsupported"); - } - - /* - * (non-Javadoc) - * - * @see - * javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert. - * X509Certificate[], java.lang.String) - */ - public void checkServerTrusted(X509Certificate[] chain, String type) - throws CertificateException { - try { - for (int i = 0; i < userTrustManagers.length; i++) { - if (userTrustManagers[i] instanceof X509TrustManager) { - X509TrustManager trustManager = (X509TrustManager) userTrustManagers[i]; - X509Certificate[] calist = trustManager - .getAcceptedIssuers(); - - if (calist.length > 0) { - trustManager.checkServerTrusted(chain, type); - } - else { - throw new CertificateException( - "Empty list of accepted issuers (a.k.a. root CA list)."); - } - } - } - - return; - } - catch (CertificateException ce) { - X509Certificate cert = chain[0]; - String certInfo = manager.res.getString(R.string.host_cert_version) + cert.getVersion() + "\r\n"; - certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_serial) + cert.getSerialNumber() + "\r\n"); - certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_algorithm) + cert.getSigAlgName() + "\r\n"); - certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_issuer) + cert.getIssuerDN().getName() + "\r\n"); - certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_from) + cert.getNotBefore() + "\r\n"); - certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_to) + cert.getNotAfter() + "\r\n"); - certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_dn) + cert.getSubjectDN().getName() + "\r\n"); - certInfo = certInfo.concat(manager.res.getString(R.string.host_cert_publickey) + cert.getPublicKey().getFormat() + "\r\n"); - bridge.outputLine(manager.res.getString(R.string.host_authenticity_warning, target)); - bridge.outputLine(manager.res.getString(R.string.host_certificate, certInfo)); - Boolean result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_accept_certificate)); - - if ((result == null) || (!result.booleanValue())) { - throw new java.security.cert.CertificateException( - "Certificate Rejected"); - } - - result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_save_certificate)); - - if ((result != null) && (result.booleanValue())) { - try { - userks.setCertificateEntry(cert.getSubjectDN().getName(), - cert); - userks.store(new FileOutputStream(userKsPath), - userksPassword); - } - catch (Exception e) { - Log.e(TAG, "Error saving certificate [" + e.getMessage() - + "]"); - e.printStackTrace(); - } - } - } - } -} \ No newline at end of file
--- a/src/org/tn5250j/framework/transport/SSL/X509CertificateTrustManager.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -package org.tn5250j.framework.transport.SSL; - -/* - * @(#)X509CertificateTrustManager.java - * - * Copyright: Copyright (c) 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import java.security.cert.X509Certificate; -import java.security.KeyStore; -import java.security.cert.CertificateException; -import java.util.ArrayList; -import java.util.Arrays; - -import com.five_ten_sg.connectbot.R; -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; - - -/** - * This class is used to trust certificates exchanged during an SSL socket - * handshake. It allows the user to accept the certificate so that connections - * can be made without requiring the server to have a certificate signed by a - * CA (Verisign, Thawte, etc.). - * - * @author Stephen M. Kennedy <skennedy@tenthpowertech.com> - * @deprecated. no longer used. - * - */ -public class X509CertificateTrustManager implements X509TrustManager { - - KeyStore ks = null; - TrustManager[] trustManagers; - TerminalBridge bridge = null; - TerminalManager manager = null; - - public X509CertificateTrustManager(TrustManager[] managers, KeyStore keyStore, TerminalBridge bridge, TerminalManager manager) { - this.bridge = bridge; - this.manager = manager; - trustManagers = managers; - ks = keyStore; - } - - public void checkClientTrusted(X509Certificate[] chain, String type) throws CertificateException { - throw new SecurityException("checkClientTrusted unsupported"); - } - - - /** - * Checks the server certificate. If it isn't trusted by the trust manager - * passed to the constructor, then the user will be prompted to accept the - * certificate. - */ - public void checkServerTrusted(X509Certificate[] chain, String type) - throws CertificateException { - try { - for (int i = 0; i < trustManagers.length; i++) { - if (trustManagers[i] instanceof X509TrustManager) - ((X509TrustManager)trustManagers[i]).checkServerTrusted(chain, type); - } - - return; - } - catch (CertificateException ce) { - X509Certificate cert = chain[0]; - String certInfo = "Version: " + cert.getVersion() + "\n"; - certInfo = certInfo.concat("Serial Number: " + cert.getSerialNumber() + "\n"); - certInfo = certInfo.concat("Signature Algorithm: " + cert.getSigAlgName() + "\n"); - certInfo = certInfo.concat("Issuer: " + cert.getIssuerDN().getName() + "\n"); - certInfo = certInfo.concat("Valid From: " + cert.getNotBefore() + "\n"); - certInfo = certInfo.concat("Valid To: " + cert.getNotAfter() + "\n"); - certInfo = certInfo.concat("Subject DN: " + cert.getSubjectDN().getName() + "\n"); - certInfo = certInfo.concat("Public Key: " + cert.getPublicKey().getFormat() + "\n"); - bridge.outputLine(manager.res.getString(R.string.host_certificate, certInfo)); - Boolean result = bridge.promptHelper.requestBooleanPrompt(null, manager.res.getString(R.string.prompt_accept_certificate)); - - if ((result == null) || (!result.booleanValue())) { - throw new java.security.cert.CertificateException("Certificate Not Accepted"); - } - } - } - - public X509Certificate[] getAcceptedIssuers() { - ArrayList<X509Certificate> list = new ArrayList<X509Certificate>(10); - - for (int i = 0; i < trustManagers.length; i++) { - if (trustManagers[i] instanceof X509TrustManager) - list.addAll(Arrays.asList(((X509TrustManager)trustManagers[i]).getAcceptedIssuers())); - } - - X509Certificate[] acceptedIssuers = new X509Certificate[list.size()]; - acceptedIssuers = list.toArray(acceptedIssuers); - return acceptedIssuers; - } -} \ No newline at end of file
--- a/src/org/tn5250j/framework/transport/SSLInterface.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -package org.tn5250j.framework.transport; - -/* - * @(#)SSLInterface.java - * - * Copyright: Copyright (c) 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -import java.net.Socket; - -public interface SSLInterface { - - /** - * Initialize the components required to create a new client socket - * when createSSLSocket is called. - * @param sslType The ssl socket type (NONE, SSLv2, SSLv3, TLS) - * @param homeDirectory location of the .tn5250j subdirectory containing - * the keystore - * @see org.tn5250j.framework.transport.SSLConstants - */ - public abstract void init(String sslType, String homeDirectory); - - /** - * Create a new socket - * @param destination - * @param port - * @return new socket, or null if none could be created. - */ - public abstract Socket createSSLSocket(String destination, int port); - -} \ No newline at end of file
--- a/src/org/tn5250j/framework/transport/SocketConnector.java Fri Jun 19 13:41:57 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ - -/** - * @(#)SocketConnector.java - * @author Stephen M. Kennedy - * - * Copyright: Copyright (c) 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - */ -package org.tn5250j.framework.transport; - -import java.net.Socket; - -import com.five_ten_sg.connectbot.service.TerminalBridge; -import com.five_ten_sg.connectbot.service.TerminalManager; - -import org.tn5250j.framework.transport.SSL.SSLImplementation; -import org.tn5250j.TN5250jConstants; -import android.util.Log; - - -public class SocketConnector { - private static final String TAG = "SocketConnector"; - - /** - * Creates a new instance that creates a plain socket by default. - */ - public SocketConnector() { - } - - /** - * Create a new client Socket to the given destination, port and sslType of - * encryption. - * @param destination - * @param port - * @return a new client socket, or null if - */ - public Socket createSocket(String destination, int port, String sslType, String homeDirectory, TerminalBridge bridge, TerminalManager manager) { - Socket socket = null; - Exception ex = null; - - if (sslType == null || sslType.trim().length() == 0 || - sslType.toUpperCase().equals(TN5250jConstants.SSL_TYPE_NONE)) { - Log.i(TAG, "Creating Plain Socket"); - - try { - // Use Socket Constructor!!! SocketFactory for jdk 1.4 - socket = new Socket(destination, port); - } - catch (Exception e) { - ex = e; - } - } - else { //SSL SOCKET - Log.i(TAG, "Creating SSL [" + sslType + "] Socket"); - SSLInterface sslIf = null; - - try { - sslIf = (SSLInterface) new SSLImplementation(bridge, manager); - } - catch (Exception e) { - ex = new Exception("Failed to create SSLInterface Instance. " + - "Message is [" + e.getMessage() + "]"); - } - - if (sslIf != null) { - sslIf.init(sslType, homeDirectory); - socket = sslIf.createSSLSocket(destination, port); - } - } - - if (ex != null) { - Log.e(TAG, "exception", ex); - } - - if (socket == null) { - Log.w(TAG, "No socket was created"); - } - - return socket; - } - - -} \ No newline at end of file
--- a/xml/Makefile Fri Jun 19 13:41:57 2015 -0700 +++ b/xml/Makefile Thu Dec 03 11:23:55 2015 -0800 @@ -1,4 +1,4 @@ -ver:=$(shell grep versionName ../AndroidManifest.xml | cut -d'"' -f2) +ver:=$(shell grep versionName ../app/src/main/AndroidManifest.xml | cut -d'"' -f2) pkg:=510Connectbot t:=../html