2012-07-24

우클릭 막힘 풀기, Personalized Web

우클릭 막힘을 해제하는 방법으로 자바스크립트를 인젝션 하는 방법과 크롬 확장프로그램을 사용하는 방법, 자바스크립트를 실행하지 않는 방법 등에 대해 글을 작성했었다.
그 중에 Allow-RightClick은 글을 작성한 때에는 괜찮은 확장프로그램이었는데, 이후 시도때도 안가리고 꽤 큼직한 이미지 광고를 인젝션을 해대는 패치가 있어 아쉽게 만들었었다.

크롬 확장프로그램 중 인젝션 프로그램을 한가지 더 소개한다.
전에 소개했던 Javascript Injector라는 확장프로그램은 단순히 자바스크립트를 인젝션 하는 기능만 되었고,
지금 소개하는  Personalized Web 은 태그의 속성별로 태그 삭제, 자바스크립트 인젝션, HTML 인젝션이 가능하다.
기본 설정되어 있는 값으로 속성별로 태그를 삭제해 광고를 차단하는 기능이 저장되어 있다.

전에 포스팅한 방법으로 자바스크립트를 인젝션 해도 우클릭이 풀리지 않는 페이지를 보다보니
JEagleEyeClient.setEnable()을 의심 했으나 아니었고


LayoutTopCommon이라는 자바스크립트가 막고 있었다.
이걸 차단하면, 우클릭은 되나 댓글도 펼쳐지지 않았다.

Personalized Web Option에서 "Add new rule"을 클릭하고,
아래 룰을 입력한다.
---
Rule Name: 네이버, 우클릭 해제
Match URLs: [blog,cafe].naver.com
Removers:
Tag(s): script  Attribute: src   Value: /nversioning/LayoutTop (대소문자 구분 없음)
---


Gmail을 넓게 보고 싶어 우측 광고영역을 태그 삭제로 없애봤다.
--
Rule name: Gmail, 광고 공간 제거
Match URLs: ^https://mail.google.com
Removers:
Tag(s): div   & Attribute: class    & Value: nH adC
Tag(s): div   & Attribute: class    & Value: nH PS


--
Dump rule로 생성한 텍스트 데이터를 아래 첨부한다.
사용은 해당 텍스트를 복사하고, Load rule을 클릭하고 붙여넣기 하면 된다.

네이버, 우클릭 해제
{
    "name":"네이버, 우클릭 해제",
    "urlRegex":"[blog,cafe].naver.com",
    "urlExcludeRegex":"",
    "enabled":true,
    "preserveDocWrite":false,"css":"","html":"","js":"",

    "filters":
    [
        {"tags":"script","attribute":"src","value":"","valueRegex":"/nversioning/LayoutTop"}
    ]
}

Gmail, 광고 공간 제거
{
    "name":"Gmail 광고공간 제거",
    "urlRegex":"^https://mail.google.com",
    "urlExcludeRegex":"",
    "enabled":true,
    "preserveDocWrite":false,"css":"","html":"","js":"",

    "filters":
    [
        {"tags":"div","attribute":"class","value":"nH adC","valueRegex":""},
        {"tags":"div","attribute":"class","value":"nH PS" ,"valueRegex":""}
    ]
}

우클릭을 막는 사람은 그 나름의 이유와 정당함을 가지고 있을 것이고.. 우클릭 방지를 반대하는 사람도 추구하는 방향이 있을 것이다.. 나는 우클릭 방지를 반대하는 입장이지만, 어느 한쪽이 옳다고 하기는 힘들다. 내 것이라는 지식, 내 것이라 올린 사진은 진정 내 것인가 진정 보호해야할 지적재산과 공동의 발전을 방해하는 무분별한 행위를 구별해야 한다.

2012-07-11

C#, 크로스 스레드 작업이 잘못되었습니다.

