>How To: Prevent Cross-Site Scripting in ASP.NET

>

Applies To

  • ASP.NET version 1.1
  • ASP.NET version 2.0

Summary

This How To shows how you can help protect your ASP.NET applications from cross-site scripting attacks by using proper input validation techniques and by encoding the output. It also describes a number of other protection mechanisms that you can use in addition to these two main countermeasures.
Cross-site scripting (XSS) attacks exploit vulnerabilities in Web page validation by injecting client-side script code. Common vulnerabilities that make your Web applications susceptible to cross-site scripting attacks include failing to properly validate input, failing to encode output, and trusting the data retrieved from a shared database. To protect your application against cross-site scripting attacks, assume that all input is malicious. Constrain and validate all input. Encode all output that could, potentially, include HTML characters. This includes data read from files and databases.

Contents

Objectives
Overview
Summary of Steps
Step 1. Check That ASP.NET Request Validation Is Enabled
Step 2. Review ASP.NET Code That Generates HTML Output
Step 3. Determine Whether HTML Output Includes Input Parameters
Step 4. Review Potentially Dangerous HTML Tags and Attributes
Step 5. Evaluate Countermeasures
Additional Considerations
Additional Resources

Objectives

  • Understand the common cross-site scripting vulnerabilities in Web page validation.
  • Apply countermeasures for cross-site scripting attacks.
  • Constrain input by using regular expressions, type checks, and ASP.NET validator controls.
  • Constrain output to ensure the browser does not execute HTML tags that contain script code.
  • Review potentially dangerous HTML tags and attributes and evaluate countermeasures.

Overview

Cross-site scripting attacks exploit vulnerabilities in Web page validation by injecting client-side script code. The script code embeds itself in response data, which is sent back to an unsuspecting user. The user’s browser then runs the script code. Because the browser downloads the script code from a trusted site, the browser has no way of recognizing that the code is not legitimate, and Microsoft Internet Explorer security zones provide no defense. Cross-site scripting attacks also work over HTTP and HTTPS (SSL) connections.
One of the most serious examples of a cross-site scripting attack occurs when an attacker writes script to retrieve the authentication cookie that provides access to a trusted site and then posts the cookie to a Web address known to the attacker. This enables the attacker to spoof the legitimate user’s identity and gain illicit access to the Web site.
Common vulnerabilities that make your Web application susceptible to cross-site scripting attacks include:

  • Failing to constrain and validate input.
  • Failing to encode output.
  • Trusting data retrieved from a shared database.

Guidelines

The two most important countermeasures to prevent cross-site scripting attacks are to:

  • Constrain input.
  • Encode output.

Constrain Input

Start by assuming that all input is malicious. Validate input type, length, format, and range.

  • To constrain input supplied through server controls, use ASP.NET validator controls such as RegularExpressionValidator and RangeValidator.
  • To constrain input supplied through client-side HTML input controls or input from other sources such as query strings or cookies, use the System.Text.RegularExpressions.Regex class in your server-side code to check for expected using regular expressions.
  • To validate types such as integers, doubles, dates, and currency amounts, convert the input data to the equivalent .NET Framework data type and handle any resulting conversion errors.

For more information about and examples of how to constrain input, see How To: Protect From Injection Attacks in ASP.NET.

Encode Output

Use the HttpUtility.HtmlEncode method to encode output if it contains input from the user or from other sources such as databases. HtmlEncode replaces characters that have special meaning in HTML-to-HTML variables that represent those characters. For example, < is replaced with < and is replaced with . Encoded data does not cause the browser to execute code. Instead, the data is rendered as harmless HTML.
Similarly, use HttpUtility.UrlEncode to encode output URLs if they are constructed from input.

Summary of Steps

To prevent cross-site scripting, perform the following steps:

  • Step 1. Check that ASP.NET request validation is enabled.
  • Step 2. Review ASP.NET code that generates HTML output.
  • Step 3. Determine whether HTML output includes input parameters.
  • Step 4. Review potentially dangerous HTML tags and attributes.
  • Step 5. Evaluate countermeasures.

Step 1. Check That ASP.NET Request Validation Is Enabled

By default, request validation is enabled in Machine.config. Verify that request validation is currently enabled in your server’s Machine.config file and that your application does not override this setting in its Web.config file. Check that validateRequest is set to true as shown in the following code example.