방법: 스레드로부터 안전한 방식으로 Windows Forms 컨트롤 호출(참조: http://msdn.microsoft.com/ko-kr/library/ms171728.aspx)

InvalidOperationException
크로스 스레드 작업이 잘못되었습니다. 'textBox1' 컨트롤이 자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다.

다른 스레드에서 컨트롤에 접근하려 할 때, 예외가 발생한다.
이 예외는 릴리즈 모드에서는 나타나지 않고, 디버그 모드에서만 나타난다고 한다.
이 예외를 무시하거나, Invoke하는 방법으로 크로스 스레드 작업을 가능하게 할 수 있다.

무시하는 방법은 아래 코드를 삽입하면 된다.

CheckForIllegalCrossThreadCalls = false;

2012-07-06

C# DBAdapter.Update(), "INSERT INTO 오류"


DB에 액세스 하는 방법에 대해 공부를 하던 중, MS Access로 DB를 만들고 DBAdapter와 DataSet을 이용해 간단하게 데이터를 보여주고 업데이트하고 수정하는 것까지는 할 수 있다고 생각했는데,
어떤 DB에서는 DBAdapter.Update() 메쏘드로 Insert 때에 "INSERT INTO 오류"가 났다.
직접 필드를 추가한 DB에서는 정상 작동하고, 꼭 엑셀파일로 필드와 데이터를 추출한 DB만 오류가 있었다.

키값, Null허용, 필드의 디자인이 어떻게 되있는지 모두 확인 했지만 답을 못찼고 있었는데
답은 필드의 이름에 공백이었다.
"날 짜"를 "날짜"로 변경하니 정상적으로 INSERT 되었다.

2012-06-28

C# 텍스트파일을 읽어서 2차원 배열로 만들기

성능 데이터가 기록된 텍스트 파일을 열어서 엑셀에 붙여넣기 하기 위해 만듬.

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
namespace automating_system_report
{
    #region RAWDATASTRUCT
    public class RAWDATASTRUCT
    {
        public int col, row;      // FieldValue가 있던, raw 파일 내에서의 위치
        public string FieldValue; // rawData 하나의 값
    }
    #endregion /RAWDATASTRUCT

    #region RawDataLOADER
    /// 
    /// XML에 추가할 RAWDATA를 로드하고, list에 등록하는 클래스
    /// fieldDelimiter의 값에 따라 필드구분을 하려고 했으나, 기본값 " "으로만 동작.
    /// 
    class RawDATALoader:FileManager
    {
        #region public Member
        public string filedDelimiter = " ";//텍스트파일의 필드구분자, 기본값 spacebar 를 필드 구분으로 함.
        public List rawdataList = new List();

        #endregion /public Member

        #region public Method
        public bool Load(string filename) //
        {
            FullPath = filename; 
            if (ExistFile)
            {
                FileStream fs = File.OpenRead(filename);
                StreamReader sr = new StreamReader(fs);
                int row = 0;// 줄 수
                while (sr.Peek() > -1) //한줄 한줄 배열에 저장
                {
                    SaveToList(sr.ReadLine(), row); 
                    row ++;
                }
                sr.Close();
                fs.Close();
                return true;
            }
            return false;
        }
        public string[,] To2DArray()
        {
            int SizeCol = rawdataList[rawdataList.Count - 1].col;
            int SizeRow = rawdataList[rawdataList.Count - 1].row;
            string[,] rtnArray = new string[SizeRow + 1, SizeCol + 1];
            int i = 0;
            foreach (RAWDATASTRUCT r in rawdataList)
            {
                rtnArray[r.row, r.col] = r.FieldValue;
            }
            return rtnArray;
        }
        #endregion /public Method

        #region private Method
        private bool SaveToList(string buf,int row)
        {
            int whereIsDelimiter = 0; //필드구분자의 문자열 내에서 위치
            int col = 0; // 필드 순번..
            string cropElement;
            buf=buf.Trim(); //앞이나 뒤에서 공백을 필드로 오인하는 것을 방지하기 위해 앞뒤 공백 삭제

            try
            {
                do
                {
                    whereIsDelimiter = buf.IndexOf(filedDelimiter);  //맨 왼쪽 필드 한 개의 길이를 찾기 위해,공백을 찾음.
                    if (whereIsDelimiter > -1) //공백을 찾은 경우
                    {
                        cropElement = buf.Substring(0, whereIsDelimiter); // 찾은 단일 필드를 저장하기 위해 임시로 변수에 저장
                        buf = buf.Remove(0, whereIsDelimiter); //다음 반복을 위해 buf에서 크롭한 부분 제거
                    }
                    else//공백을 못찾은 마지막 필드인 경우
                    {
                        cropElement = buf;
                    }

                    RAWDATASTRUCT fieldAdd = new RAWDATASTRUCT(); //crop한 필드를 저장하기 위해 임시 RAWDATASTRUCT를 만듬.
                    fieldAdd.FieldValue = cropElement;
                    fieldAdd.row = row; //텍스트 문서상의 줄 위치, 2차원 배열 생성시 사용됨
                    fieldAdd.col = col; //컬럼값, 2차원 배열 생성시 사용됨
                    rawdataList.Add(fieldAdd);//crop한 필드를 리스트에 저장
                    buf = buf.TrimStart();              //문자열 앞의 의미없는 공백제거
                    col += 1;

                } while (buf != null & whereIsDelimiter > -1); //buf가 null일 때까지, 더 이상 필드가 없을 때까지 반복.
                return true;
            }
            catch (Exception e) 
            {
                MessageBox.Show(e.Message);
                return false;
            }
        }
        #endregion /private Method
    }
    #endregion /RawDataLOADER
}
//

2012-06-27

C# 문자열의 yy, mm, dd를 지정한 날짜데이터의 숫자로 변환하기

파일을 날짜별로 생성해야 해서 만들었다.

public string ConvertDateInString(string filenameFormat, DateTime targetdate)

string filenameFormat에 "yymmdd_파일이름_yymmdd-1.xlsx"를  넘겨주면,
targetdate의 년월일의 숫자데이터로 변경한다.
return string은 변경된 이름이다.
(소문자 yy, mm, dd 또는 yyyy만 인식한다.)

 
/// 지정한 날짜 데이터의 숫자로 yy, mm ,dd 또는 yyyy를 replace 함.
/// 
using System;

namespace automating_system_report
{
    class DateStringConverter
    {
        #region global var
        FindNumberInString fn = new FindNumberInString(); // source에서 숫자 부분을 검출,  +나 - 기호의 뒤에 숫자가 위치하면, 날짜 데이터에 가감하기 위해 선언
        #endregion global var

        /// 
        /// filenameFormat을 yy, dd, mm의 해당 문자열을 targetdate의 날짜 데이터로 바꿈
        /// 파라미터 설명은 2012년 6월 26일을 예로 함.
        /// 
        /// 
ex) yyyymmdd점검일지yy-mm-dd-1.xlsx
        /// 
ex)날짜 데이터(2012-06-26)
        /// ex) 20120626점검일지12-06-25.xlsx
        public string ConvertDateInString(string filenameFormat, DateTime targetdate)
        {
            fn.FindNumber(filenameFormat);
            DateTime convertedDate=targetdate;

            filenameFormat = RecursiveReplaceDate(filenameFormat, "dd", ref targetdate); //filenameFormat의 dd부분을 days로 변경
            filenameFormat = RecursiveReplaceDate(filenameFormat, "mm", ref targetdate); //filenameFormat의 mm부분을 months로 변경
            if(filenameFormat.LastIndexOf("yyyy")>-1)
                filenameFormat = RecursiveReplaceDate(filenameFormat, "yyyy", ref targetdate); //filenameFormat의 yyyy부분을 years로 변경
            else if(filenameFormat.LastIndexOf("yy")>-1)
                filenameFormat = RecursiveReplaceDate(filenameFormat, "yy", ref targetdate); //filenameFormat의 yy부분을 years로 변경
            
            if ((filenameFormat.IndexOf("yy")>-1) ||(filenameFormat.IndexOf("mm")>-1) ||(filenameFormat.IndexOf("dd")>-1) )
            {
                filenameFormat=ConvertDateInString(filenameFormat,targetdate);
            }
            return filenameFormat;
        }
        public string RecursiveReplaceDate(string source, string repStr, ref DateTime convertedDate)
        {
            int whereIsrepStr=-1;  // repStr이 있는 위치를 저장할 변수
            int adjustLocPredication=-1; // repStr뒤에 +나 -로 조정할 기호가 있을 위치를 비교하기 위한 변수
            int adjustVal=0;  // +나 -로 조정할 기호가 있다면 조정할 수치
            int adjustLength=0; // +나 - 기호부터 ~ 수치까지 길이
            string dating=""; //년월일에 변경할 숫자 문자.
            string prestr; //숫자로 변경할 날짜부분의 앞
            string poststr;//숫자로 변경할 날짜부분의 뒤
            DateTime convertedDate;// targetdate에서 +,-로 변경한 날짜데이터.
            try
            {
                whereIsrepStr = source.LastIndexOf(repStr); //뒤에서부터 repStr을 검색, 위치를 기억
            }
            catch { whereIsrepStr = -1; } //repStr을 source문자열에서 못찾을 경우

            if (whereIsrepStr > -1)// 바꿀 대상인 repStr이 문자열에 있으면, 숫자로 변환하기 위해 아래를 수행
            {
                adjustLocPredication = whereIsrepStr + repStr.Length; //adjustLocPredication는 문자열에서 repStr위치한 다음 칸

                // 먼저 repStr뒤에 +나 - 기호의 조정자가 있는지 검색
                foreach (FindNumberInString.NumberInStringSTRUCT n in fn.ListNumber) //filenameFormat의 숫자의 값과 위치를 담고 있는 ListNumber를 foreach
                {
                    //Trace.WriteLine(n.StartIndex);
                    if (n.StartIndex == adjustLocPredication + 1) //foreach수행한 요소마다 위치가 +, - 기호 뒤에 위치하는지 비교
                    {                                             //(+,-기호 위치 바로 뒤에 오는 숫자는 날짜데이터에서 변경할 값으로 인식)
                        adjustVal = Int32.Parse(n.NumberString); //adjustVal은 날짜에서 변경할 값
                        // +기호인지 -기호인지 확인
                        char[] sign = source.ToCharArray();
                        if (sign[adjustLocPredication] == '-')
                        {
                            adjustVal *= (-1); //음수
                            adjustLength=n.Length+1;
                        }
                        else if (sign[adjustLocPredication ] == '+')
                        {
                            adjustLength=n.Length+1;
                        }
                        else { adjustVal = 0; } // + , - 기호가 없으면 날짜에서 변경할 값이 아닌 일반 숫자로 받아들임
                    }
                }
                switch (repStr) //repStr의 종류에 따라 위에서 찾은 adjustVal만큼 조정후, 년월일에 해당하는 문자열을 substring
                {
                            case "dd":
                                convertedDate = targetdate.AddDays(adjustVal);
                                dating = convertedDate.Date.ToString().Substring(8, 2);

                                break;
                            case "mm":
                                convertedDate = targetdate.AddMonths(adjustVal);
                                dating = convertedDate.Date.ToString().Substring(5, 2);

                                break;
                            case "yyyy":
                                convertedDate = targetdate.AddYears(adjustVal);
                                dating=convertedDate.Date.ToString().Substring(0,4);

                                break;
                            case "yy":
                                convertedDate= targetdate.AddYears(adjustVal);
                                dating=convertedDate.Date.ToString().Substring(2,2);
                                break;
                }
                if (dating!="")
                {
                     prestr = source.Substring(0, whereIsrepStr); //변경할 문자열을 제외한 앞부분
                     poststr = source.Substring(whereIsrepStr + repStr.Length + adjustLength);//변경할 문자열을 제외한 뒷부분
                     source = prestr + dating + poststr;//앞부분 + 날짜문자열 + 뒷부분을 다시 source에 저장
                }
                
            }
            return source;
        }
    }
}
//