You can disable request validation on a page-by-page basis. Check that your pages do not disable this feature unless necessary. For example, you may need to disable this feature for a page if it contains a free-format, rich-text entry field designed to accept a range of HTML characters as input. For more information about how to safely handle this type of page, see Step 5. Evaluate Countermeasures.
To test that ASP.NET request validation is enabled

  1. Create an ASP.NET page that disables request validation. To do this, set ValidateRequest=”false”, as shown in the following code example.
    <%@ Page Language="C#" ValidateRequest="false" %>


    void btnSubmit_Click(Object sender, EventArgs e)
    {
    // If ValidateRequest is false, then 'hello' is displayed
    // If ValidateRequest is true, then ASP.NET returns an exception
    Response.Write(txtString.Text);
    }




    Text="<script>
    alert('hello');
    </script>" />

    OnClick="btnSubmit_Click"
    Text="Submit" />



  2. Run the page. It displays Hello in a message box because the script in txtString is passed through and rendered as client-side script in your browser.
  3. Set ValidateRequest=”true” or remove the ValidateRequest page attribute and browse to the page again. Verify that the following error message is displayed.
    A potentially dangerous Request.Form value was detected from the client (txtString="
    alert('hello...").

    This indicates that ASP.NET request validation is active and hasrejected the input because it includes potentially dangerous HTMLcharacters.

    Note   Do not rely on ASP.NET request validation.Treat it as an extra precautionary measure in addition to your owninput validation.

Step 2. Review ASP.NET Code That Generates HTML Output

ASP.NET writes HTML as output in two ways, as shown in the following code examples.

Response.Write
<% =

Search your pages to locate where HTML and URL output is returned to the client.

Step 3. Determine Whether HTML Output Includes Input Parameters

Analyze your design and your page code to determine whether theoutput includes any input parameters. These parameters can come from avariety of sources. The following list includes common input sources:

  • Form fields, such as the following.
    Response.Write(name.Text);
    Response.Write(Request.Form["name"]);
    Query Strings
    Response.Write(Request.QueryString["name"]);

  • Query strings, such as the following:
    Response.Write(Request.QueryString["username"]);

  • Databases and data access methods, such as the following:
    SqlDataReader reader = cmd.ExecuteReader();
    Response.Write(reader.GetString(1));

    Be particularly careful with data read from a database if it is shared by other applications.

  • Cookie collection, such as the following:
    Response.Write(
    Request.Cookies["name"].Values["name"]);

  • Session and application variables, such as the following:
    Response.Write(Session["name"]);
    Response.Write(Application["name"]);

In addition to source code analysis, you can also perform a simple test by typing text such as “XYZ” in form fields and testing the output. If the browser displays “XYZ” or if you see “XYZ” when you view the source of the HTML, your Web application is vulnerable to cross-site scripting.

To see something more dynamic, inject <script>alert(‘hello’);</script>through an input field. This technique might not work in all casesbecause it depends on how the input is used to generate the output.

Step 4. Review Potentially Dangerous HTML Tags and Attributes

If you dynamically create HTML tags and construct tag attributeswith potentially unsafe input, make sure you HTML-encode the tagattributes before writing them out.

The following .aspx page shows how you can write HTML directly to the return page by using the <asp:Literal>control. The code takes user input of a color name, inserts it into theHTML sent back, and displays text in the color entered. The page uses HtmlEncode to ensure the inserted text is safe.
















Color: 

<asp:Button ID="Button1" runat="server" Text="Show color"
OnClick="Button1_Click" />





private void Page_Load(Object Src, EventArgs e)
{
protected void Button1_Click(object sender, EventArgs e)
{
Literal1.Text = @"<span style=""color:"
+ Server.HtmlEncode(TextBox1.Text)
+ @""">Color example";
}
}

Potentially Dangerous HTML Tags

While not an exhaustive list, the following commonly used HTML tags could allow a malicious user to inject script code:

  • <applet>
  • <body>
  • <embed>
  • <frame>
  • <script>
  • <frameset>
  • <html>
  • <iframe>
  • <img>
  • <style>
  • <layer>
  • <link>
  • <ilayer>
  • <meta>
  • <object>

An attacker can use HTML attributes such as src, lowsrc, style, and href in conjunction with the preceding tags to inject cross-site scripting. For example, the src attribute of the <img> tag can be a source of injection, as shown in the following examples.


<img src="java
script:alert('hello');" />
<img src="java
script:alert('hello');" />

An attacker can also use the <style> tag to inject a script by changing the MIME type as shown in the following.


alert('hello');

Step 5. Evaluate Countermeasures

When you find ASP.NET code that generates HTML using some input, you need to evaluate appropriate countermeasures for your specific application. Countermeasures include:

  • Encode HTML output.
  • Encode URL output.
  • Filter user input.

Encode HTML Output

If you write text output to a Web page and you do not know if the text contains HTML special characters (such as <, >, and &), pre-process the text by using the HttpUtility.HtmlEncode method as shown in the following code example. Do this if the text came from user input, a database, or a local file.

Response.Write(HttpUtility.HtmlEncode(Request.Form["name"]));

Do not substitute encoding output for checking that input is well-formed and correct. Use it as an additional security precaution.

Encode URL Output

If you return URL strings that contain input to the client, use the HttpUtility.UrlEncode method to encode these URL strings as shown in the following code example.

Response.Write(HttpUtility.UrlEncode(urlString));

Filter User Input

If you have pages that need to accept a range of HTML elements, for example through some kind of rich text input field, you must disable ASP.NET request validation for the page. If you have several pages that do this, create a filter that allows only the HTML elements that you want to accept. A common practice is to restrict formatting to safe HTML elements such as bold (<b>) and italic (<i>).
To safely allow restricted HTML input

  1. Disable ASP.NET request validation by the adding the ValidateRequest=”false” attribute to the @ Page directive.
  2. Encode the string input with the HtmlEncode method.
  3. Use a StringBuilder and call its Replace method to selectively remove the encoding on the HTML elements that you want to permit.

The following .aspx page code shows this approach. The page disables ASP.NET request validation by setting ValidateRequest=”false”. It HTML-encodes the input and then selectively allows the <b> and <i> HTML elements to support simple text formatting.

<%@ Page Language="C#" ValidateRequest="false"%>


void submitBtn_Click(object sender, EventArgs e)
{
// Encode the string input
StringBuilder sb = new StringBuilder(
HttpUtility.HtmlEncode(htmlInputTxt.Text));
// Selectively allow and
sb.Replace("", "");
sb.Replace("", "
");
sb.Replace("", "");
sb.Replace("
", "");
Response.Write(sb.ToString());
}






TextMode="MultiLine" Width="318px"
Height="168px">


Text="Submit" OnClick="submitBtn_Click" />

Additional Considerations

In addition to the techniques discussed previously in this How To, use the following countermeasures as further safe guards to prevent cross-site scripting:

  • Set the correct character encoding.
  • Do not rely on input sanitization.
  • Use the HttpOnly cookie option.
  • Use the <frame> security attribute.
  • Use the innerText property instead of innerHTML.

Set the Correct Character Encoding

To successfully restrict valid data for your Web pages, you should limit the ways in which the input data can be represented. This prevents malicious users from using canonicalization and multi-byte escape sequences to trick your input validation routines. A multi-byte escape sequence attack is a subtle manipulation that uses the fact that character encodings, such as uniform translation format-8 (UTF-8), use multi-byte sequences to represent non-ASCII characters. Some byte sequences are not legitimate UTF-8, but they may be accepted by some UTF-8 decoders, thus providing an exploitable security hole.
ASP.NET allows you to specify the character set at the page level or at the application level by using the <globalization> element in the Web.config file. The following code examples show both approaches and use the ISO-8859-1 character encoding, which is the default in early versions of HTML and HTTP.
To set the character encoding at the page level, use the <meta> element or the ResponseEncoding page-level attribute as follows:


content="text/html; charset=ISO-8859-1" />

OR
<% @ Page ResponseEncoding="iso-8859-1" %>

To set the character encoding in the Web.config file, use the following configuration.




requestEncoding="iso-8859-1"
responseEncoding="iso-8859-1"/>

Validating Unicode Characters

Use the following code to validate Unicode characters in a page.

using System.Text.RegularExpressions;
. . .

public class WebForm1 : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
// Name must contain between 1 and 40 alphanumeric characters
// and (optionally) special characters such as apostrophes
// for names such as O'Dell

if (!Regex.IsMatch(Request.Form["name"],
@"^[\p{L}\p{Zs}\p{Lu}\p{Ll}\']{1,40}$"))
throw new ArgumentException("Invalid name parameter");

// Use individual regular expressions to validate other parameters
. . .
}
}

The following explains the regular expression shown in the preceding code:

  • ^ means start looking at this position.
  • \p{ ..} matches any character in the named character class specified by {..}.
  • {L} performs a left-to-right match.
  • {Lu} performs a match of uppercase.
  • {Ll} performs a match of lowercase.
  • {Zs} matches separator and space.
  • matches apostrophe.
  • {1,40} specifies the number of characters: no less than 1 and no more than 40.
  • $ means stop looking at this position.

Do Not Rely on Input Sanitization

A common practice is for code to attempt to sanitize input by filtering out known unsafe characters. Do not rely on this approach because malicious users can usually find an alternative means of bypassing your validation. Instead, your code should check for known secure, safe input. Table 1 shows various safe ways to represent some common characters.

Table 1: Character Representation
Characters Decimal Hexadecimal HTML Character Set Unicode
(double quotation marks) &#34 &#x22 \u0022
(single quotation mark) &#39 &#x27 \u0027
& (ampersand) &#38 &#x26 & \u0026
< (less than) &#60 &#x3C < \u003c
> (greater than) &#62 &#x3E > \u003e

Use the HttpOnly Cookie Option

Internet Explorer 6 Service Pack 1 and later supports an HttpOnly cookie attribute, which prevents client-side scripts from accessing a cookie from the document.cookie property. Instead, the script returns an empty string. The cookie is still sent to the server whenever the user browses to a Web site in the current domain.

Note   Web browsers that do not support the HttpOnly cookie attribute either ignore the cookie or ignore the attribute, which means that it is still subject to cross-site scripting attacks.

The System.Net.Cookie class in Microsoft .NET Framework version 2.0 supports an HttpOnly property. The HttpOnly property is always set to true by Forms authentication.
Earlier versions of the .NET Framework (versions 1.0 and 1.1) require that you add code similar to the following to the Application_EndRequest event handler in your application Global.asax file to explicitly set the HttpOnly attribute.

protected void Application_EndRequest(Object sender, EventArgs e) 
{
string authCookie = FormsAuthentication.FormsCookieName;
foreach (string sCookie in Response.Cookies)
{
// Just set the HttpOnly attribute on the Forms
// authentication cookie. Skip this check to set the attribute
// on all cookies in the collection

if (sCookie.Equals(authCookie))
{
// Force HttpOnly to be added to the cookie header
Response.Cookies[sCookie].Path += ";HttpOnly";
}
}
}

Use the Security Attribute

Internet Explorer 6 and later support a new security attribute for the <frame> and <iframe> elements. You can use the security attribute to apply the user’s Restricted Sites Internet Explorer security zone settings to an individual frame or iframe. By default, the Restricted Sites zone does not support script execution.
If you use the security attribute, it must be set to “restricted” as shown in the following.


Use the innerText Property Instead of innerHTML

If you use the innerHTML property to build a page and the HTML is based on potentially untrusted input, you must use HtmlEncode to make it safe. To avoid having to remember to do this, use innerText instead. The innerText property renders content safe and ensures that scripts are not executed.
The following example shows this approach for two HTML <span> controls. The code in the Page_Load method sets the text displayed in the Welcome1 <span> element using the innerText property, so HTML-encoding is unnecessary. The code sets the text in the Welcome2 <span> element by using the innerHtml property; therefore, you must HtmlEncode it first to make it safe.

<%@ Page Language="C#" AutoEventWireup="true"%>









private void Page_Load(Object Src, EventArgs e)
{
// Using InnerText renders the content safe–no need to HtmlEncode
Welcome1.InnerText = "Hello, " + User.Identity.Name;

// Using InnerHtml requires the use of HtmlEncode to make it safe
Welcome2.InnerHtml = "Hello, " +
Server.HtmlEncode(User.Identity.Name);
}

Additional Resources

Source: MSDN
Posted in .NET, asp.net, javascript | Leave a comment

>COM Interop Exposed

>Introduction
Microsoft realized that the very first version of .NET needed a way to work with the existing Windows technology used to develop applications over the past 8+ years: COM. With that in mind, Microsoft added support in the .NET runtime for interoperating with COM – simply called “COM Interop”. The support goes both ways: .NET code can call COM components and COM code can call .NET components. This article is geared towards VB6 programmers who are familiar with developing COM components and familiar with the concept of an interface. I’ll review some background on COM, explain how VB6 interacts with COM, and then show how to design .NET components to smoothly interact with COM. In a future article, I’ll discuss how to use an existing COM component in .NET applications.
For those die-hard COM experts, there will be some things in this article that are oversimplified, but the concepts, as presented, are the important points to know for those developers supplementing their COM code with .NET components.

A Brief History of COM and VB6
One of the key concepts of COM is that everything is called through an interface. There is no such thing as simply creating a COM object and calling a method. You must use an interface. You’re probably thinking “Wait a minute! I’ve coded hundreds of classes in VB6 and never needed an interface”. That’s right – you didn’t need one because VB6 provided it for you in the background. Whenever you defined a public method on a class, VB6 made that method part of a COM interface and made your class implement the interface.
For example, consider the following VB6 class from an ActiveX DLL project. The class is called “Robot”:


Option Strict

Public Sub MoveForward()
...
End Sub

Public Sub FindCar()
...
End Sub

When you compile this into a DLL, VB6 creates an interface called “_Robot” (note the leading underscore) and a “coclass” called “Robot”, which implements the interface “_Robot” (a “coclass” is the actual COM creatable object). The Microsoft utility OLE View is a tool used to examine the types defined in a COM component. OLE View should be installed under “Start, Programs, Microsoft Visual Studio 6.0, Microsoft Visual Studio 6.0 Tools, OLE View”. Using the ActiveX DLL compiled above, I started up OLE View, selected “View TypeLib…” from the “File” menu and selected the DLL. Here are the important parts of the output:


interface _Robot : IDispatch {
...
HRESULT MoveForward();
...
HRESULT FindCar();
};

coclass Robot {
[default] interface _Robot;
};

The first item to point out is that there is an interface called “_Robot”. This is the interface VB6 creates for us. It defines the two methods I added to the class (MoveForward and FindCar). Next, you’ll see a “coclass” called “Robot”. This represents the actual, creatable class. Since everything in COM is called through an interface, the “coclass” lists all interfaces supported by this object. Right now, there is only the “_Robot” interface – and it’s marked with the “default” modifier. There are a lot of COM details about the default interface, but for this article, the importance of a default interface in terms of VB6 components is that of all the interfaces a class may implement, only the default interface supports late binding. And since scripting clients like VBScript only do late binding, the methods on the default interface are the only ones they can see.

Multiple Interfaces
COM will allow you to implement more than one interface. Take the ActiveX DLL from the previous section and add a new class module called “IMaid” (VB6 doesn’t support directly creating a COM interface – more on that below). Here’s the IMaid code:


Option Explicit

Public Sub CleanKitchen()
...
End Sub

Public Sub WashCar()
...
End Sub

Now add “Implements IMaid” to the Robot class:


Option Explicit

Implements IMaid

Public Sub MoveForward()
End Sub

Public Sub FindCar()
End Sub

Private Sub IMaid_CleanKitchen()
End Sub

Private Sub IMaid_WashCar()
End Sub

If I compile this DLL now and examine it with OLE View, I see the following structures (again, only the relevant portions are shown below):


interface _Robot : IDispatch {
...
HRESULT MoveForward();
...
HRESULT FindCar();
};

coclass Robot {
[default] interface _Robot;
interface _IMaid;
};

interface _IMaid : IDispatch {
..
HRESULT CleanKitchen();
..
HRESULT WashCar();
};

coclass IMaid {
[default] interface _IMaid;
};

As noted earlier, VB6 does not support creating a true COM interface. However, since VB6 creates a COM interface with every class (prefixed with the underscore), the VB6 compiler will actually use the auto-generated interface when compiling the code when you use the “Implements” keyword on a class in VB6. So above, the Robot coclass implements the interface _Robot (automatically generated by VB6) and the _IMaid interface (the automatically generated one from the IMaid class). Also note that the _Robot interface created by VB6 is marked as the default interface. If you were going to use this object in a scripting environment (such as an ASP page), you could only access the MoveForward and FindCar methods. The methods implemented by the IMaid interface are not accessible since they are not on the default interface.
Almost to .NET!
If you’ve stuck around this long, the answer is yes, you’re getting close to some .NET code! But it’s important to know these concepts before you move into making .NET components that you expose to COM. Think of it as having a blueprint before starting to build a house. Sure, you can work without a blueprint, but the house will come out much nicer if you start off right. A quick recap of what happens in VB6 when it creates COM objects:

  • COM is interface based. Everything in COM must be called through an interface.
  • VB6 doesn’t require that you implement a specific interface when creating a COM class. Instead, it will create an interface for you. Its name will be defined as your class name prefixed with the underscore (_) character.
  • The interface created by VB6 is always marked as the default COM interface and therefore only those methods are available to scripting clients (in the example above, VBScript can not access the IMaid methods of the Robot object).


Where Are My Methods?!
Many people who first expose a .NET object to COM notice that when they try and use the object in VB6, none of their methods are listed. Create a quick .NET class library that will be exposed to COM to see why that happens: [VB.NET]


Option Strict On
Option Explicit On

Namespace QuickNET
Public Class Bee
Public Sub FindFlowers()

End Sub

Public Sub MakeHoney()

End Sub
End Class
End Namespace

[C#]


using System;

namespace QuickNET
{
public class Bee
{
public void FindFlowers()
{
}

public void MakeHoney()
{
}
}
}

Now create a COM type library from this .NET component to see what it looks like (this doesn’t actually register it for COM – it just creates a COM type library). Go to a Visual Studio .NET Command Prompt (Start, Programs, Microsoft Visual Studio .NET, Visual Studio .NET Tools, Microsoft Visual Studio.NET Command Prompt), change to the directory of the above compiled .NET component and enter the following command:


TLBEXP.EXE QuickNET.dll /out:Com.QuickNET.tlb

The TLBEXP.EXE utility generates a COM type library from the .NET assembly. You can name the type library anything you want, but, by convention, it usually has a .tlb extension. I prefix my exported type libraries with “Com.”. Now load up OLE View and open the type library “Com.QuickNET.tlb”. Below are the relevant parts:


coclass Bee {
[default] interface _Bee;
interface _Object;
};

interface _Bee : IDispatch {
};

This looks very similar to VB6 COM type libraries. You can see that an interface called “_Bee” was created for the “Bee” class and it’s also the default interface. However, there are no methods on the interface. If you were to start up VB6 and add a reference to this tlb to your project, you’d notice by looking at the Object Browser that the Bee class has no methods (VB6 always looks at the “default” interface to see what methods are on the class).

NOTE: The _Object interface isn’t important for our discussion. Since everything inherits from the Object class in .NET and that class exposes a _Object interface, there’s a _Object interface added to all exported types.

So why didn’t TLBEXP.EXE put all of the methods on the _Bee interface? Since the layout of a COM interface is a binding contract, adding new methods to a .NET class and then regenerating the COM type library might change that layout – thus breaking existing COM clients compiled against the old layout. By defining an empty interface, all clients will do late-bound calls and new versions of the .NET component (and its COM wrapper) will work without recompiling the COM clients.

Taking Control
So how do you get those methods on your .NET component to show up in VB6? You can take what you know about VB6 and COM and apply it to .NET. Basically, you need to:

  • Have an interface with your methods defined.
  • Make that interface the default interface.

The first one is easy. Add a .NET interface that includes the methods you want to expose to COM:
[VB.NET]


Public Interface IBee
Sub FindFlower()
Sub MakeHoney()
End Interface

[C#]


public interface IBee
{
void FindFlower();
void MakeHoney();
}

Now you’ll simply implement that interface in your Bee class. [VB.NET]


Public Class Bee
Implements IBee

Public Sub FindFlower() Implements IBee.FindFlower
End Sub

Public Sub MakeHoney() Implements IBee.MakeHoney
End Sub
End Class

[C#]


public class Bee : IBee
{
public void FindFlower()
{
}

public void MakeHoney()
{
}
}

You’ll compile this component, run the TLBEXP.EXE utility and check it out with OLE View. What you see may surprise you:


interface IBee : IDispatch {
...
HRESULT FindFlower();
...
HRESULT MakeHoney();
};

coclass Bee {
[default] interface _Bee;
interface _Object;
interface IBee;
};

interface _Bee : IDispatch {
};

The IBee interface came straight through as a standard COM interface – it even includes the methods. The “Bee” coclass even implements this class (as expected), but there’s still that (empty) _Bee interface that is marked as the default interface. And that’s where VB6 will look for the methods belonging to the class. But the IBee interface is exposed as a standard COM interface so you could do everything through that interface and it would work fine. For example, using the type library created above, this VB6 code is perfectly legal:


Dim bee As IBee
Set bee = New Bee
bee.FindFlower
bee.MakeHoney

To make a cleaner integration, however, the IBee interface needs to be the default interface. That is accomplished through attributes.

Attributes
If you’re not familiar with attributes, here’s a quick summary. Attributes are a “descriptive declaration”. They’re used to “annotate” programming elements such as types, fields, methods, classes, etc… Attributes can have values associated with them and those values, along with the attribute information, are saved with all of the other .NET metadata. They can be used to describe code to the CLR (Common Language Runtime) or to affect application behavior at runtime. To control how TLBEXP.EXE creates the type library, you can use an attribute to prevent it from creating that “default” interface. The “ClassInterfaceAttribute” can be applied to a class with the “ClassInterfaceType.None” enumeration member. It can also be applied at the Assembly level where it would apply to every public class in the Assembly. Using the example above, you can make a small modification to the Bee class and apply the attribute:
[VB.NET]


Option Strict On
Option Explicit On

Imports System.Runtime.InteropServices

Namespace QuickNET
_
Public Class Bee
Implements IBee

Public Sub FindFlower() Implements IBee.FindFlower

End Sub

Public Sub MakeHoney() Implements IBee.MakeHoney

End Sub
End Class
End Namespace

[C#]


using System;
using System.Runtime.InteropServices;

namespace QuickNET
{
[ClassInterface(ClassInterfaceType.None)]
public class Bee : IBee
{
public void FindFlower()
{
}

public void MakeHoney()
{
}
}
}

After compiling this and re-creating the type library, OLE View shows a much cleaner structure:


interface IBee : IDispatch {
...
HRESULT FindFlower();
...
HRESULT FindHoney();
};

coclass Bee {
interface _Object;
[default] interface IBee;
};

Not only do you not have the “_Bee” interface, but your IBee interface is marked as the default interface. Why is that? If the ClassInterfaceAttribute specifies that no automatic interface is to be generated, TLBEXP.EXE will take the first interface implemented by the class and make it the default interface. So if you plan on exposing your .NET class to COM, take into account which interface is the first interface implemented in the source code (either through the VB.NET “Implements” keyword or the first interface listed after the “:” in your C# class definition).

Controlling Your GUIDs
The last thing you need to control is your GUIDs – Globally Unique Identifiers. You’ve probably seen a GUID before. Here’s a sample:


82CC3E6A-148E-4b77-866E-598DBEDC5C74

Every interface in COM and every coclass (creatable class object) is identified by a unique GUID. VB6 controls GUID creation for you. You can “coax” VB6 into using the same GUIDs for classes and interfaces by using the “Binary Compatibility” mode of your VB6 project when recompiling. The .NET TLBEXP.EXE utility will also auto-generate a GUID for every interface and class it exports to COM. But you can use attributes to define the GUID yourself. Why should you care? Whenever you register a .NET object as a COM component, registry entries are created. Some of those registry entries are the GUIDs used to identify your classes and interfaces to COM. If you don’t specify a specific GUID, TLBEXP.EXE will generate a new one every time you re-create your COM type library. COM clients already developed could have references to the old GUID and would no longer work since the GUIDs changed. Likewise, if you do control and define a specific GUID for your classes and interfaces, then the GUIDs aren’t changing and your COM clients won’t need to be recompiled and will continue to work even with new versions of your .NET component.
You can use attributes to define a GUID for your classes and interfaces. Instead of trying to “make up” your own unique GUID, VS .NET (along with previous versions of Visual Studio) comes with a tool for generating a GUID called (interestingly enough) guidgen.exe. This should be found in the “\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools” directory. Double-click on it and you should see a screen similar to the one below:

GUIDs are used in many different places, so guidgen supports creating a GUID in four different formats. For your purposes, you need the fourth format: Registry Format. You don’t need the opening and closing braces, but you can trim those off. Press “New GUID” to generate a new GUID and then “Copy” to copy it to the clipboard.
Now define a GUID for your IBee interface (make sure you’ve added the System.Runtime.InteropServices namespace to your code). Paste the clipboard into the “Guid” attribute and remove the leading and trailing braces:
[VB.NET]


_
Public Interface IBee
Sub FindFlower()
Sub MakeHoney()
End Interface

[C#]


[Guid("0490E147-F2D2-4909-A4B8-3533D2F264D0")]
public interface IBee
{
void FindFlower();
void MakeHoney();
}

Now the class also needs its own GUID. Go back to guidgen, click “New GUID” and then “Copy”. Now apply the Guid attribute to the class with the new GUID value (again, trim the braces): [VB.NET]



Guid("03AD5D2D-2AFD-439f-8713-A4EC0705B4D9")> _
Public Class Bee
Implements IBee

Public Sub FindFlower() Implements IBee.FindFlower

End Sub

Public Sub MakeHoney() Implements IBee.MakeHoney

End Sub
End Class

[C#]


[ClassInterface(ClassInterfaceType.None)]
[Guid("03AD5D2D-2AFD-439f-8713-A4EC0705B4D9")]
public class Bee : IBee
{
public void FindFlower()
{
}

public void MakeHoney()
{
}
}

Now tblexp will always use the same GUID.
Deployment

You’ve been using the TLBEXP.EXE utility throughout this article to generate a COM type library. That’s because, so far, you’ve only been interested in seeing how .NET exposes its structures to COM. To actually make the .NET component look like a COM component, you need to register it just like any other COM component. I’m sure you’re familiar with regsvr32: the utility for registering and unregistering COM components. This utility won’t work for a .NET component. Instead, you’ll need to use the .NET utility “regasm.exe” – short for “Register Assembly”. This utility adds registry entries to make your .NET component “look” like a regular COM component.
The REGASM.EXE utility also has the option to generate a COM type library which can be used by VB6. The “/tlb” option on REGASM performs the same thing that TLBEXP.EXE does. Therefore, you really don’t need to use TLBEXP when creating a .NET object for COM. Just use REGASM with the /tlb option. Here’s an example. Go to the Visual Studio .NET 2003 Command Prompt, change to the directory of your .NET assembly, and enter:


REGASM myassem.dll /tlb:com.myassem.tlb

Your object is now registered as a COM component, and you have a COM type library you can reference from VB6 to early-bind to the component. Now all you need to do is get COM to find the .NET assembly.

Local Deployment or the GAC?
Once your .NET assembly is registered as a COM component, any attempt to create an instance of one of the .NET components from COM will cause a copy of the .NET runtime to be loaded. The .NET runtime will then need to locate the assembly. Even though you’re running in a COM environment, the .NET rules for finding an assembly still apply:

  • Tirst, the Global Assembly Cache (GAC) is checked.
  • Then, the local directory is checked.

The second option is a bit easier but not as flexible. For the first option, simply copy the .NET assembly to the same directory as your COM exe client and the runtime will find it. However, if you’re building/debugging in the VB6 IDE, then the “local directory” is the location of VB6.EXE. In this situation, you need to copy your .NET assembly to different locations depending on whether you’re running inside the VB6 IDE or not. And copying files into the same directory as VB6.EXE isn’t a great idea. If you make any updates to the .NET assembly, you need to make sure you copy it to both locations. For these reasons, placing the assembly in the Global Assembly Cache (GAC) is usually the best option for COM Interop. Before placing an assembly in the GAC, you need to make sure you’ve got a fixed versioning scheme and a strong-name key pair. Getting a fixed versioning scheme is simple: In your AssemblyInfo file, change the value of the AssemblyVersion attribute from the default “1.0.*” to “1.0.0.0”. The version number is a key component of placing an assembly in the GAC. Leaving the “*” makes VS .NET generate a new value every time you build your project. Since other projects that reference your assembly look for a specific version number, having it change every time you build is a problem! Therefore, hard-code a specific value and as you develop new releases of your assembly, increment the version number as appropriate.
Next, you’ll need to generate a strong-name key pair. Use the SN.EXE tool by going to the Visual Studio .NET 2003 Command Prompt, changing to the directory of your .NET project and enter:


sn -k mykey.snk

Now update the AssemblyKeyFile attribute in your AssemblyInfo to point to the “mykey.snk” file. Finally, recompile your .NET component. It is now ready to be added to the GAC. Go to a Visual Studio .NET 2003 Command prompt, change to the directory of your .NET assembly and enter:


gacutil -I myassembly.dll

This installs your assembly into the GAC. Now, the runtime can locate the assembly no matter which COM client instantiates your .NET component. 
 
Summary of Best Practices
This article has covered a lot of ground. Here’s a review of the best practices for hassle-free COM Interop:

  1. Define a .NET Interface for the methods you want to expose to COM.
  2. Assign a GUID to that interface with the “Guid” attribute.
  3. Have your class implement your interface as the first interface.
  4. Assign a GUID to that class with the “Guid” attribute.
  5. Add the “ClassInterface(ClassInterfaceType.None)” attribute to prevent regasm/tlbexp from creating an empty default interface.
  6. Hard-code a specific version number in your AssemblyVersion attribute.
  7. Create a strong-name key pair for your assembly and point to it via the AssemblyKeyFile attribute.
  8. Add your assembly to the GAC,
  9. Register your assembly for COM by using the REGASM command along with the “/tlb” option to generate a COM type library.

VB6 projects can add a reference to the generated type library to receive the benefits of early binding. Scripting clients like VBScript can also access the object, but they’ll only be able to access the methods on the default interface. When it comes time to enhance your .NET component, don’t touch your existing interface. If you need to add more methods, create a new interface (with a Guid) and implement that interface. Changing the existing interface could break clients already compiled against that interface.

Posted in .NET, components | Leave a comment

Using the Gnu Privacy Guard (GnuPG/PGP) within ASP.NET [v1.0]

>

 
Environment: .NET, ASP.NET, C#
Keywords: GnuPG, PGP, Cryptography, Thread, Process, Command Line Program

GnuPG Wrapper

This article presents GnuPGWrapper v1.0, a wrapper class for GnuPG.
GnuPG stands for GNU Privacy Guard and is GNU’s tool for secure communication and data storage. It can be used to encrypt data and to create digital signatures. It includes an advanced key management facility and is compliant with the proposed OpenPGP Internet standard as described in RFC 2440. As such, GnuPG is a complete and free replacement for PGP (Pretty Good Privacy).
This article provides a C# wrapper class (GnuPGWrapper) that will enable the use of an OpenPGP Internet encryption standard within a .NET world. It is shipped with a demo ASP.NET Web Form (GnuPG.aspx), which calls the wrapper class.

Installation

Prerequisites

  • Complete ASP .NET Environment—Windows XP Professional + IIS 5.0 + .NET Framework SDK
  • GnuPG for Windows (more about GnuPG)

Procedure

  • Download the zip file (GnuPGDotNet_src.zip)
  • Extract the zip file (for example, into directory “C:\Inetpub\wwwroot\”)
  • Using Administrative Tools/Internet Information Services, create an IIS Application for directory GnuPGDotNet
  • Call demo Web Form via URL http://localhost/GnuPGDotNet/GnuPG.aspx

Implementation

GnuPG ships as a command line program (gpg.exe) acting as a filter (reads from standard input and writes into standard output). Although suitable for scripting on UNIX systems (where calling a command line program from “sh” or “bash” is easy), it’s pretty hard to integrate this in a production .NET environment.
The GnuPG Wrapper executes the command line program (gpg.exe) in a different process, redirects standard input (stdin), standard output (stdout), and standard error (stderr) streams, and monitors the streams to fetch the results of the encryption/signing operation.
The GnuPG Wrapper:

  • Doesn’t use any temporary files to store results; it directly uses streams/pipes.
  • Uses multiple threads to read data from standard input and standard error, preventing any deadlocks.
  • Uses configurable timeouts to prevent blocking calling applications in case of a system/program/process crash.
  • Uses a configurable passphrase, which can be stored in a local configuration file (Web.Config) to prevent disclosure of the phrase.

Please note that you must have INSTALLED GnuPG AND generated/imported the appropriate keys before using this class. Refer to the GnuPG manual to do this….

Sample Code

To use the wrapper class, you need to proceed as follows:

  1. Create an instance of the class
  2. Set the “command” property to the requested command (SignAndEncrypt, Encrypt, Decrypt, Sign, Verify)
  3. Optionally, set parameters for the command (home directory, originator, recipients, and so forth)
  4. Call the “ExecuteCommand” method with input/output strings variables

The next sections show sample source code for the most command operations (SignAndEncrypt, Decrypt, Verify).

Encrypt and Sign

// Reference My GnuPG wrapping class
using Emmanuel.Cryptography.GnuPG;

// Create GnuPG wrapping class
GnuPGWrapper gpg = new GnuPGWrapper();

// Set command
gpg.command = Commands.SignAndEncrypt;

// Set some parameters from on Web.Config file
gpg.homedirectory = Server.MapPath(ConfigurationSettings.
AppSettings["homedirectory"]);
gpg.passphrase = ConfigurationSettings.AppSettings
["passphrase"];

// Set other parameters from Web Controls
gpg.originator = FromTextBox.Text;
gpg.recipient = ToTextBox.Text;

// Declare input/output variables (input is also read from a
// Web control)

string inputText = MessageTextBox.Text;
string outputText = "";

// Execute GnuPG
gpg.ExecuteCommand(inputText, out outputText);

// Display output text
OutputTextBox.Text = outputText;
OutputTextBox.Visible = true;
ErrorMessage.Visible = false;
ExitCodeLabel.Text = gpg.exitcode.ToString();

Decrypt

using Emmanuel.Cryptography.GnuPG;

GnuPGWrapper gpg = new GnuPGWrapper();

gpg.homedirectory = "C:\Inetpub\wwwroot\GnuPGDotNet\GnuPG"
gpg.passphrase = "My passphrase is so cool I can't remember it"
gpg.command = Commands.Decrypt;

// Execute GnuPG
string outputText = "";
gpg.ExecuteCommand("This is a test message.", out outputText);

// Display output text
[...]

Verify

using Emmanuel.Cryptography.GnuPG;

GnuPGWrapper gpg = new GnuPGWrapper();

gpg.homedirectory = "C:\Inetpub\wwwroot\GnuPGDotNet\GnuPG"
gpg.passphrase = "My passphrase is so cool I can't remember it"
gpg.originator = "me@mycompany.com";
gpg.command = Commands.Verify;

// Execute GnuPG
string outputText = "";
gpg.ExecuteCommand("This is a test message.", out outputText);

// Display output text
[...]

Error Handling

Error handling is done via a specific Exception class; method “ExecuteCommand” raises this exception whenever an error occurs. Your calling application can handle this exception as follows:

using Emmanuel.Cryptography.GnuPG;
try
{

GnuPGWrapper gpg = new GnuPGWrapper();

gpg.homedirectory = "C:\Inetpub\wwwroot\GnuPGDotNet\GnuPG"
gpg.passphrase = "My passphrase is so cool I can't remember
it"
gpg.originator = "me@mycompany.com";
gpg.recipient = "you@yourcompany.com";
gpg.command = Commands.SignAndEncrypt;

// Execute GnuPG
string outputText = "";
gpg.ExecuteCommand("This is a test message.", out outputText);

// Display output text
[...]

}
catch (GnuPGException gpge)
{
// Display error message
ErrorMessage.Text = gpge.Message; // Contains a clear text
// error message, either
// from the wrapper or
// from gpg.exe itself

}

Real-Life Deployment

This code is deployed in a real-life e-commerce Web site that uses GnuPG to communicate with some of its partners (http://www.gourmeo.com).

About GnuPG and PGP

This class has been developed and tested with GnuPG v1.2.0 (MingW32).
You can check the command line manual page for gpg.exe
For more about GNU, please refer to http://www.gnu.org
For more about GnuPG, please refer to http://www.gnupg.org
For more about OpenPGP (RFC 2440), please refer to http://www.gnupg.org/rfc2440.html
For more about PGP, please refer to http://www.pgpi.org

Downloads

Download source and demo – 535 Kb

Source: Emmanuel KARTMANN

Posted in .NET | Leave a comment

>Khi vợ biết làm bánh

>
Khi vợ biết làm bánh…

Vợ biết làm bánh, nghe quá thấy rất hâm mộ. Sáng ăn sáng bằng bánh mỳ nóng hổi vợ làm, tối ăn cơm xong làm mấy cái bánh quy vợ nướng, trước khi đi ngủ làm cái bánh nhân mặn vợ làm cho chắc dạ, sinh nhật con thì tắt đèn thổi nến trên chiếc bánh ga tô made in Vợ bakery. Chưa hết, mỗi lần làm bánh xong vợ còn chụp ảnh post công thức trên blog để làm hàng với vợ các cậu bạn khác.

Vợ biết làm bánh thật là hạnh phúc, thật là hạnh phúc, không thể hạnh phúc và tự hào hơn. Thật. Thật như mình đã từng nghĩ thế sau khi đọc blog vợ mấy thằng khác biết làm bánh.

Và thế là mình gật đầu cái rụp khi vợ ỏn ẻn bảo: “Anh ơi cho em mua cái lò nướng” (nên hiểu là mua cho em cái lò nướng), rồi lại gật đầu tiếp khi vợ tham gia vào cái câu lạc bộ hay hội làm bánh khỉ gió gì đó trên mạng, chắc mẩm quả này yên thân để chơi sudoku rồi.

Vợ biết làm bánh, nghĩa là phải hiểu rằng, không phải cứ trộn bột vào nướng là ra cái bánh, mà nó có thể là một cái gì đó gần như thế, hoặc không phải như thế, không thể ăn mà chỉ để cho vào thùng rác. “Bao nhiêu người đã vứt hàng kg bột vào thùng rác ý chứ, như em là ít đấy”. Vâng, ít, vậy thì thế nào mới gọi là nhiều?

Vợ biết làm bánh, nghĩa là chuyện chăm sóc con cái (và bố con cái) chuyển giao sang cho osin và chồng. Thay vì ngồi bắn dynomite, chơi sudoku, chơi đế quốc, thì mình lại phải ru con ngủ, thay bỉm, pha sữa, để dành thời gian cho vợ lên mạng giao lưu học hỏi tìm công thức, xem video, đọc blog… hay thậm chí chỉ để nghĩ xem mai làm bánh gì…

Vợ biết làm bánh, nghĩa là mình cũng phải tập trộn bột, đánh trứng và nặng nhất là đập bột. Còn nếu mà kêu đập bột mỏi tay thì vợ có ngay ý tưởng “Mua cái kichen aids ý anh ạ, đỡ phải đập bột”, “Bao nhiêu hả em?” “Tám triệu”. Thôi, thế bằng cả tháng lương rồi, xài tạm cái kitchen aids chạy cơm có bằng master này cho đỡ tiền điện em ạ, ngoài các chức năng trộn, đập bột, nó còn có thể hát mọi bài theo yêu cầu, chưa kể nó còn biết đèo vợ đi mua bột.

Vợ biết làm bánh, nghĩa là khả năng văn học và khả năng diễn xuất của mình cũng phải nâng cao vì thường xuyên phải đưa ra các nhận xét và đánh giá sao cho khách quan (theo hướng khen) và tự nhiên nhất. Đồng thời cũng phải làm sao cho các câu bình luận dở hơi trở nên đáng yêu hơn bao giờ hết, kiểu như “Cái này trông giống bánh mỳ phết” (bánh mỳ không giống bánh mỳ thì giống bánh gì hả trời) hay “ăn cũng giống bánh quy đấy chứ” (không lẽ giống bánh chưng?). Đôi khi còn phải tìm ra những điểm giống cái bánh nhất của một sản phẩm vốn không phải cái bánh để động viên vợ.

Vợ biết làm bánh là mình phải hiểu chức năng chính của cái bánh làm ra là để chụp ảnh và đưa lên blog chứ ko phải để ăn. Mẻ bánh nóng giòn vừa ra lò mà sờ tay vào là ăn đòn ngay, khôn hồn thì biết đường mang máy ảnh xuống cho vợ chụp, còn thì tìm cái nào đui què mẻ sứt mà chén

Vợ biết làm bánh thì mình cũng phải ghi nhớ tên các vợ của người khác, ví như chị Khai Tâm, chị Cúc Bebibo, hay mẹ Cu Kít, chị Thủy luongtam… đồng thời phải nhớ luôn ai làm bánh gì giỏi, hay thậm chí con ai xinh hơn để còn nói chuyện với vợ.

Vợ biết làm bánh, đến chiều chủ nhật thay vì đi xem V-Leagues, thì phải ở nhà trông con cho vợ đi offline hội bánh, làm mình phải lừa mãi cho ông bà trông mới trốn đi được, trong khi mình xin đi off hội đế quốc thì bảo chơi chưa đủ hay sao mà còn phải offline, thế làm bánh chưa đủ hay sao còn phải offline?

Vợ biết làm bánh, mình chợt nhận ra, mình thật giàu trí tưởng tượng và tưởng bở.
Loáng thoáng hôm qua nghe vợ dọa còn sắp mua máy làm kem, không biết bang hội làm kem có hay offline không nữa, hoảng quá…

Nguồn: Internet
Posted in relax | Leave a comment

>ActiveSync encountered a problem on the desktop error code 0x86000107

>
This error happens on Windows Mobile 6.1 and when syncing with more than one computer.

You have to try one of solutions below:

1. Delete the 2nd partnership from your phone
Launch Active Sync on your phone while you’re not connected to your PC, open the options and delete the second partnership if you have one.

2. Disable Advanced Networking
Start / Settings / Connections / USB to PC and unselect “Enable advanced network functionality”. (This way not work for me)

3. Change Sync Settings from your desktop
Try unselecting Tasks, e-mail, etc and see if one of them is causing the problem. Note – if you unselect Contacts, e-mail, or Calendar it will remove all information of that type so uncheck the least important ones first. (This one works for me. However, it does not solve 100%, the problem will happen again on next sync)

4. Check Outlook on your desktop
Fully close Outlook and then open the Task Manager. See if there are any rogue instances of Outlook.exe running – if so – remove them.

5. Repair your PST file(s)
This is built into Outlook 2003 – for Outlook 2007 you’ll need to run SCANPST.EXE which should be located in C:\Program Files\Microsoft Office\Office12. You’ll likely have to manually select your PST file. Reboot and resync.

If none of these work we’re getting into more drastic steps

6. Re-install Windows Mobile Device Center or ActiveSync
Find the latest version and re-install

7. Delete your Partnership
From both your device and from your sync software – delete the partnership. This likely means you’ll lose any changes you’ve made from your device.

8. Create a new PST file in Outlook
Requires some working knowledge of outlook. Create a new PST file, set it as default and then try importing all of the data from your previous PST file. This should have the same effect as running SCANPST.EXE but some reported this worked. Reboot and re-sync.

9. Re-install Outlook
Shouldn’t be necessary if you’ve followed the above steps but now we’re trying to remove all possible culprits.

10. Hard Reset your phone
When all else fails – start over. Not a pleasant option. Check your manual for instructions on how to hard reset your phone. And please note, a hard reset will remove all installed data and applications – your phone with be returned to an “out of the box” state.

Source: Internet + Adrian’s blog

Posted in ActiveSync, Windows Mobile | Leave a comment

>Làm sao nghe được tiếng Anh

>

Một trong những trở ngại lớn nhất của chúng ta khi học một ngoại ngữ ấy là chúng ta quá… thông minh và có quá nhiều kinh nghiệm.

Quá thông minh: vì mình không thể nào chấp nhận nghe một câu mà mình không hiểu: cần phải hiểu một câu nói gì trước khi nghe tiếp câu thứ hai, nếu không thì mình không buồn nghe tiếp.

Quá kinh nghiệm: Cuộc đời đã dạy ta không nghe những gì người khác nói mà chỉ hiểu những gì mà nội dung chuyển tải. Nếu không hiểu nội dung, chúng ta không thể lặp lại lời người kia. Cũng vì thế mà – trong giai đoạn đầu học ngoại ngữ – mỗi lần nghe một câu tiếng Anh thì trong đầu phải dịch ra được tiếng Việt thì mới yên tâm, bằng không thì … câu ấy không có nghĩa.

Thế nhưng, đấy là lối học sinh ngữ ngược chiều. Tôi biết được 6 ngôn ngữ, trong đó có ba ngôn ngữ thành thạo nghe nói đọc viết: Việt – Anh – Pháp, và tôi thấy rằng trong các ngôn ngữ tôi biết thì, một cách khách quan, nghe và nói tiếng Việt là khó nhất (vì ở phương tây, không có ngôn ngữ nào mà mình đổi cao độ của một từ thì ý nghĩa từ ấy lại thay đổi: ma – má – mà – mạ – mã – mả). Nhưng các bạn ở forum này, cũng như tôi, đều không có vấn đề gì cả với cái sinh ngữ khó vào bậc nhất ấy!

Tuy nhiên, những thầy cô dạy chúng ta nghe nói tiếng Việt chẳng phải là những vị chuyên viên ngôn ngữ như các thầy cô ngoại ngữ mà ta học tại các trường. Thầy dạy tiếng Việt chúng ta là tất cả những người quanh ta từ ngày ta ra đời: cha mẹ, anh chị, hàng xóm, bạn bè… nghĩa là đại đa số những người chưa có một giờ sư phạm nào cả, thậm chí không có một khái niệm nào về văn phạm tiếng Việt. Thế mà ta nghe tiếng Việt thoải mái và nói như sáo. Còn tiếng Anh thì không thể như thế được. Ấy là vì đối với tiếng Việt, chúng ta học theo tiến trình tự nhiên, còn ngoại ngữ thì ta học theo tiến trình phản tự nhiên.

Từ lúc sinh ra chúng ta đã NGHE mọi người nói tiếng Việt chung quanh (mà chẳng bao giờ ta phản đối: “tôi chẳng hiểu gì cả, đừng nói nữa”! Mới sinh thì biết gì mà hiểu và phản đối!). Sau một thời gian dài từ 9 tháng đến 1 năm, ta mới NÓI những tiếng nói đầu tiên (từng chữ một), mà không hiểu mình nói gì. Vài năm sau vào lớp mẫu giáo mới học ĐỌC, rồi vào lớp 1 (sáu năm sau khi bắt đầu nghe) mới tập VIẾT… Lúc bấy giờ, dù chưa biết viết thì mình đã nghe đưọc tất cả những gì người lớn nói rồi (kể cả điều mình chưa hiểu). Như vậy, tiến trình học tiếng Việt của chúng ta là Nghe – Nói – Đọc – Viết. Giai đoạn dài nhất là nghe và nói, rồi sau đó từ vựng tự thêm vào mà ta không bao giờ bỏ thời gian học từ ngữ. Và ngữ pháp (hay văn phạm) thì đến cấp 2 mới học qua loa, mà khi xong trung học thì ta đã quên hết 90% rồi.

Nhưng tiến trình ta học tiếng Anh (hay bất cứ ngoại ngữ nào) thì hoàn toàn ngược lại.

Thử nhìn lại xem: Trước tiên là viết một số chữ và chua thêm nghĩa tiếng Việt nếu cần. Và kể từ đó, học càng nhiều từ vựng càng tốt, kế đến là học văn phạm, rồi lấy từ vựng ráp vào cho đúng với văn phạm mà VIẾT thành câu! Rồi loay hoay sửa cho đúng luật! Sau đó thì tập ĐỌC các chữ ấy trúng được chừng nào hay chừng ấy, và nhiều khi lại đọc một âm tiếng Anh bằng một âm tiếng Việt! (ví dụ fire, fight, five, file… đều được đọc là ‘phai’ ). Sau đó mới tới giai đoạn NÓI, mà ‘nói’ đây có nghĩa là Đọc Lớn Tiếng những câu mình viết trong đầu mình, mà không thắc mắc người đối thoại có hiểu ‘message’ của mình hay không vì mình chỉ lo là nói có sai văn phạm hay không. Lúc bấy giờ mới khám phá rằng những câu mình viết thì ai cũng hiểu, như khi mình nói thì chỉ có mình và … Thượng Đế hiểu thôi, còn người bản xứ (tiếng Anh) thì ‘huh – huh’ dài cổ như cổ cò! Thế là học nói bằng cách sửa đổi phát âm những từ nào chưa chuẩn cho đến khi người khác có thể hiểu được.

Sau thời gian dài thật dài, mình khám phá rằng mình từng biết tiếng Anh, và nói ra thì người khác hiểu tàm tạm, nhưng khi họ nói thì mình không nghe được gì cả (nghĩa là nghe không hiểu gì cả). Lúc bấy giờ mới tập NGHE, và rồi đành bỏ cuộc vì cố gắng mấy cũng không hiểu được những gì người ta nói.

Vấn đề là ở đó: chúng ta đã học tiếng Anh ngược với tiến trình tự nhiên, vì quá thông minh và có quá nhiều kinh nghiệm. Tiến trình ấy là Viết – Đọc – Nói – Nghe!

Vì thế, muốn nghe và nói tiếng Anh, chuyện đầu tiên là phải quên đi kinh nghiệm và trí thông minh, để trở lại trạng thái ‘sơ sinh và con nít’, và đừng sử dụng quá nhiều chất xám để phân tích, lý luận, dịch thuật!

A. Nghe thụ động:

1. – ‘Tắm’ ngôn ngữ. Nghe không cần hiểu: Hãy nghe! Đừng hiểu.
Bạn chép vào CD một số bài tiếng Anh . Mỗi bài có thể dài từ 1 đến 5 phút.

Khi nào bạn ở nhà một mình, thì mở các bài đó ra vừa đủ nghe, và cứ lặp đi lặp lại mãi ra rả như âm thanh nền suốt ngày. Bạn không cần để ý đến nó. Bạn cứ làm việc của mình, đánh răng, rửa mặt, học bài làm bài, vào internet… với tiếng lải nhải của bài tiếng Anh. (thậm chí, trong lúc bạn ngủ cũng có thể để cho nó nói).

Trường hợp bạn có CD player, USB player hay iPod, thì đem theo để mở nghe khi mình có thời gian chết – ví dụ: di chuyển lâu giờ trên xe, đợi ai hay đợi đến phiên mình tại phòng mạch.

Công việc ‘tắm ngôn ngữ’ này rất quan trọng, vì cho ta nghe đúng với từng âm của một ngôn ngữ lạ. Tai của chúng ta bắt rất nhanh một âm quen, nhưng loại trừ những âm lạ. Ví dụ: Nếu bạn nghe câu: ‘mặt trời mọc cánh khi chim voi truy cập chén chó’, một câu hoàn toàn vô nghĩa, nhưng bảo bạn lặp lại thì bạn lặp lại được ngay, vì bạn đã quá quen với các âm ấy. Nhưng khi một người nói một câu bằng chừng ấy âm (nghĩa là 11 âm/vần), trong ngôn ngữ bạn chưa từng học, và bảo bạn lặp lại thì bạn không thể nào lặp lại được, và bảo rằng… không nghe được! (Bạn có điếc đâu! Vấn đề là tai bạn không nhận ra được các âm!) Lối ‘tắm ngôn ngữ’ đó chỉ là vấn đề làm quen đôi tai, và sau một thời gian (lâu đấy chứ không phải vài ngày) bạn sẽ bắt được các âm của tiếng Anh, và thấy rằng âm ấy rất dễ nghe, nhưng hoàn toàn khác với âm Việt. Đừng nản lòng vì lâu ngày mình vẫn không phân biệt âm: hãy nhớ rằng bạn đã tắm ngôn ngữ tiếng Việt ít ra là 9 tháng liên tục ngày đêm trước khi mở miệng nói được tiếng nói đầu tiên và hiểu được một hai tiếng ngắn của cha mẹ; và sau đó lại tiếp tục ‘tắm ngôn ngữ’ Việt cho đến 4, 5 năm nữa!

2 – Nghe với hình ảnh động.
Nếu có giờ thì xem một số tin tức bằng tiếng Anh (một điều khuyên tránh: đừng xem chương trình tiếng Anh của các đài Việt Nam, ít ra là giai đoạn đầu, vì xướng ngôn viên Việt Nam, phần lớn, nói rất gần với âm Việt Nam (kể cả pronunciation), nên mình dễ quen nghe, và từ đó lỗ tai mình lại hỏng, về sau lại khó nghe người bản xứ nói tiếng Anh – thế là phải học lại lần thứ hai!). Các hình ảnh đính kèm làm cho ta ‘hiểu’ được ít nhiều nội dung bản tin, mà không cần phải ‘dịch’ từng câu của những gì xướng ngôn viên nói. Bạn sẽ yên tâm hơn, sau khi nghe 15 phút tin tức, tự tóm lược lại, thì thấy rằng mình đã nắm bắt được phần chính yếu của nội dung bản tin. Và đây là cách thứ hai để tắm ngôn ngữ.

B. Nghe chủ động:

1. Bản tin special english:- Thu một bản tin, và nghe lại rồi chép ra nhiều chừng nào hay chừng nấy… nhớ là đừng tra cứu tự điển hay tìm hiểu nghĩa vội. Đoán nghĩa trong nội dung câu, và nhớ lại âm thanh của từ, hay cụm từ đó, sau này tự nó sẽ rõ nghĩa, nếu trở đi trở lại hoài.

(Ngày xưa, trên đài VOA, sau mỗi chương trình tôi thường nghe một cụm từ tương tự như: statue, statute hay statu gì đó, mà không biết viết thế nào, tuy vẫn hiểu đại loại là: hãy đợi đấy để nghe tiếp. Mãi sau này tôi mới biết rằng thuật ngữ rất quen thuộc ấy là ‘stay tuned’, nhưng một thời gian dài, chính tả của chữ ấy đối với tôi không thành vấn đề!)

2. Chăm chú nghe lại một số bài mình từng nghe trong giai đoạn ‘tắm ngôn ngữ’- Lấy lại script của những bài mình từng nghe, đọc lại và nhớ lại trong tưởng tượng lời đọc mà mình từng nghe nhiều lần.

Sau đó xếp bản script và nghe lại để hiểu. Lần này: tự nhiên mình sẽ nghe rõ từng tiếng và hiểu. Trường hợp không hiểu một từ hay cụm từ, thì gắng lặp lại nhiều lần đúng như mình đã nghe, sau đó lật lại script để so sánh.

3. Một số bài Audio trong Forum này: nghe nhiều lần, trước khi đọc script. Sau đó, đọc lại script, chủ yếu kiểm tra những từ mình đã nghe hoặc đoán, hoặc những từ mà mình có thể phát âm lại nhưng không hiểu viết và nghĩa thế nào. Qua việc này, nhiều khi ta phát hiện rằng một từ mình rất quen thuộc mà từ xưa đến nay mình cứ in trí là phải nói một cách nào đó, thì thực ra cần phải nói khác hẳn và phát âm như thế thì mới mong nghe đúng và nói cho người khác hiểu. Sau đó, xếp bản script và nghe lại một hai lần nữa. (Ví dụ: hai chữ tomb, bury, khi xưa tôi cứ đinh ninh là sẽ phát âm là ‘tôm-b(ơ), bơri’ – sau này nghe chữ ‘tum, beri’ tôi chẳng hiểu gì cả – dù cho tôi nghe rõ ràng là tum, beri -cho đến khi xem script thì mới vỡ lẽ!)

4. Học hát tiếng Anh, và hát theo trong khi nghe.
Chọn một số bài hát mà mình thích, tìm lyrics của nó rồi vừa nghe vừa nhìn lyrics. Sau đó học thuộc lòng và hát song song với ca sĩ, và gắng phát âm cũng như giữ tốc độ và trường độ cho đúng. Khi nào buồn buồn cũng có thể tự hát cho mình nghe (nếu không có giọng tốt và hát sai giọng một tí cũng không sao, vì chủ yếu là tập phát âm, tốc độ, trường độ và âm điệu tiếng Anh).

Và nói cho đúng giọng (qua hát) cũng là một cách giúp mình sau này nhạy tai hơn khi nghe, vì thường thường ngôn ngữ trong các bài hát khó nghe hơn những câu nói bình thường rất nhiều.

C. Nghe bằng tai:

Khi tôi bảo rằng chúng ta gặp trở ngại khi học ngoại ngữ vì thông minh và có nhiều kinh nghiệm, có người cho rằng đó là nói theo nghĩa bóng. Không phải đâu, tôi nói theo nghĩa đen đó! Qua sự kiện sau (và ACE chắc chắn cũng từng gặp những trường hợp tương tự) ACE sẽ thấy ngay. Một người bạn từng dạy Anh Văn ở Trung Tâm Ngoại Ngữ với tôi, sau này sang định cư ở Mỹ. Anh cùng đi với đứa con 7 tuổi, chưa biết một chữ tiếng Anh nào. 11 năm sau tôi gặp lại hai cha con tại Hoa Kỳ. Con anh nói và nghe tiếng Anh không khác một người Mỹ chính cống. Trong khi đó anh nói tiếng Anh tuy lưu loát hơn xưa, nhưng rõ ràng là một người nước ngoài nói tiếng Mỹ. Khi xem chương trình hài trên TV, con anh cười đúng với tiếng cười nền trong chương trình, trong khi đó anh và tôi nhiều khi không hiểu họ nói gì đáng cười: rõ ràng là kỹ năng nghe của con anh hơn anh rồi! Điều này chứng tỏ rằng khi sang Mỹ, anh đã có kinh nghiệm về tiếng Anh, và ‘khôn’ hơn con anh vì biết nhiều kỹ thuật, phương pháp học tiếng Anh, nên tiếp tục học tiếng Anh theo tiến trình phản tự nhiên; trong khi con anh, vì không ‘thông minh’ bằng anh, và thiếu kinh nghiệm, nên đã học tiếng Anh theo tiến trình tự nhiên mà không theo một phương pháp cụ thế nào để học vocabulary, grammar, listening, speaking cả.

– Xóa bỏ kinh nghiệm nghe nguyên âm: Tiếng Anh là tiếng phụ âm.
Tiếng Anh chủ yếu là ngôn ngữ đa âm: một từ thường có nhiều âm. Lỗ tai chúng ta đã ‘bị điều kiện hóa’ để nghe âm tiếng Việt. Tiếng Việt là loại tiếng đơn âm, vì thế, mỗi tiếng là một âm và âm chủ yếu trong một từ là nguyên âm. Đổi một nguyên âm thì không còn là từ đó nữa: ‘ma, mi, mơ’ không thể hoán chuyển nguyên âm cho nhau, vì ba từ có ba nghĩa hoàn toàn khác nhau. Mặc khác, tiếng Việt không bao giờ có phụ âm cuối từ. Ngay cả những chữ mà khi viết có phụ âm cuối, thì người việt cũng không đọc phụ âm cuối; ví dụ: trong từ ‘hát’, nguyên âm mới là ‘át’, h(ờ)-át, chứ không phải là h(ờ)-á-t(ơ), trong khi đó từ ‘hat’ tiếng Anh được đọc là h(ờ)-a-t(ờ), với phụ âm ‘t’ rõ ràng.
Trong tiếng Việt hầu như không có những từ với hai phụ âm đi kế tiếp (ngoài trừ ch và tr – nhưng thực ra, ch và tr cũng có thể thay bằng 1 phụ âm duy nhất) vì thế, tai của một người Việt Nam – chưa bao giờ làm quen với ngoại ngữ – không thể nhận ra hai phụ âm kế tiếp. Do đó, muốn cho người Việt nghe được một tiếng nước ngoài có nhiều phụ âm kế tiếp, thì phải thêm nguyên âm (ơ) vào giữa các phụ âm; ví dụ: Ai-xơ-len; Mat-xơ-cơ-va.

Với kinh nghiệm đó, một khi ta nghe tiếng Anh, ta chờ đợi nghe cho đủ các nguyên âm như mình NHÌN thấy trong ký âm (phonetic signs), và không bao giờ nghe được cả. Ví dụ: khi học từ America ta thấy rõ ràng trong ký âm: (xin lỗi vì không thể ghi phonetic signs vào trang này) ‘ơ-me-ri-kơ’, nhưng không bao giờ nghe đủ bốn âm cả, thế là ta cho rằng họ ‘nuốt chữ’. Trong thực tế, họ đọc đủ cả, nhưng trong một từ đa âm (trong khi viết) thì chỉ đọc đúng nguyên âm ở dấu nhấn (stress) – nếu một từ có quá nhiều âm thì thêm một âm có dấu nhấn phụ (mà cũng có thể bỏ qua) – và những âm khác thì phải đọc hết các PHỤ ÂM, còn nguyên âm thì sao cũng đưọc (mục đích là làm rõ phụ âm). Có thể chúng ta chỉ nghe: _me-r-k, hay cao lắm là _me-rơ-k, và như thế là đủ, vì âm ‘me’ và tất cả các phụ âm đều hiện diện. Bạn sẽ thắc mắc, nghe vậy thì làm sao hiểu? Thế trong tiếng Việt khi nghe ‘Mỹ’ (hết) không có gì trước và sau cả, thì bạn hiểu ngay, tại sao cần phải đủ bốn âm là ơ-mê-ri-kơ bạn mới hiểu đó là ‘Mỹ’? Tóm lại: hãy nghe phụ âm, đừng chú ý đến nguyên âm, trừ âm có stress!

Một ví dụ khác: từ interesting! Tôi từng được hỏi, từ này phải đọc là in-tơ-res-ting hay in-tơ-ris-ting mới đúng? Chẳng cái nào đúng, chẳng cái nào sai cả. Nhưng lối đặt vấn đề sai! Từ này chủ yếu là nói ‘in’ cho thật rõ (stress) rồi sau đó đọc cho đủ các phụ âm là người ta hiểu, vì người bản xứ chỉ nghe các phụ âm chứ không nghe các nguyên âm kia; nghĩa là họ nghe: in-trstng; và để rõ các phụ âm kế tiếp thì họ có thể nói in-tr(i)st(i)ng; in-tr(ơ)st(ơ)ng; in-tr(e)st(ư)ng. Mà các âm (i) (ơ), để làm rõ các phụ âm, thì rất nhỏ và nhanh đến độ không rõ là âm gì nữa. Trái lại, nếu đọc to và rõ in-tris-ting, thì người ta lại không hiểu vì dấu nhấn lại sang ‘tris’!

Từ đó, khi ta phát âm tiếng Anh (nói và nghe là hai phần gắn liền nhau – khi nói ta phát âm sai, thì khi nghe ta sẽ nghe sai!) thì điều tối quan trọng là phụ âm, nhất là phụ âm cuối. Lấy lại ví dụ trước: các từ fire, fight, five, file phải được đọc lần lượt là fai-(ơ)r; fai-t(ơ); fai-v(ơ), và fai-(ơ)l, thì người ta mới hiểu, còn đọc ‘fai’ thôi thì không ai hiểu cả.

Với từ ‘girl’ chẳng hạn, thà rằng bạn đọc gơ-rôl / gơ-rơl (dĩ nhiên chỉ nhấn gơ thôi), sai hẳn với ký âm, thì người ta hiểu ngay, vì có đủ r và l, trong khi đó đọc đúng ký âm là ‘gơ:l’ hay bỏ mất l (gơ) thì họ hoàn toàn không hiểu bạn nói gì; mà có hiểu chăng nữa, thì cũng do context của câu chứ không phải là do bạn đã nói ra từ đó.

– Xóa bỏ kinh nghiệm nghe âm Việt.
Các nguyên âm Việt và Anh không hề giống nhau. Một âm rất rõ trong tiếng Anh sẽ rất nhoè với một lỗ tai người Việt, và một âm rất rõ trong tiếng Việt thì rất nhoè trong lỗ tai người Anh (người bản xứ nói tiếng Anh). Ví dụ: Khi bạn nói: “Her name’s Hương!” Bạn đọc từ Hương thật rõ! Thậm chí la lên thật to và nói thật chậm thì người ấy vẫn không nghe ra. Vì ‘ươ’ đối với họ là âm rất nhoè. Nhưng nói là ‘Hu-ôn-gh(ơ)’ họ nghe rõ ngay; từ đó ta phải hiểu họ khi nói đến cô Huôngh chứ đừng đòi hỏi họ nói tên Hương như người Việt
Tương tư như vậy, không có nguyên âm tiếng Anh nào giống như nguyên âm tiếng Việt. Nếu ta đồng hóa để cho dễ mình, là ta sẽ không nghe được họ nói, vì thế giới này không quan tâm gì đến cách nghe của người Việt Nam đối với ngôn ngữ của họ. Ví dụ: âm ‘a’ trong ‘man’ thì không phải là ‘a’ hay ‘ê’ hay ‘a-ê’ hay ‘ê-a’ tiếng Việt, mà là một âm khác hẳn, không hề có trong tiếng Việt. Phải nghe hàng trăm lần, ngàn lần, thậm chí hàng chục ngàn lần mới nghe đúng âm đó, và rất rõ! Ấy là chưa nói âm ‘a’ trong từ này, được phát âm khác nhau, giữa một cư dân England , Scotland, Massachusetts ,Missouri, Texas!

Cũng thế, âm ‘o’ trong ‘go’ không phải là ‘ô’ Việt Nam, cũng chẳng phải là ô-u (như cách phiên âm xưa) hay ơ-u (như cách phiên âm hiện nay), lại càng không phài là ‘âu’, mà là một âm khác hẳn tiếng Việt. Phát âm là ‘gô’, ‘gơu’ hay ‘gâu’ là nhoè hẳn, và do đó những từ dễ như ‘go’ cũng là vấn đề đối với chúng ta khi nó được nói trong một câu dài, nếu ta không tập nghe âm ‘ô’ của tiếng Anh đúng như họ nói. Một âm nhoè thì không có vấn đề gì, nhưng khi phải nghe một đoạn dài không ngưng nghỉ thì ta sẽ bị rối ngay.

Đây cũng là do một kinh nghiệm tai hại xuất phát từ việc tiếp thu kiến thức. Trong quá trình học các âm tiếng Anh, nhiều khi giáo viên dùng âm Việt để so sánh cho dễ hiểu, rồi mình cứ xem đó là ‘chân lý’ để không thèm nghĩ đến nữa. Ví dụ, muốn phân biệt âm (i) trong sheep và ship, thì giáo viên nói rằng I trong sheep là ‘I dài’ tương tự như I trong tiếng Bắc: ít; còn I trong ship là I ngắn, tương tự như I trong tiếng Nam: ít – ích. Thế là ta cho rằng mình đã nghe được I dài và I ngắn trong tiếng Anh rồi, nhưng thực chất là chưa bao giờ nghe cả! Lối so sánh ấy đã tạo cho chúng ta có một ý niệm sai lầm; thay vì xem đấy là một chỉ dẫn để mình nghe cho đúng âm, thì mình lại tiếp thu một điều sai! Trong tiếng Anh không có âm nào giống âm I bắc hoặc I nam cả! Bằng chứng: ‘eat’ trong tiếng Anh thì hoàn toàn không phải là ‘ít’ trong tiếng Việt, đọc theo giọng bắc, và ‘it’ trong tiếng Anh hoàn toàn không phải là ‘ít’ trong tiếng Việt, đọc theo giọng nam! Vì thế, phải xóa bỏ những kinh nghiệm loại này, và phải nghe trực tiếp thôi!

– Xóa bỏ kinh nghiệm nghe bằng chữ viết.
Nếu ta hỏi một em bé: cháu nghe bằng gì? Thì nó sẽ trả lời: Nghe bằng tai! Nếu ta bảo: “Cháu phải nghe bằng mắt cơ!” Chắc em bé tưởng ta … trêu cháu! Thế nhưng điều xảy ra cho nhiều người học tiếng nước ngoài là Nghe Bằng Mắt!

Thử nhìn lại xem. Trong giai đoạn đầu tiếp xúc với tiếng Anh, khi ta nghe một người nói: “I want a cup of coffee!”. Tức tốc, chúng ta thấy xuất hiện câu ấy dưới dạng chữ Viết trong trí mình, sau đó mình dịch câu ấy ra tiếng Việt, và ta HIỂU! Ta Nghe bằng MẮT, nếu câu ấy không xuất hiện bằng chữ viết trong đầu ta, ta không Thấy nó, thì ta … Điếc!

Sau này, khi ta có trình độ cao hơn, thì ta hiểu ngay lập tức chứ không cần phải suy nghĩ lâu. Thế nhưng tiến trình cũng chẳng khác nhau bao nhiêu, ta vẫn còn thấy chữ xuất hiện và dịch, cái khác biệt ấy là ta viết và dịch rất nhanh, nhưng từ một âm thanh phát ra cho đến khi ta hiểu thì cũng thông qua ba bước: viết, dịch, hiểu. Khi ta đi đến một trình độ nào đó, thì trong giao tiếp không có vấn đề gì cả, vì các câu rất ngắn, và ba bước đó được ‘process’ rất nhanh nên ta không bị trở ngại, nhưng khi ta nghe một bài dài, thì sẽ lòi ra ngay, vì sau hai, ba, bốn câu liên tục ‘processor’ trong đầu ta không còn đủ thì giờ để làm ba công việc đó. Trong lúc nếu một người nói bằng tiếng Việt thì ta nghe và hiểu ngay, không phải viết và dịch (tại vì ngày xưa khi ta học tiếng Việt thì quá trình là nghe thì hiểu ngay, chứ không thông qua viết và dịch, vả lại, nếu muốn dịch, thì dịch ra ngôn ngữ nào?), và người nói có nhanh cách mấy thì cũng không thể nào vượt cái khả năng duy nhất của chúng ta là ‘nghe bằng tai’.

Vì thế, một số sinh viên cảm thấy rằng mình tập nghe, và đã nghe được, nhưng nghe một vài câu thì phải bấm ‘stop’ để một thời gian chết – như computer ngưng mọi sự lại một tí để process khi nhận quá nhiều lệnh – rồi sau đó nghe tiếp; nhưng nếu nghe một diễn giả nói liên tục thì sau vài phút sẽ ‘điếc’. Từ đó, người sinh viên nói rằng mình ‘đã tới trần rồi, không thể nào tiến xa hơn nữa! Vì thế giới này không stop cho ta có giờ hiểu kịp’!’(1)

Từ những nhận xét trên, một trong việc phải làm để nâng cao kỹ năng nghe, ấy xóa bỏ kinh nghiệm Nghe bằng Mắt, mà trở lại giai đoạn Nghe bằng Tai, (hầu hết các du học sinh ở nước ngoài, sau khi làm chủ một ngoại ngữ rồi từ trong nước, đều thấy ‘đau đớn và nhiêu khê’ lắm khi buộc phải bỏ thói quen nghe bằng mắt để trở lại với trạng thái tự nhiên là nghe bằng tai! Có người mất cả 6 tháng cho đến 1 năm mới tàm tạm vượt qua).

– Xóa bỏ kinh nghiệm nghe bằng cấu trúc văn phạm.
Khi nghe ai nói, ta viết một câu vào đầu, và sửa cho đúng văn phạm, rồi mới dịch, và sau đó mới hiểu! Ví dụ. Ta nghe ‘iwanago’ thì viết trong đầu là ‘I want to go’, xong rồi mới dịch và hiểu; nếu chưa viết được như thế, thì iwanago là một âm thanh vô nghĩa.

Thế nhưng, nếu ta nghe lần đầu tiên một người nói một câu hằng ngày: igotago, ta không thể nào viết thành câu được, và vì thế ta không hiểu. Bởi vì thực tế, câu này hoàn toàn sai văn phạm. Một câu đúng văn phạm phải là ‘I am going to go’ hoặc chí ít là ‘I have got to go’. Và như thế, đúng ra thì người nói, dù có nói tốc độ, cũng phải nói hoặc: I’m gona go; hoặc I’ve gota go (tiếng Anh không thể bỏ phụ âm), chứ không thể là I gotta go! Thế nhưng trong thực tế cuộc sống người ta nói như vậy, và hiểu rõ ràng, bất chấp mọi luật văn phạm. Văn phạm xuất phát từ ngôn ngữ sống, chứ không phải ngôn ngữ sống dựa trên luật văn phạm. Do đó, ta cũng phải biết nghe mà hiểu; còn cứ đem văn phạm ra mà tra thì ta sẽ khựng mãi. (Tôi đang nói về kỹ năng nghe, còn làm sao viết một bài cho người khác đọc thì lại là vấn đề khác!)

Tóm lại, trong phần chia sẻ này, tôi chỉ muốn nhắc với ACE rằng, hãy NGHE ĐIỀU NGƯỜI TA NÓI, CHỨ ĐỪNG NGHE ĐIỂU MÌNH MUỐN NGHE, và muốn được như vậy, thì HÃY NGHE BẰNG TAI, ĐỪNG NGHE BẰNG MẮT!

C. Nghe tiếng Anh và ‘nghe’ tiếng Anh:

1. ‘Nghe’ trong ngữ cảnh.
Tôi từng nhắc đi nhắc lại rằng đừng bao giờ tra từ điển khi mình nghe một diễn từ. Điều chủ yếu là nghe và lặp lại được những âm thanh đã nghe, rồi dần dần hiểu được một từ mới, khi nó xuất hiện trong nhiều nội dung khác nhau (nếu cả năm mình mới nghe từ đó một lần, có nghĩa là từ ấy không thông dụng và, trong giai đoạn này, ta không cần phải bận tâm đến nó!). Ví dụ: bạn nghe nhiều lần (âm thanh) ‘oubou’ mà không hiểu nghĩa, lần lượt trong những câu sau:

– To play the ‘oubou’ you need to have strong arms.
– The ‘oubou’ is considered one of the most difficult instruments to play.
– The ‘oubou’ is very difficult to play, because Karen must force air at very high pressure into the tiny double reed.

Lần đầu tiên, bạn chẳng biết âm ‘oubou’ chỉ cái gì, nhưng vì đi với play nên bạn đoán rằng đó là một cái gì để ‘chơi’. Như thế là đã ‘hiểu’ một cách tổng quát. Lần 2, với từ ‘instrument’ bạn biết rằng đó là cái để ‘chơi’ nhưng không phải là trong thể thao, mà là trong âm nhạc. Lần thứ ba, với cụm từ ‘must force air’ thì ta biết rằng đó là một nhạc cụ thổi hơi (khí nhạc) chứ không phải là nhạc cụ dây hay gõ… Và ta tạm hiểu như thế, mà không cần biết phải viết thế nào, cho đến khi đọc câu sau (chẳng hạn):
The oboe looks very similar to the clarinet, but sounds very different!
Thế là ta biết được rõ ràng đó là một nhạc khí tương tự như clarinet, và từ mà ta nghe là ‘oubou’ thì được viết là oboe (và ta đọc đúng ngay chứ không cần phải tra từ điển!)

Ps: Đây cũng là vấn đề ‘hiểu’ một từ. Chúng ta có cảm giác rằng nếu dịch được tiếng ấy ra là ta hiểu ngay, thế nhưng không có gì sai cho bằng. Nếu bạn học theo quá trình ngược, nghĩa là khởi sự biết từ ấy dưới dạng chữ viết, bạn sẽ tra từ điển và đọc là: kèn ô-boa! Bạn thấy hài lòng vì mình đã hiểu! Nhưng thực ra, nếu bạn không phải là một nhạc sĩ, thì ‘kèn ô-boa’ cũng chẳng thêm gì trong kiến thức bạn. Ngay trong tiếng mẹ đẻ, ta có thể hài lòng với khái niệm mơ hồ về một từ, nhưng khi học ngoại ngữ thì ta có cái cảm giác sai lầm là phải trở lại với từ mẹ đẻ mới gọi là hiểu. Đối với tôi, nightingale là một loại chim có tiếng hót hay và thường hót vào ban đêm, còn có dịch ra là ‘sơn ca’ hay ‘họa mi’ thì cũng bằng thừa, vì tôi chưa bao giờ thấy và biết chim ‘sơn ca’ hay ‘họa mi’. Thậm chí không biết là có phải một loài chim hay hai loài chim khác nhau, vì cả hai từ đều được dịch là nightingale.

2. Nghe trong toàn bộ bối cảnh.
Ta thường nghĩ rằng: ‘một từ thì có một nghĩa nhất định’. Hoàn toàn sai.
– Thử tra từ ‘tiêu cực’ trong từ điển: negative. Như thế, ‘một cán bộ tiêu cực’ phải được dịch là ‘a negative cadre’! Nếu cụm từ tiếng Việt có ý nghĩa rõ ràng thì cụm từ dịch ra tiếng Anh (như trên) là hoàn toàn vô nghĩa! Nói cách khác: khi người Anh nói ‘negative’, thì người Việt hiểu là ‘tiêu cực’; nhưng khi người Việt nói ‘tiêu cực’, thì người Anh không thể hiểu là ‘negative.’

– Từ đó ta không thể nào hiểu đúng nghĩa một từ tiếng Anh nếu không đặt vào trong bối cảnh của nó. Ví dụ: nếu không để ý rằng câu chuyện xảy ra ở Anh hay ở Mỹ, thì khi nghe từ corn ta có thể hiểu sai: Ở Anh là lúa mì, và ở Mỹ là bắp!

Nếu thấy một người mở nắp bình xăng lên mà nói ‘Oh my! No more gas’ thì ta hiểu ngay rằng ‘gas’ chính là ‘xăng’, mặc dù trước đó mình có thể học: petrol hay gasoline mới là xăng, còn gas có nghĩa là khí đốt!

Mà nhiều khi bối cảnh rõ đến nỗi, người ta dùng một từ sai mình cũng hiểu đúng. Bạn cứ thử đến cây xăng, mở bình và nói: đổ cho tôi 30.000 dầu! Tôi cam đoan là người ta không thắc mắc gì cả và sẽ đổ XĂNG chứ không đổ DẦU vào xe bạn; cao lắm là trong 100 lần, thì một lần người ta nhắc lại: đổ xăng phải không? Bạn nói là Dầu người ta vẫn hiểu là Xăng. Và trong tiếng Anh cũng thế! Bạn sẽ hiểu một từ trong toàn bộ bối cảnh của nó.

3. Nghe với tất cả giai điệu của câu.

Trong phần đầu tôi nói rằng khi ‘nghe’ một câu, chủ yếu là làm sao nắm bắt được thông tin của chuỗi âm thanh ấy. Nói cách khác, ngôn ngữ có nhiệm vụ là truyền tin. Nhưng ngoài nhiệm vụ truyền tin thì còn một nhiệm vụ thứ hai, vô cùng quan trọng, ấy là nhiệm vụ truyền cảm (truyền một tình cảm). Một câu nói giao tiếp hằng ngày, luôn chuyển tải một phần của thất tình (= bảy tình cảm con người, chứ không phải là bị tình phụ đâu: hỉ, nộ, ai, lạc, ái, ố, dục). Vì thế, cao độ, tốc độ, cường độ của câu nói, trường độ (độ dài) và dấu nhấn của một từ, có thể là điều mình cần phải ‘nghe’ cùng một lúc với các âm thanh được phát ra, thậm chí nghe âm điệu là chính. Nếu không thì ta hiểu sai, hoặc không hiểu gì cả. Đừng tưởng rằng khi ta nghe được từ ‘hate’ là ta hiểu ngay: ghét!
Vì dụ nghe một cô gái nói với một cậu trai: I hate you! Câu này không phải lúc nào cũng là ‘Em ghét anh’! Nói với một ngữ điệu nào đó thì có thể hiểu là: Tôi căm thù anh; hay Thôi, để tôi yên; hay Anh làm tôi bực mình; hoặc trái lại: Anh làm em cảm động quá; thậm chí: Em yêu anh quá chừng chừng!

Và cách nhấn câu cũng thế. Ví dụ trong câu sau đây:
I didn’t say Paul stole my watch!
Nếu người nói nhấn mạnh các từ theo 7 cách khác nhau, mỗi cách nhấn một từ ( I – didn’t – say – Paul – stole – my – watch ) thì nghĩa sẽ khác nhau hoàn toàn:
I didn’t say Paul stole my watch! (Somebody else said that!)
I didn’t say Paul stole my watch! (No! I didn’t act like that)
I didn’t say Paul stole my watch! (I disclosed by another way, but I didn’t SAY) v.v

Khi học tiếng Việt, chúng ta nghe toàn bộ giai điệu, nên nghe (và nói) đúng cao độ của một từ (đúng các dấu); thế nhưng khi một người nước ngoài học tiếng Việt, chúng ta phải khổ công giải thích cho họ lên giọng, xuống giọng, uốn giọng như thế nào để nói các dấu sắc, huyền, nặng, hỏi – ngã (do học nghe bằng tai nên người Nam và người Trung đồng hóa ? và ~, trong khi người Bắc phân biệt chúng rõ ràng). Vì thế, ngược lại, khi nghe tiếng Anh, cần phải nghe toàn bộ âm điệu để nắm bắt những tình cảm bên dưới câu nói.

Nghe với cả giai điệu, mình sẽ hiểu (và sau này sẽ dùng) những câu hay thành ngữ một cách chính xác như người bản ngữ, mà không cần phải dịch ra. Ví dụ: các câu ngắn như: Oh my God! Look at this! Hoặc No way! Hoặc You’re joking/kidding! Với giọng điệu khác nhau, những câu nói hằng ngày đó có thể được hiểu là một tiếng khen hay chê, thán phục hay thất vọng, bằng lòng hay bất bình, chấp thuận hay từ chối!

Và từ đó, mình sẽ biết đối xử khi dùng tiếng Anh cho đúng nghĩa, chứ không chỉ đúng văn phạm. Ví dụ, khi tiếp một nhân vật quan trọng đến công ty bạn, bạn chuẩn bị nói một câu mời rất trân trọng và đúng nghi thức (formal): Would you please take a seat? Thế nhưng bạn căng thẳng đến độ nói theo một âm điệu nào đó khiến người kia bực mình với bạn (mà bạn không hề biết), vì ngỡ rằng bạn diễu cợt người ta! Thế là hỏng cả một cuộc đàm phán. Thà rằng bạn nói đơn sơ: Sit down! Với một giọng hòa nhã, thái độ tôn trọng, cử chỉ lịch thiệp và nụ cười nồng hậu, thì không ai lầm bạn! Trái lại, nói câu rất formal trên kia, với thái độ căng thẳng và giọng nói cộc lốc (vì sợ nói sai!), thì tai hại hơn nhiều.

4. Nghe với những gì một từ bao hàm.

Ngôn ngữ dùng để truyền tin, nhưng đồng thời cũng truyền cảm. Vì thế, mỗi danh từ vừa chỉ định một cái gì cụ thể (denotation), vừa kèm theo một tình cảm (connotation). Các từ this gentleman, this man, this guy, this rascal đều có một denotation như nhau là một người nam nào đó, nhưng connotation thì hoàn toàn khác; cũng như đối với một người nữ nào đó ta có thể dùng: a lady, a woman, a girl, a whore. Cùng một từ như communism chẳng hạn. Đối với một đảng viên đảng Cộng Sản hay một cảm tình viên, thì từ ấy gợi lên bao nhiêu điều dịu dàng cao đẹp, còn đối với người chống cộng, thì từ ấy gợi lên bao nhiêu điều xấu xa, độc ác! Trong khi denotation của nó chỉ là một triết thuyết như trăm ngàn thuyết thuyết khác, mà dù thích dù không, người ta cũng phải dùng để chỉ định triết thuyết do Karl Marx đề ra! Từ đó, câu nói ‘You’re a communist!’ có thể là một lời khen nồng ấm hoặc là một lời chỉ trích thậm tệ, tùy theo connotation của nó.

Khi học tiếng Anh, muốn nâng cao vốn từ vựng thì ta cố học nhiều từ đồng nghĩa (synonyms). Thế nhưng, không bao giờ có synonyms đích thực cả: chỉ tương đương trong denotation chứ connotation hoàn toàn khác (và cũng vì thế mà không bao giờ có hai từ hoàn toàn có nghĩa giống nhau ở hai ngôn ngữ khác nhau: father/mother không hoàn toàn là cha/mẹ – và daddy/mummy không hoàn toàn là ba/má; vì tình cảm đính kèm với các từ ấy khác hẳn giữa người Việt và người Anh). “Nghe” tiếng Anh, chính là biết nghe những connotations trong các thuật ngữ mình nghe.

Cho đến nay, tôi chỉ đề nghị các bạn nghe tin tức. Nhưng đó là giai đoạn nghe để quen với các âm. Trong giai đoạn ‘nghe’ tiếng Anh này, phải bớt giờ nghe tin tức mà xem phóng sự hoặc các phim truyện. Trên thế giới, các speakers của các chương trình tin tức buộc phải nói với thái độ neutral, nghĩa là không được dùng từ kèm theo tình cảm, và không được xử lý âm điệu để bộc lộ tình cảm của mình, vì thế họ nói rất dễ nghe, nhưng chỉ nghe tin tức thôi thì ta bỏ sót một phần khá chủ yếu trong tiếng Anh.

(Trái lại thông tín viên Việt Nam nhiều khi chưa làm chủ được tình cảm mình trong quá trình đọc một bản tin, và người ta thấy ngay là thông tín viên vui mừng hay bực tức, tán đồng hay bất đồng, với nội dung bản tin mình đọc. Còn người viết bản tin thì dùng những từ có connotation: ví dụ trước kia, khi nói đến một tổng thống Mỹ thì bao giờ cũng là ‘tên Kennedy’ hoặc ‘tên tổng thống Kennedy’. Còn hiện nay thì ‘Ngài tổng thống Bush’, mà ít khi nói một cách trung lập: Tổng Thống G. Bush. Trong khi đó, hầu như không bao giờ nghe trong một bản tin: ‘Cố chủ tịch Hồ Chí Minh’, mà lúc nào cũng là ‘Bác Hồ’. Thuật ngữ ‘Bác Hồ’ mặc nhiện tiềm ẩn một tình yêu thương và kính trọng đến độ cụm từ ‘cố chủ tịch Hồ Chí Minh’, vốn là một cụm từ neutral, lại trở thành một cụm từ ‘thất kính, xem thường’ đối với ‘Chủ tịch Hồ Chí Minh’!)

5. Nghe bằng trái tim để cảm điều họ cảm.

Và cuối cùng, đối với các bạn muốn đi thật sâu vào tiếng Anh, thì có thể phối hợp tất cả các kỹ năng để hiểu những điều tiềm tàng bên dưới ngôn ngữ giao tiếp; và điều này hướng đến cách nghe văn học. Mọi ngôn ngữ đều gợi lên một cái gì đó vượt lên trên từ ngữ. Vì thế, thi ca là một ngôn ngữ đặc biệt. Người Việt nào, dù thích hay không thích, vẫn cảm được ngôn ngữ của thi ca. Do đó, muốn nâng cao kỹ năng ‘nghe’ tiếng Anh của mình thì cần tập nghe những bài thơ. Cho đến nay, khó tìm những bài thơ audio, nhưng không phải là không có. Tập nghe đọc thơ, dần dần, chúng ta sẽ cảm được cái tinh túy của tiếng Anh, từ đó ta cảm được vì sao cùng một tư tưởng mà diễn đạt cách này thì ‘hay’ hơn cách kia. Bấy giờ ta mới có quyền nói: tôi đã ‘nghe’ được tiếng Anh.

Ví dụ, khi muốn người ta cảm nhận tiếng gió mùa thu, thì Xuân Diệu đã sử dụng âm ‘r’ trong bài “Đây Mùa Thu Tới”:
Những luồng run rẩy rung rinh lá

Tương tự như vậy Robert L. Stevenson viết trong The Wind
I saw you toss the kites on high
And blow the birds about the sky;
And all around I heard you pass,
Like ladies’ skirts across the grass..
Tác giả đã làm cho ta cảm được làn gió hiu hiu với các âm ‘r’ và ‘s’ nối tiếp và quyện vào nhau trong câu cuối, kèm với hình ảnh độc đáo của váy các mệnh phụ lướt qua trên cỏ (điều mà người Việt Nam hoàn toàn không có kinh nghiệm, vì mọi nét yêu kiều đều gắn liền với tà áo dài).

Kết luận:

Tôi đã bắt đầu gợi ý nghe tiếng Anh để rồi đi đến vấn đề ‘nghe’ tiếng Anh. Tuy nhiên, tôi lặp lại, những gì tôi nói chỉ là lý thuyết, và không có lý thuyết nào có thế làm cho bạn nghe được tiếng Anh. Cách duy nhất ấy là bạn phải tự mình nghe và rút ra những phương pháp thích hợp với xu hướng, kinh nghiệm và sở thích của mình.

Qua loạt bài này, tôi luôn đả phá cách nghe dựa trên viết và dịch. Thế nhưng, những điều tôi cho là trở ngại, nhiều khi lại có ích cho bạn, vì những thứ ấy không cản trở mà còn giúp bạn những cột móc để bám vào. Vâng. Nếu các bạn thấy việc đọc script, hoặc học từ vựng, hoặc viết thành câu và tra từ điển – như vẫn làm từ trước đến nay – giúp cho bạn nghe và hiểu nhanh hơn thì cứ sử dụng phương pháp của mình. Tôi chỉ nhắc lại một điều này:

Tất cả những trợ giúp đó cũng giống như chiếc phao cho người tập bơi. Khi tập bơi, nhiều người cần có một cái phao để bám vào cho dễ nổi, từ đó bạo dạn xuống nước mà tập bơi. Và không ít người bơi giỏi đã khởi sự như thế. Bạn cũng vậy, có thể những cách nghe từ trước đến giờ (nhìn script – học từ – kiểm tra văn phạm) giúp bạn những cột chắc chắn để bám vào mà nghe. Vậy thì xin nhớ rằng: Chiếc phao giúp cho bạn nổi, nhưng không giúp cho bạn biết bơi. Đến một giai đoạn nào đó, chính chiếc phao lại cản trở bạn và không cho bạn bơi thoải mái.
Hãy vứt cái phao sớm chừng nào hay chừng nấy, nếu không nó trở thành một trở ngại cho bạn khi bạn muốn bơi nhanh và xa.
Hãy vứt những chữ viết khi nghe nói, nhanh chừng nào hay chừng ấy, nếu không chúng sẽ cản trở bạn và bạn không bao giờ thực sự ‘nghe’ được tiếng Anh!

Nguồn: Internet

Posted in English | Leave a comment

>Google Public DNS và OpenDNS

>Ra đời muộn hơn dịch vụ OpenDNS, thế nhưng với danh nghĩa là “con của người khổng lồ”, DNS mới mẻ này của Google có thể làm nên chuyện.
DNS là dịch vụ giúp phân giải tên miền thành địa chỉ IP để xác định vị trí máy chủ cần truy cập. DNS ra đời để thay thế chuỗi IP khó nhớ thành một tên miền ngắn gọn dễ nhớ hơn.
Cũng như OpenDNS, DNS của Google giúp người dùng cải thiện tốc độ truy cập web so với việc sử dụng DNS mặc định của nhà cung cấp dịch vụ Internet.

Những cái hay của Google Public DNS:
– Địa chỉ DNS server rất dễ nhớ, đó là 8.8.8.8 và 8.8.4.4
– Không chuyển sang trang có quảng cáo khi gõ nhầm địa chỉ web như dịch vụ OpenDNS.
– Hệ thống máy chủ DNS mạnh mẽ và bảo đảm về bảo mật.
Với những lý do trên, Google Public DNS thật sự là mối đe dọa lớn đối với OpenDNS – hiện dẫn đầu về dịch vụ DNS miễn phí.

Hướng dẫn cài đặt:
Đối Window XP vào Start > Settings > Control Panel > Network Connections còn với Vista vào Control Panel > Network and Internet > Network and Sharing Center > Manage network connections.
Sau đó nhấn chuột phải vào Local Area Connection hoặc Wireless Network Connection và chọn Properties.
Vào thẻ Networking > Internet Protocol Version 4 (TCP/IPv4) nhấn Properties.
(Với Vista chọn Advanced > thẻ DNS). Kế tiếp chọn Use the following DNS server addresses > Nhập Preferred DNS server: 8.8.8.8, nhập Alternate DNS server: 8.8.4.4.

Google Public DNS 8.8.8.8

Các DNS khác ngoài Google:

  1. OpenDNS: 208.67.222.222 , 208.67.220.220
  2. Norton: 198.153.192.1 , 198.153.194.1

Xem bài giới thiệu OpenDNS

Posted in configuration | Leave a comment